diff options
author | Adrian Jamróz | 2013-07-13 18:59:07 +0200 |
---|---|---|
committer | Michael Brown | 2013-07-15 11:25:51 +0200 |
commit | 4fabc0012ac69c3a333a192ab97c790bed18b6e1 (patch) | |
tree | 39ee94b1c90fd0b2b0200bb63fc472b1025393b9 | |
parent | [script] Allow for backslash continuation of script lines (diff) | |
download | ipxe-4fabc0012ac69c3a333a192ab97c790bed18b6e1.tar.gz ipxe-4fabc0012ac69c3a333a192ab97c790bed18b6e1.tar.xz ipxe-4fabc0012ac69c3a333a192ab97c790bed18b6e1.zip |
[velocity] Rewrite VIA Velocity driver
Signed-off-by: Adrian Jamróz <adrian.jamroz@gmail.com>
Modified-by: Thomas Miletich <thomas.miletich@gmail.com>
Signed-off-by: Thomas Miletich <thomas.miletich@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/drivers/net/velocity.c | 807 | ||||
-rw-r--r-- | src/drivers/net/velocity.h | 356 | ||||
-rw-r--r-- | src/drivers/net/via-velocity.c | 1927 | ||||
-rw-r--r-- | src/drivers/net/via-velocity.h | 1932 | ||||
-rw-r--r-- | src/include/ipxe/errfile.h | 2 |
5 files changed, 1164 insertions, 3860 deletions
diff --git a/src/drivers/net/velocity.c b/src/drivers/net/velocity.c new file mode 100644 index 00000000..6d518520 --- /dev/null +++ b/src/drivers/net/velocity.c @@ -0,0 +1,807 @@ +/* + * Copyright (C) 2012 Adrian Jamróz <adrian.jamroz@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <byteswap.h> +#include <ipxe/netdevice.h> +#include <ipxe/ethernet.h> +#include <ipxe/if_ether.h> +#include <ipxe/iobuf.h> +#include <ipxe/malloc.h> +#include <ipxe/pci.h> +#include <ipxe/mii.h> +#include "velocity.h" + +#define velocity_setbit(_reg, _mask) writeb ( readb ( _reg ) | _mask, _reg ) +#define virt_to_le32bus(x) ( cpu_to_le32 ( virt_to_bus ( x ) ) ) + +/** @file + * + * VIA Velocity network driver + * + */ + +/****************************************************************************** + * + * MII interface + * + ****************************************************************************** + */ + +/** + * Stop MII auto-polling + * + * @v vlc Velocity device + * @ret rc Return status code + */ +static int velocity_autopoll_stop ( struct velocity_nic *vlc ) { + int timeout = VELOCITY_TIMEOUT_US; + + /* Disable MII auto polling */ + writeb ( 0, vlc->regs + VELOCITY_MIICR ); + + /* Wait for disabling to take effect */ + while ( timeout-- ) { + udelay ( 1 ); + if ( readb ( vlc->regs + VELOCITY_MIISR ) & + VELOCITY_MIISR_IDLE ) + return 0; + } + + DBGC ( vlc, "MII autopoll stop timeout\n" ); + return -ETIMEDOUT; +} + +/** + * Start MII auto-polling + * + * @v vlc Velocity device + * @ret rc Return status code + */ +static int velocity_autopoll_start ( struct velocity_nic *vlc ) { + int timeout = VELOCITY_TIMEOUT_US; + + /* Enable MII auto polling */ + writeb ( VELOCITY_MIICR_MAUTO, vlc->regs + VELOCITY_MIICR ); + + /* Wait for enabling to take effect */ + while ( timeout-- ) { + udelay ( 1 ); + if ( ( readb ( vlc->regs + VELOCITY_MIISR ) & + VELOCITY_MIISR_IDLE ) == 0 ) + return 0; + } + + DBGC ( vlc, "MII autopoll start timeout\n" ); + return -ETIMEDOUT; +} + +/** + * Read from MII register + * + * @v mii MII interface + * @v reg Register address + * @ret value Data read, or negative error + */ +static int velocity_mii_read ( struct mii_interface *mii, unsigned int reg ) { + struct velocity_nic *vlc = + container_of ( mii, struct velocity_nic, mii ); + int timeout = VELOCITY_TIMEOUT_US; + int result; + + DBGC2 ( vlc, "VELOCITY %p MII read reg %d\n", vlc, reg ); + + /* Disable autopolling before we can access MII */ + velocity_autopoll_stop ( vlc ); + + /* Send read command and address */ + writeb ( reg, vlc->regs + VELOCITY_MIIADDR ); + velocity_setbit ( vlc->regs + VELOCITY_MIICR, VELOCITY_MIICR_RCMD ); + + /* Wait for read to complete */ + while ( timeout-- ) { + udelay ( 1 ); + if ( ( readb ( vlc->regs + VELOCITY_MIICR ) & + VELOCITY_MIICR_RCMD ) == 0 ) { + result = readw ( vlc->regs + VELOCITY_MIIDATA ); + velocity_autopoll_start ( vlc ); + return result; + } + } + + /* Restart autopolling */ + velocity_autopoll_start ( vlc ); + + DBGC ( vlc, "MII read timeout\n" ); + return -ETIMEDOUT; +} + +/** + * Write to MII register + * + * @v mii MII interface + * @v reg Register address + * @v data Data to write + * @ret rc Return status code + */ +static int velocity_mii_write ( struct mii_interface *mii, unsigned int reg, + unsigned int data) { + struct velocity_nic *vlc = + container_of ( mii, struct velocity_nic, mii ); + int timeout = VELOCITY_TIMEOUT_US; + + DBGC2 ( vlc, "VELOCITY %p MII write reg %d data 0x%04x\n", + vlc, reg, data ); + + /* Disable autopolling before we can access MII */ + velocity_autopoll_stop ( vlc ); + + /* Send write command, data and destination register */ + writeb ( reg, vlc->regs + VELOCITY_MIIADDR ); + writew ( data, vlc->regs + VELOCITY_MIIDATA ); + velocity_setbit ( vlc->regs + VELOCITY_MIICR, VELOCITY_MIICR_WCMD ); + + /* Wait for write to complete */ + while ( timeout-- ) { + udelay ( 1 ); + if ( ( readb ( vlc->regs + VELOCITY_MIICR ) & + VELOCITY_MIICR_WCMD ) == 0 ) { + velocity_autopoll_start ( vlc ); + return 0; + } + } + + /* Restart autopolling */ + velocity_autopoll_start ( vlc ); + + DBGC ( vlc, "MII write timeout\n" ); + return -ETIMEDOUT; +} + +/** Velocity MII operations */ +static struct mii_operations velocity_mii_operations = { + .read = velocity_mii_read, + .write = velocity_mii_write, +}; + +/** + * Set Link speed + * + * @v vlc Velocity device + */ +static void velocity_set_link ( struct velocity_nic *vlc ) { + int tmp; + + /* Advertise 1000MBit */ + tmp = velocity_mii_read ( &vlc->mii, MII_CTRL1000 ); + tmp |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; + velocity_mii_write ( &vlc->mii, MII_CTRL1000, tmp ); + + /* Enable GBit operation in MII Control Register */ + tmp = velocity_mii_read ( &vlc->mii, MII_BMCR ); + tmp |= BMCR_SPEED1000; + velocity_mii_write ( &vlc->mii, MII_BMCR, tmp ); +} + +/****************************************************************************** + * + * Device reset + * + ****************************************************************************** + */ + +/** + * Reload eeprom contents + * + * @v vlc Velocity device + */ +static int velocity_reload_eeprom ( struct velocity_nic *vlc ) { + int timeout = VELOCITY_TIMEOUT_US; + + /* Initiate reload */ + velocity_setbit ( vlc->regs + VELOCITY_EECSR, VELOCITY_EECSR_RELOAD ); + + /* Wait for reload to complete */ + while ( timeout-- ) { + udelay ( 1 ); + if ( ( readb ( vlc->regs + VELOCITY_EECSR ) & + VELOCITY_EECSR_RELOAD ) == 0 ) + return 0; + } + + DBGC ( vlc, "VELOCITY %p EEPROM reload timeout\n", vlc ); + return -ETIMEDOUT; +} + +/** + * Reset hardware + * + * @v vlc Velocity device + * @ret rc Return status code + */ +static int velocity_reset ( struct velocity_nic *vlc ) { + int timeout = VELOCITY_TIMEOUT_US; + uint8_t tmp; + + DBGC ( vlc, "VELOCITY %p reset\n", vlc ); + + /* clear sticky Power state bits */ + tmp = readb ( vlc->regs + VELOCITY_STICKY ); + tmp &= ~( VELOCITY_STICKY_DS0 | VELOCITY_STICKY_DS1 ); + writeb ( tmp, vlc->regs + VELOCITY_STICKY ); + + /* clear PACPI, which might have been enabled by the EEPROM reload */ + tmp = readb ( vlc->regs + VELOCITY_CFGA ); + tmp &= ~VELOCITY_CFGA_PACPI; + writeb ( tmp, vlc->regs + VELOCITY_CFGA ); + + velocity_setbit ( vlc->regs + VELOCITY_CRS1, VELOCITY_CR1_SFRST ); + + /* Wait for reset to complete */ + while ( timeout-- ) { + udelay ( 1 ); + if ( ( readb ( vlc->regs + VELOCITY_CRS1 ) & + VELOCITY_CR1_SFRST ) == 0 ) + return 0; + } + + return -EINVAL; +} + +/****************************************************************************** + * + * Link state + * + ****************************************************************************** + */ + +/** + * Check link state + * + * @v netdev Network device + */ +static void velocity_check_link ( struct net_device *netdev ) { + struct velocity_nic *vlc = netdev->priv; + + if ( readb ( vlc->regs + VELOCITY_PHYSTS0 ) & VELOCITY_PHYSTS0_LINK ) { + netdev_link_up ( netdev ); + DBGC ( vlc, "VELOCITY %p link up\n", vlc ); + } else { + netdev_link_down ( netdev ); + DBGC ( vlc, "VELOCITY %p link down\n", vlc ); + } + + /* The card disables auto-poll after a link change */ + velocity_autopoll_start ( vlc ); +} + +/****************************************************************************** + * + * Network device interface + * + ****************************************************************************** + */ + +/** + * Allocate descriptor rings + * + * @v vlc Velocity device + * @ret rc Return status code + */ +static int velocity_alloc_rings ( struct velocity_nic *vlc ) { + int rc = 0; + + /* Allocate RX descriptor ring */ + vlc->rx_prod = 0; + vlc->rx_cons = 0; + vlc->rx_commit = 0; + vlc->rx_ring = malloc_dma ( VELOCITY_RXDESC_SIZE, VELOCITY_RING_ALIGN ); + if ( ! vlc->rx_ring ) + return -ENOMEM; + + memset ( vlc->rx_ring, 0, VELOCITY_RXDESC_SIZE ); + + DBGC2 ( vlc, "VELOCITY %p RX ring start address: %p(phys: %#08lx)\n", + vlc, vlc->rx_ring, virt_to_bus ( vlc->rx_ring ) ); + + /* Allocate TX descriptor ring */ + vlc->tx_prod = 0; + vlc->tx_cons = 0; + vlc->tx_ring = malloc_dma ( VELOCITY_TXDESC_SIZE, VELOCITY_RING_ALIGN ); + if ( ! vlc->tx_ring ) { + rc = -ENOMEM; + goto err_tx_alloc; + } + + memset ( vlc->tx_ring, 0, VELOCITY_TXDESC_SIZE ); + + /* Send RX ring to the card */ + writel ( virt_to_bus ( vlc->rx_ring ), + vlc->regs + VELOCITY_RXDESC_ADDR_LO ); + writew ( VELOCITY_RXDESC_NUM - 1, vlc->regs + VELOCITY_RXDESCNUM ); + + /* Send TX ring to the card */ + writel ( virt_to_bus ( vlc->tx_ring ), + vlc->regs + VELOCITY_TXDESC_ADDR_LO0 ); + writew ( VELOCITY_TXDESC_NUM - 1, vlc->regs + VELOCITY_TXDESCNUM ); + + DBGC2 ( vlc, "VELOCITY %p TX ring start address: %p(phys: %#08lx)\n", + vlc, vlc->tx_ring, virt_to_bus ( vlc->tx_ring ) ); + + return 0; + +err_tx_alloc: + free_dma ( vlc->rx_ring, VELOCITY_RXDESC_SIZE ); + return rc; +} + +/** + * Refill receive descriptor ring + * + * @v vlc Velocity device + */ +static void velocity_refill_rx ( struct velocity_nic *vlc ) { + struct velocity_rx_descriptor *desc; + struct io_buffer *iobuf; + int rx_idx, i = 0; + + /* Check for new packets */ + while ( ( vlc->rx_prod - vlc->rx_cons ) < VELOCITY_RXDESC_NUM ) { + iobuf = alloc_iob ( VELOCITY_RX_MAX_LEN ); + + /* Memory pressure: try again next poll */ + if ( ! iobuf ) + break; + + rx_idx = ( vlc->rx_prod++ % VELOCITY_RXDESC_NUM ); + desc = &vlc->rx_ring[rx_idx]; + + /* Set descrptor fields */ + desc->des1 = 0; + desc->addr = virt_to_le32bus ( iobuf-> data ); + desc->des2 = cpu_to_le32 ( + VELOCITY_DES2_SIZE ( VELOCITY_RX_MAX_LEN - 1 ) | + VELOCITY_DES2_IC ); + + vlc->rx_buffs[rx_idx] = iobuf; + i++; + + /* Return RX descriptors in blocks of 4 (hw requirement) */ + if ( rx_idx % 4 == 3 ) { + int j; + for (j = 0; j < 4; j++) { + desc = &vlc->rx_ring[rx_idx - j]; + desc->des0 = cpu_to_le32 ( VELOCITY_DES0_OWN ); + } + vlc->rx_commit += 4; + } + } + + wmb(); + + if ( vlc->rx_commit ) { + writew ( vlc->rx_commit, + vlc->regs + VELOCITY_RXDESC_RESIDUECNT ); + vlc->rx_commit = 0; + } + + if ( i > 0 ) + DBGC2 ( vlc, "VELOCITY %p refilled %d RX descriptors\n", + vlc, i ); +} + +/** + * Open network device + * + * @v netdev Network device + * @ret rc Return status code + */ +static int velocity_open ( struct net_device *netdev ) { + struct velocity_nic *vlc = netdev->priv; + int rc; + + DBGC ( vlc, "VELOCITY %p open\n", vlc ); + DBGC ( vlc, "VELOCITY %p regs at: %p\n", vlc, vlc->regs ); + + /* Allocate descriptor rings */ + if ( ( rc = velocity_alloc_rings ( vlc ) ) != 0 ) + return rc; + + velocity_refill_rx ( vlc ); + + /* Enable TX/RX queue */ + writew ( VELOCITY_TXQCSRS_RUN0, vlc->regs + VELOCITY_TXQCSRS ); + writew ( VELOCITY_RXQCSR_RUN | VELOCITY_RXQCSR_WAK, + vlc->regs + VELOCITY_RXQCSRS ); + + /* Enable interrupts */ + writeb ( 0xff, vlc->regs + VELOCITY_IMR0 ); + writeb ( 0xff, vlc->regs + VELOCITY_IMR1 ); + + /* Start MAC */ + writeb ( VELOCITY_CR0_STOP, vlc->regs + VELOCITY_CRC0 ); + writeb ( VELOCITY_CR1_DPOLL, vlc->regs + VELOCITY_CRC0 ); + writeb ( VELOCITY_CR0_START | VELOCITY_CR0_TXON | VELOCITY_CR0_RXON, + vlc->regs + VELOCITY_CRS0 ); + + /* Receive all packets */ + writeb ( 0xff, vlc->regs + VELOCITY_RCR ); + + /* Set initial link state */ + velocity_check_link ( netdev ); + + velocity_autopoll_start ( vlc ); + + DBGC2 ( vlc, "VELOCITY %p CR3 %02x\n", + vlc, readb ( vlc->regs + 0x0B ) ); + + return 0; +} + +/** + * Close network device + * + * @v netdev Network device + */ +static void velocity_close ( struct net_device *netdev ) { + struct velocity_nic *vlc = netdev->priv; + int i; + + /* Stop NIC */ + writeb ( VELOCITY_CR0_TXON | VELOCITY_CR0_RXON, + vlc->regs + VELOCITY_CRC0 ); + writeb ( VELOCITY_CR0_STOP, vlc->regs + VELOCITY_CRS0 ); + + /* Clear RX ring information */ + writel ( 0, vlc->regs + VELOCITY_RXDESC_ADDR_LO ); + writew ( 0, vlc->regs + VELOCITY_RXDESCNUM ); + + /* Destroy RX ring */ + free_dma ( vlc->rx_ring, VELOCITY_RXDESC_SIZE ); + vlc->rx_ring = NULL; + vlc->rx_prod = 0; + vlc->rx_cons = 0; + + /* Discard receive buffers */ + for ( i = 0 ; i < VELOCITY_RXDESC_NUM ; i++ ) { + if ( vlc->rx_buffs[i] ) + free_iob ( vlc->rx_buffs[i] ); + vlc->rx_buffs[i] = NULL; + } + + /* Clear TX ring information */ + writel ( 0, vlc->regs + VELOCITY_TXDESC_ADDR_LO0 ); + writew ( 0, vlc->regs + VELOCITY_TXDESCNUM ); + + /* Destroy TX ring */ + free_dma ( vlc->tx_ring, VELOCITY_TXDESC_SIZE ); + vlc->tx_ring = NULL; + vlc->tx_prod = 0; + vlc->tx_cons = 0; +} + +/** + * Transmit packet + * + * @v netdev Network device + * @v iobuf I/O buffer + * @ret rc Return status code + */ +static int velocity_transmit ( struct net_device *netdev, + struct io_buffer *iobuf ) { + struct velocity_nic *vlc = netdev->priv; + struct velocity_tx_descriptor *desc; + unsigned int tx_idx; + + /* Pad packet to minimum length */ + iob_pad ( iobuf, ETH_ZLEN ); + + tx_idx = ( vlc->tx_prod++ % VELOCITY_TXDESC_NUM ); + desc = &vlc->tx_ring[tx_idx]; + + /* Set packet size and transfer ownership to NIC */ + desc->des0 = cpu_to_le32 ( VELOCITY_DES0_OWN | + VELOCITY_DES2_SIZE ( iob_len ( iobuf ) ) ); + /* Data in first desc fragment, only desc for packet, generate INT */ + desc->des1 = cpu_to_le32 ( VELOCITY_DES1_FRAG ( 1 ) | + VELOCITY_DES1_TCPLS | + VELOCITY_DES1_INTR ); + + desc->frags[0].addr = virt_to_le32bus ( iobuf->data ); + desc->frags[0].des2 = cpu_to_le32 ( + VELOCITY_DES2_SIZE ( iob_len ( iobuf ) ) ); + + wmb(); + + /* Initiate TX */ + velocity_setbit ( vlc->regs + VELOCITY_TXQCSRS, VELOCITY_TXQCSRS_WAK0 ); + + DBGC2 ( vlc, "VELOCITY %p tx_prod=%d desc=%p iobuf=%p len=%zd\n", + vlc, tx_idx, desc, iobuf->data, iob_len ( iobuf ) ); + + return 0; +} + +/** + * Poll for received packets. + * + * @v vlc Velocity device + */ +static void velocity_poll_rx ( struct velocity_nic *vlc ) { + struct velocity_rx_descriptor *desc; + struct io_buffer *iobuf; + int rx_idx; + size_t len; + uint32_t des0; + + /* Check for packets */ + while ( vlc->rx_cons != vlc->rx_prod ) { + rx_idx = ( vlc->rx_cons % VELOCITY_RXDESC_NUM ); + desc = &vlc->rx_ring[rx_idx]; + + des0 = cpu_to_le32 ( desc->des0 ); + + /* Return if descriptor still in use */ + if ( des0 & VELOCITY_DES0_OWN ) + return; + + iobuf = vlc->rx_buffs[rx_idx]; + + /* Get length, strip CRC */ + len = VELOCITY_DES0_RMBC ( des0 ) - 4; + iob_put ( iobuf, len ); + + DBGC2 ( vlc, "VELOCITY %p got packet on idx=%d (prod=%d), len %zd\n", + vlc, rx_idx, vlc->rx_prod % VELOCITY_RXDESC_NUM, len ); + + if ( des0 & VELOCITY_DES0_RX_ERR ) { + /* Report receive error */ + netdev_rx_err ( vlc->netdev, iobuf, -EINVAL ); + DBGC ( vlc, "VELOCITY %p receive error, status: %02x\n", + vlc, des0 ); + } else if ( des0 & VELOCITY_DES0_RXOK ) { + /* Report receive success */ + netdev_rx( vlc->netdev, iobuf ); + } else { + /* Card indicated neither success nor failure + * Technically this shouldn't happen, but we saw it + * in debugging once. */ + DBGC ( vlc, "VELOCITY %p RX neither ERR nor OK: %04x\n", + vlc, des0 ); + DBGC ( vlc, "packet len: %zd\n", len ); + DBGC_HD ( vlc, iobuf->data, 64 ); + + /* we don't know what it is, treat is as an error */ + netdev_rx_err ( vlc->netdev, iobuf, -EINVAL ); + } + + vlc->rx_cons++; + } +} + +/** + * Poll for completed packets. + * + * @v vlc Velocity device + */ +static void velocity_poll_tx ( struct velocity_nic *vlc ) { + struct velocity_tx_descriptor *desc; + int tx_idx; + + /* Check for packets */ + while ( vlc->tx_cons != vlc->tx_prod ) { + tx_idx = ( vlc->tx_cons % VELOCITY_TXDESC_NUM ); + desc = &vlc->tx_ring[tx_idx]; + + /* Return if descriptor still in use */ + if ( le32_to_cpu ( desc->des0 ) & VELOCITY_DES0_OWN ) + return; + + /* Report errors */ + if ( le32_to_cpu ( desc->des0 ) & VELOCITY_DES0_TERR ) { + netdev_tx_complete_next_err ( vlc->netdev, -EINVAL ); + return; + } + + netdev_tx_complete_next ( vlc->netdev ); + + DBGC2 ( vlc, "VELOCITY %p poll_tx cons=%d prod=%d tsr=%04x\n", + vlc, tx_idx, vlc->tx_prod % VELOCITY_TXDESC_NUM, + ( desc->des0 & 0xffff ) ); + vlc->tx_cons++; + } +} + +/** + * Poll for completed and received packets + * + * @v netdev Network device + */ +static void velocity_poll ( struct net_device *netdev ) { + struct velocity_nic *vlc = netdev->priv; + uint8_t isr1; + + isr1 = readb ( vlc->regs + VELOCITY_ISR1 ); + + /* ACK interrupts */ + writew ( 0xFFFF, vlc->regs + VELOCITY_ISR0 ); + + /* Check for competed packets */ + velocity_poll_rx ( vlc ); + velocity_poll_tx ( vlc ); + + if ( isr1 & VELOCITY_ISR1_SRCI ) { + /* Update linkstate */ + DBGC2 ( vlc, "VELOCITY %p link status interrupt\n", vlc ); + velocity_check_link ( netdev ); + } + + velocity_refill_rx ( vlc ); + + /* deal with potential RX stall caused by RX ring underrun */ + writew ( VELOCITY_RXQCSR_RUN | VELOCITY_RXQCSR_WAK, + vlc->regs + VELOCITY_RXQCSRS ); +} + +/** + * Enable or disable interrupts + * + * @v netdev Network device + * @v enable Interrupts should be enabled + */ +static void velocity_irq ( struct net_device *netdev, int enable ) { + struct velocity_nic *vlc = netdev->priv; + + DBGC ( vlc, "VELOCITY %p interrupts %s\n", vlc, + enable ? "enable" : "disable" ); + + if (enable) { + /* Enable interrupts */ + writeb ( VELOCITY_CR3_GINTMSK1, vlc->regs + VELOCITY_CRS3 ); + } else { + /* Disable interrupts */ + writeb ( VELOCITY_CR3_GINTMSK1, vlc->regs + VELOCITY_CRC3 ); + } +} + +/** Velocity network device operations */ +static struct net_device_operations velocity_operations = { + .open = velocity_open, + .close = velocity_close, + .transmit = velocity_transmit, + .poll = velocity_poll, + .irq = velocity_irq, +}; + +/****************************************************************************** + * + * PCI interface + * + ****************************************************************************** + */ + +/** + * Probe PCI device + * + * @v pci PCI device + * @ret rc Return status code + */ +static int velocity_probe ( struct pci_device *pci ) { + struct net_device *netdev; + struct velocity_nic *vlc; + int rc; + + /* Allocate and initialise net device */ + netdev = alloc_etherdev ( sizeof ( *vlc ) ); + if ( ! netdev ) { + rc = -ENOMEM; + goto err_alloc; + } + netdev_init ( netdev, &velocity_operations ); + vlc = netdev->priv; + pci_set_drvdata ( pci, netdev ); + netdev->dev = &pci->dev; + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Map registers */ + vlc->regs = ioremap ( pci->membase, VELOCITY_BAR_SIZE ); + vlc->netdev = netdev; + + /* Reset the NIC */ + if ( ( rc = velocity_reset ( vlc ) ) != 0 ) + goto err_reset; + + /* Reload EEPROM */ + if ( ( rc = velocity_reload_eeprom ( vlc ) ) != 0 ) + goto err_reset; + + /* Get MAC address */ + netdev->hw_addr[0] = readb ( vlc->regs + VELOCITY_MAC0 ); + netdev->hw_addr[1] = readb ( vlc->regs + VELOCITY_MAC1 ); + netdev->hw_addr[2] = readb ( vlc->regs + VELOCITY_MAC2 ); + netdev->hw_addr[3] = readb ( vlc->regs + VELOCITY_MAC3 ); + netdev->hw_addr[4] = readb ( vlc->regs + VELOCITY_MAC4 ); + netdev->hw_addr[5] = readb ( vlc->regs + VELOCITY_MAC5 ); + + /* Initialise and reset MII interface */ + mii_init ( &vlc->mii, &velocity_mii_operations ); + if ( ( rc = mii_reset ( &vlc->mii ) ) != 0 ) { + DBGC ( vlc, "VELOCITY %p could not reset MII: %s\n", + vlc, strerror ( rc ) ); + goto err_mii_reset; + } + + /* Enable proper link advertising */ + velocity_set_link ( vlc ); + + /* Register network device */ + if ( ( rc = register_netdev ( netdev ) ) != 0 ) + goto err_register_netdev; + + return 0; + + err_register_netdev: + err_mii_reset: + velocity_reset ( vlc ); + err_reset: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void velocity_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct velocity_nic *vlc = netdev->priv; + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset card */ + velocity_reset ( vlc ); + + /* Free network device */ + netdev_nullify ( netdev ); + netdev_put ( netdev ); +} + +/** Velocity PCI device IDs */ +static struct pci_device_id velocity_nics[] = { + PCI_ROM ( 0x1106, 0x3119, "vt6122", "VIA Velocity", 0 ), +}; + +/** Velocity PCI driver */ +struct pci_driver velocity_driver __pci_driver = { + .ids = velocity_nics, + .id_count = ( sizeof ( velocity_nics ) / sizeof ( velocity_nics[0] ) ), + .probe = velocity_probe, + .remove = velocity_remove, +}; diff --git a/src/drivers/net/velocity.h b/src/drivers/net/velocity.h new file mode 100644 index 00000000..04e6a146 --- /dev/null +++ b/src/drivers/net/velocity.h @@ -0,0 +1,356 @@ +#ifndef _VELOCITY_H +#define _VELOCITY_H + +/** @file + * + * VIA Velocity network driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** Skeleton BAR size */ +#define VELOCITY_BAR_SIZE 256 + +/** Default timeout */ +#define VELOCITY_TIMEOUT_US 10 * 1000 + +struct velocity_frag { + uint32_t addr; + uint32_t des2; +} __attribute__ ((packed)); + +/** Velocity descriptor format */ +struct velocity_tx_descriptor { + uint32_t des0; + uint32_t des1; + /* We only use the first fragment, the HW requires us to have 7 */ + struct velocity_frag frags[7]; +} __attribute__ ((packed)); + +struct velocity_rx_descriptor { + uint32_t des0; + uint32_t des1; + uint32_t addr; + uint32_t des2; +} __attribute__ ((packed)); + +#define VELOCITY_DES0_RMBC(_n) (((_n) >> 16) & 0x1fff) +#define VELOCITY_DES0_OWN (1 << 31) +#define VELOCITY_DES0_TERR (1 << 15) +#define VELOCITY_DES0_RXOK (1 << 15) +#define VELOCITY_DES0_FDX (1 << 14) +#define VELOCITY_DES0_GMII (1 << 13) +#define VELOCITY_DES0_LNKFL (1 << 12) +#define VELOCITY_DES0_SHDN (1 << 10) +#define VELOCITY_DES0_CRS (1 << 9) +#define VELOCITY_DES0_CDH (1 << 8) +#define VELOCITY_DES0_ABT (1 << 7) +#define VELOCITY_DES0_OWT (1 << 6) +#define VELOCITY_DES0_OWC (1 << 5) +#define VELOCITY_DES0_COLS (1 << 4) + +#define VELOCITY_DES0_RXSHDN (1 << 30) +#define VELOCITY_DES0_RXER (1 << 5) +#define VELOCITY_DES0_RLE (1 << 4) +#define VELOCITY_DES0_CE (1 << 3) +#define VELOCITY_DES0_FAE (1 << 2) +#define VELOCITY_DES0_CRC (1 << 1) +#define VELOCITY_DES0_RX_ERR ( VELOCITY_DES0_RXER | \ + VELOCITY_DES0_RLE | \ + VELOCITY_DES0_CE | \ + VELOCITY_DES0_FAE | \ + VELOCITY_DES0_CRC ) + +/** TX descriptor fragment number */ +#define VELOCITY_DES1_FRAG(_n) (((_n + 1) & 0xf) << 28) +#define VELOCITY_DES1_TCPLS ((1 << 24) | (1 << 25)) +#define VELOCITY_DES1_INTR (1 << 23) +#define VELOCITY_DES1_PIC (1 << 22) +#define VELOCITY_DES1_VETAG (1 << 21) +#define VELOCITY_DES1_IPCK (1 << 20) +#define VELOCITY_DES1_UDPCK (1 << 19) +#define VELOCITY_DES1_TCPCK (1 << 18) +#define VELOCITY_DES1_JMBO (1 << 17) +#define VELOCITY_DES1_CRC (1 << 16) + +#define VELOCITY_DES2_IC (1 << 31) +#define VELOCITY_DES2_SIZE(_n) (((_n) & 0x1fff) << 16) + +/** Number of receive descriptors + * + * Must be a multiple of 4 (hardware requirement). + */ +#define VELOCITY_RXDESC_NUM 8 +#define VELOCITY_RXDESC_SIZE \ + ( VELOCITY_RXDESC_NUM * sizeof ( struct velocity_rx_descriptor ) ) + +/** Number of transmit descriptors */ +#define VELOCITY_TXDESC_NUM 8 +#define VELOCITY_TXDESC_SIZE \ + ( VELOCITY_TXDESC_NUM * sizeof ( struct velocity_tx_descriptor ) ) + +/** Descriptor alignment */ +#define VELOCITY_RING_ALIGN 64 + +/** Receive buffer length */ +#define VELOCITY_RX_MAX_LEN 1536 + +/** MAC address registers */ +#define VELOCITY_MAC0 0x00 +#define VELOCITY_MAC1 0x01 +#define VELOCITY_MAC2 0x02 +#define VELOCITY_MAC3 0x03 +#define VELOCITY_MAC4 0x04 +#define VELOCITY_MAC5 0x05 + +/** Receive control register */ +#define VELOCITY_RCR 0x06 +#define RHINE_RCR_SYMERR_ACCEPT (1 << 7) /*< Accept symbol error */ +#define RHINE_RCR_FILTER_ACCEPT (1 << 6) /*< Accept based on filter */ +#define RHINE_RCR_LONG_ACCEPT (1 << 5) /*< Accept long packets */ +#define RHINE_RCR_PROMISC (1 << 4) /*< Promiscuous mode */ +#define RHINE_RCR_BCAST_ACCEPT (1 << 3) /*< Accept broadcast */ +#define RHINE_RCR_MCAST_ACCEPT (1 << 2) /*< Accept multicast */ +#define RHINE_RCR_RUNT_ACCEPT (1 << 1) /*< Accept runt frames */ +#define RHINE_RCR_ERR_ACCEPT (1 << 0) /*< Accept erroneous frames */ + +/** Transmit control register */ +#define VELOCITY_TCR 0x07 +#define VELOCITY_TCR_LB0 (1 << 0) /*< Loopback control */ +#define VELOCITY_TCR_LB1 (1 << 1) /*< Loopback control */ +#define VELOCITY_TCR_COLTMC0 (1 << 2) /*< Collision retry control */ +#define VELOCITY_TCR_COLTMC1 (1 << 3) /*< Collision retry control */ + +/** Command register 0 (set) */ +#define VELOCITY_CRS0 0x08 +#define VELOCITY_CR0_TXON (1 << 3) /*< Transmit enable */ +#define VELOCITY_CR0_RXON (1 << 2) /*< Receive enable */ +#define VELOCITY_CR0_STOP (1 << 1) /*< Stop NIC */ +#define VELOCITY_CR0_START (1 << 0) /*< Start NIC */ + +/** Command register 1 (set) */ +#define VELOCITY_CRS1 0x09 +#define VELOCITY_CR1_SFRST (1 << 7) /*< Software reset */ +#define VELOCITY_CR1_TM1EN (1 << 6) /*< Perioding software counting */ +#define VELOCITY_CR1_TM0EN (1 << 5) /*< Single-shot software counting */ +#define VELOCITY_CR1_DPOLL (1 << 3) /*< Disable auto polling */ +#define VELOCITY_CR1_DISAU (1 << 0) /*< Unicast reception disable */ + +/** Command register 2 (set) */ +#define VELOCITY_CRS2 0x0A +#define VELOCITY_CR2_XONEN (1 << 7) /*< XON/XOFF mode enable */ +#define VELOCITY_CR2_FDXTFCEN (1 << 6) /*< FDX flow control TX */ +#define VELOCITY_CR2_FDXRFCEN (1 << 5) +#define VELOCITY_CR2_HDXFCEN (1 << 4) + +/** Command register 3 (set) */ +#define VELOCITY_CRS3 0x0B +#define VELOCITY_CR3_FOSRST (1 << 6) +#define VELOCITY_CR3_FPHYRST (1 << 5) +#define VELOCITY_CR3_DIAG (1 << 4) +#define VELOCITY_CR3_INTPCTL (1 << 2) +#define VELOCITY_CR3_GINTMSK1 (1 << 1) +#define VELOCITY_CR3_SWPEND (1 << 0) + +/** Command register 0 (clear) */ +#define VELOCITY_CRC0 0x0C + +/** Command register 1 (clear) */ +#define VELOCITY_CRC1 0x0D + +/** Command register 2 (clear */ +#define VELOCITY_CRC2 0x0E + +/** Command register 3 (clear */ +#define VELOCITY_CRC3 0x0F +#define VELOCITY_CAM0 0x10 +#define VELOCITY_CAM1 0x11 +#define VELOCITY_CAM2 0x12 +#define VELOCITY_CAM3 0x13 +#define VELOCITY_CAM4 0x14 +#define VELOCITY_CAM5 0x15 +#define VELOCITY_CAM6 0x16 +#define VELOCITY_CAM7 0x17 +#define VELOCITY_TXDESC_HI 0x18 /* Hi part of 64bit txdesc base addr */ +#define VELOCITY_DATABUF_HI 0x1D /* Hi part of 64bit data buffer addr */ +#define VELOCITY_INTCTL0 0x20 /* interrupt control register */ +#define VELOCITY_RXSUPPTHR 0x20 +#define VELOCITY_TXSUPPTHR 0x20 +#define VELOCITY_INTHOLDOFF 0x20 +#define VELOCITY_INTCTL1 0x21 /* interrupt control register */ +#define VELOCITY_TXHOSTERR 0x22 /* TX host error status */ +#define VELOCITY_RXHOSTERR 0x23 /* RX host error status */ + +/** Interrupt status register 0 */ +#define VELOCITY_ISR0 0x24 +#define VELOCITY_ISR0_PTX3 (1 << 7) +#define VELOCITY_ISR0_PTX2 (1 << 6) +#define VELOCITY_ISR0_PTX1 (1 << 5) +#define VELOCITY_ISR0_PTX0 (1 << 4) +#define VELOCITY_ISR0_PTXI (1 << 3) +#define VELOCITY_ISR0_PRXI (1 << 2) +#define VELOCITY_ISR0_PPTXI (1 << 1) +#define VELOCITY_ISR0_PPRXI (1 << 0) + +/** Interrupt status register 1 */ +#define VELOCITY_ISR1 0x25 +#define VELOCITY_ISR1_SRCI (1 << 7) +#define VELOCITY_ISR1_LSTPEI (1 << 6) +#define VELOCITY_ISR1_LSTEI (1 << 5) +#define VELOCITY_ISR1_OVFL (1 << 4) +#define VELOCITY_ISR1_FLONI (1 << 3) +#define VELOCITY_ISR1_RACEI (1 << 2) + +/** Interrupt status register 2 */ +#define VELOCITY_ISR2 0x26 +#define VELOCITY_ISR2_HFLD (1 << 7) +#define VELOCITY_ISR2_UDPI (1 << 6) +#define VELOCITY_ISR2_MIBFI (1 << 5) +#define VELOCITY_ISR2_SHDNII (1 << 4) +#define VELOCITY_ISR2_PHYI (1 << 3) +#define VELOCITY_ISR2_PWEI (1 << 2) +#define VELOCITY_ISR2_TMR1I (1 << 1) +#define VELOCITY_ISR2_TMR0I (1 << 0) + +/** Interrupt status register 3 */ +#define VELOCITY_ISR3 0x27 + +/** Interrupt mask register 0 */ +#define VELOCITY_IMR0 0x28 + +/** Interrupt mask register 1 */ +#define VELOCITY_IMR1 0x29 + +/** Interrupt mask register 2 */ +#define VELOCITY_IMR2 0x2a + +/** Interrupt mask register 3 */ +#define VELOCITY_IMR3 0x2b + +#define VELOCITY_TXSTS_PORT 0x2C /* Transmit status port (???) */ +#define VELOCITY_TXQCSRS 0x30 /* TX queue ctl/status set */ + +#define VELOCITY_TXQCSRS_DEAD3 (1 << 15) +#define VELOCITY_TXQCSRS_WAK3 (1 << 14) +#define VELOCITY_TXQCSRS_ACT3 (1 << 13) +#define VELOCITY_TXQCSRS_RUN3 (1 << 12) +#define VELOCITY_TXQCSRS_DEAD2 (1 << 11) +#define VELOCITY_TXQCSRS_WAK2 (1 << 10) +#define VELOCITY_TXQCSRS_ACT2 (1 << 9) +#define VELOCITY_TXQCSRS_RUN2 (1 << 8) +#define VELOCITY_TXQCSRS_DEAD1 (1 << 7) +#define VELOCITY_TXQCSRS_WAK1 (1 << 6) +#define VELOCITY_TXQCSRS_ACT1 (1 << 5) +#define VELOCITY_TXQCSRS_RUN1 (1 << 4) +#define VELOCITY_TXQCSRS_DEAD0 (1 << 3) +#define VELOCITY_TXQCSRS_WAK0 (1 << 2) +#define VELOCITY_TXQCSRS_ACT0 (1 << 1) +#define VELOCITY_TXQCSRS_RUN0 (1 << 0) + +#define VELOCITY_RXQCSRS 0x32 /* RX queue ctl/status set */ +#define VELOCITY_RXQCSRC 0x36 + +#define VELOCITY_RXQCSR_DEAD (1 << 3) +#define VELOCITY_RXQCSR_WAK (1 << 2) +#define VELOCITY_RXQCSR_ACT (1 << 1) +#define VELOCITY_RXQCSR_RUN (1 << 0) + +#define VELOCITY_TXQCSRC 0x34 /* TX queue ctl/status clear */ +#define VELOCITY_RXQCSRC 0x36 /* RX queue ctl/status clear */ +#define VELOCITY_RXDESC_ADDR_LO 0x38 /* RX desc base addr (lo 32 bits) */ +#define VELOCITY_RXDESC_CONSIDX 0x3C /* Current RX descriptor index */ +#define VELOCITY_TXQTIMER 0x3E /* TX queue timer pend register */ +#define VELOCITY_RXQTIMER 0x3F /* RX queue timer pend register */ +#define VELOCITY_TXDESC_ADDR_LO0 0x40 /* TX desc0 base addr (lo 32 bits) */ +#define VELOCITY_TXDESC_ADDR_LO1 0x44 /* TX desc1 base addr (lo 32 bits) */ +#define VELOCITY_TXDESC_ADDR_LO2 0x48 /* TX desc2 base addr (lo 32 bits) */ +#define VELOCITY_TXDESC_ADDR_LO3 0x4C /* TX desc3 base addr (lo 32 bits) */ +#define VELOCITY_RXDESCNUM 0x50 /* Size of RX desc ring */ +#define VELOCITY_TXDESCNUM 0x52 /* Size of TX desc ring */ +#define VELOCITY_TXDESC_CONSIDX0 0x54 /* Current TX descriptor index */ +#define VELOCITY_TXDESC_CONSIDX1 0x56 /* Current TX descriptor index */ +#define VELOCITY_TXDESC_CONSIDX2 0x58 /* Current TX descriptor index */ +#define VELOCITY_TXDESC_CONSIDX3 0x5A /* Current TX descriptor index */ +#define VELOCITY_TX_PAUSE_TIMER 0x5C /* TX pause frame timer */ +#define VELOCITY_RXDESC_RESIDUECNT 0x5E /* RX descriptor residue count */ +#define VELOCITY_FIFOTEST0 0x60 /* FIFO test register */ +#define VELOCITY_FIFOTEST1 0x64 /* FIFO test register */ +#define VELOCITY_CAMADDR 0x68 /* CAM address register */ +#define VELOCITY_CAMCTL 0x69 /* CAM control register */ +#define VELOCITY_MIICFG 0x6C /* MII port config register */ +#define VELOCITY_MIISR 0x6D /* MII port status register */ +#define VELOCITY_MIISR_IDLE (1 << 7) +#define VELOCITY_PHYSTS0 0x6E /* PHY status register */ +#define VELOCITY_PHYSTS0_LINK (1 << 6) +#define VELOCITY_PHYSTS1 0x6F /* PHY status register */ +#define VELOCITY_MIICR 0x70 /* MII command register */ +#define VELOCITY_MIICR_MAUTO (1 << 7) +#define VELOCITY_MIICR_RCMD (1 << 6) +#define VELOCITY_MIICR_WCMD (1 << 5) +#define VELOCITY_MIICR_MDPM (1 << 4) +#define VELOCITY_MIICR_MOUT (1 << 3) +#define VELOCITY_MIICR_MDO (1 << 2) +#define VELOCITY_MIICR_MDI (1 << 1) +#define VELOCITY_MIICR_MDC (1 << 0) + +#define VELOCITY_MIIADDR 0x71 /* MII address register */ +#define VELOCITY_MIIDATA 0x72 /* MII data register */ +#define VELOCITY_SSTIMER 0x74 /* single-shot timer */ +#define VELOCITY_PTIMER 0x76 /* periodic timer */ +#define VELOCITY_DMACFG0 0x7C /* DMA config 0 */ +#define VELOCITY_DMACFG1 0x7D /* DMA config 1 */ +#define VELOCITY_RXCFG 0x7E /* MAC RX config */ +#define VELOCITY_TXCFG 0x7F /* MAC TX config */ +#define VELOCITY_SWEEDATA 0x85 /* EEPROM software loaded data */ + +/** Chip Configuration Register A */ +#define VELOCITY_CFGA 0x78 +#define VELOCITY_CFGA_PACPI (1 << 0) + +/** Power Management Sticky Register */ +#define VELOCITY_STICKY 0x83 +#define VELOCITY_STICKY_DS0 (1 << 0) +#define VELOCITY_STICKY_DS1 (1 << 1) + +#define VELOCITY_EEWRDAT 0x8C /* EEPROM embedded write */ +#define VELOCITY_EECSUM 0x92 /* EEPROM checksum */ +#define VELOCITY_EECSR 0x93 /* EEPROM control/status */ +#define VELOCITY_EECSR_RELOAD (1 << 5) +#define VELOCITY_EERDDAT 0x94 /* EEPROM embedded read */ +#define VELOCITY_EEADDR 0x96 /* EEPROM address */ +#define VELOCITY_EECMD 0x97 /* EEPROM embedded command */ + +/** A Velocity network card */ +struct velocity_nic { + /** Registers */ + void *regs; + /** MII interface */ + struct mii_interface mii; + /** Netdev */ + struct net_device *netdev; + + /** Receive descriptor ring */ + struct velocity_rx_descriptor *rx_ring; + /** Receive I/O buffers */ + struct io_buffer *rx_buffs[VELOCITY_RXDESC_NUM]; + /** Receive producer index */ + unsigned int rx_prod; + /** Receive consumer index */ + unsigned int rx_cons; + /** Receive commit number + * + * Used to fullfill the hardware requirement of returning receive buffers + * to the hardware only in blocks of 4. + */ + unsigned int rx_commit; + + /** Transmit descriptor ring */ + struct velocity_tx_descriptor *tx_ring; + /** Transmit producer index */ + unsigned int tx_prod; + /** Transmit consumer index */ + unsigned int tx_cons; +}; + +#endif /* _VELOCITY_H */ diff --git a/src/drivers/net/via-velocity.c b/src/drivers/net/via-velocity.c deleted file mode 100644 index e98e81a2..00000000 --- a/src/drivers/net/via-velocity.c +++ /dev/null @@ -1,1927 +0,0 @@ -/************************************************************************** -* via-velocity.c: Etherboot device driver for the VIA 6120 Gigabit -* Changes for Etherboot port: -* Copyright (c) 2006 by Timothy Legge <tlegge@rogers.com> -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -* 02110-1301, USA. -* -* This driver is based on: -* via-velocity.c: VIA Velocity VT6120, VT6122 Ethernet driver -* The changes are (c) Copyright 2004, Red Hat Inc. -* <alan@redhat.com> -* Additional fixes and clean up: Francois Romieu -* -* Original code: -* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. -* All rights reserved. -* Author: Chuang Liang-Shing, AJ Jiang -* -* Linux Driver Version 2.6.15.4 -* -* REVISION HISTORY: -* ================ -* -* v1.0 03-06-2006 timlegge Initial port of Linux driver -* -* Indent Options: indent -kr -i8 -*************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "etherboot.h" -#include "nic.h" -#include <ipxe/pci.h> -#include <ipxe/ethernet.h> - -#include "via-velocity.h" - -typedef int pci_power_t; - -#define PCI_D0 ((int) 0) -#define PCI_D1 ((int) 1) -#define PCI_D2 ((int) 2) -#define PCI_D3hot ((int) 3) -#define PCI_D3cold ((int) 4) -#define PCI_POWER_ERROR ((int) -1) - - -/* Condensed operations for readability. */ -#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) -#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) - -//FIXME: Move to pci.c -int pci_set_power_state(struct pci_device *dev, int state); - -/* FIXME: Move BASE to the private structure */ -static u32 BASE; - -/* NIC specific static variables go here */ -#define VELOCITY_PARAM(N,D) \ - static const int N[MAX_UNITS]=OPTION_DEFAULT; -/* MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UNITS) "i");\ - MODULE_PARM_DESC(N, D); */ - -VELOCITY_PARAM(RxDescriptors, "Number of receive descriptors"); -VELOCITY_PARAM(TxDescriptors, "Number of transmit descriptors"); - - -#define VLAN_ID_MIN 0 -#define VLAN_ID_MAX 4095 -#define VLAN_ID_DEF 0 -/* VID_setting[] is used for setting the VID of NIC. - 0: default VID. - 1-4094: other VIDs. -*/ -VELOCITY_PARAM(VID_setting, "802.1Q VLAN ID"); - -#define RX_THRESH_MIN 0 -#define RX_THRESH_MAX 3 -#define RX_THRESH_DEF 0 -/* rx_thresh[] is used for controlling the receive fifo threshold. - 0: indicate the rxfifo threshold is 128 bytes. - 1: indicate the rxfifo threshold is 512 bytes. - 2: indicate the rxfifo threshold is 1024 bytes. - 3: indicate the rxfifo threshold is store & forward. -*/ -VELOCITY_PARAM(rx_thresh, "Receive fifo threshold"); - -#define DMA_LENGTH_MIN 0 -#define DMA_LENGTH_MAX 7 -#define DMA_LENGTH_DEF 0 - -/* DMA_length[] is used for controlling the DMA length - 0: 8 DWORDs - 1: 16 DWORDs - 2: 32 DWORDs - 3: 64 DWORDs - 4: 128 DWORDs - 5: 256 DWORDs - 6: SF(flush till emply) - 7: SF(flush till emply) -*/ -VELOCITY_PARAM(DMA_length, "DMA length"); - -#define TAGGING_DEF 0 -/* enable_tagging[] is used for enabling 802.1Q VID tagging. - 0: disable VID seeting(default). - 1: enable VID setting. -*/ -VELOCITY_PARAM(enable_tagging, "Enable 802.1Q tagging"); - -#define IP_ALIG_DEF 0 -/* IP_byte_align[] is used for IP header DWORD byte aligned - 0: indicate the IP header won't be DWORD byte aligned.(Default) . - 1: indicate the IP header will be DWORD byte aligned. - In some environment, the IP header should be DWORD byte aligned, - or the packet will be droped when we receive it. (eg: IPVS) -*/ -VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned"); - -#define TX_CSUM_DEF 1 -/* txcsum_offload[] is used for setting the checksum offload ability of NIC. - (We only support RX checksum offload now) - 0: disable csum_offload[checksum offload - 1: enable checksum offload. (Default) -*/ -VELOCITY_PARAM(txcsum_offload, "Enable transmit packet checksum offload"); - -#define FLOW_CNTL_DEF 1 -#define FLOW_CNTL_MIN 1 -#define FLOW_CNTL_MAX 5 - -/* flow_control[] is used for setting the flow control ability of NIC. - 1: hardware deafult - AUTO (default). Use Hardware default value in ANAR. - 2: enable TX flow control. - 3: enable RX flow control. - 4: enable RX/TX flow control. - 5: disable -*/ -VELOCITY_PARAM(flow_control, "Enable flow control ability"); - -#define MED_LNK_DEF 0 -#define MED_LNK_MIN 0 -#define MED_LNK_MAX 4 -/* speed_duplex[] is used for setting the speed and duplex mode of NIC. - 0: indicate autonegotiation for both speed and duplex mode - 1: indicate 100Mbps half duplex mode - 2: indicate 100Mbps full duplex mode - 3: indicate 10Mbps half duplex mode - 4: indicate 10Mbps full duplex mode - - Note: - if EEPROM have been set to the force mode, this option is ignored - by driver. -*/ -VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode"); - -#define VAL_PKT_LEN_DEF 0 -/* ValPktLen[] is used for setting the checksum offload ability of NIC. - 0: Receive frame with invalid layer 2 length (Default) - 1: Drop frame with invalid layer 2 length -*/ -VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame"); - -#define WOL_OPT_DEF 0 -#define WOL_OPT_MIN 0 -#define WOL_OPT_MAX 7 -/* wol_opts[] is used for controlling wake on lan behavior. - 0: Wake up if recevied a magic packet. (Default) - 1: Wake up if link status is on/off. - 2: Wake up if recevied an arp packet. - 4: Wake up if recevied any unicast packet. - Those value can be sumed up to support more than one option. -*/ -VELOCITY_PARAM(wol_opts, "Wake On Lan options"); - -#define INT_WORKS_DEF 20 -#define INT_WORKS_MIN 10 -#define INT_WORKS_MAX 64 - -VELOCITY_PARAM(int_works, "Number of packets per interrupt services"); - -/* The descriptors for this card are required to be aligned on -64 byte boundaries. As the align attribute does not guarantee alignment -greater than the alignment of the start address (which for Etherboot -is 16 bytes of alignment) it requires some extra steps. Add 64 to the -size of the array and the init_ring adjusts the alignment */ - -/* Define the TX Descriptor */ -static u8 tx_ring[TX_DESC_DEF * sizeof(struct tx_desc) + 64]; - -/* Create a static buffer of size PKT_BUF_SZ for each TX Descriptor. -All descriptors point to a part of this buffer */ -static u8 txb[(TX_DESC_DEF * PKT_BUF_SZ) + 64]; - -/* Define the RX Descriptor */ -static u8 rx_ring[RX_DESC_DEF * sizeof(struct rx_desc) + 64]; - -/* Create a static buffer of size PKT_BUF_SZ for each RX Descriptor - All descriptors point to a part of this buffer */ -static u8 rxb[(RX_DESC_DEF * PKT_BUF_SZ) + 64]; - -static void velocity_init_info(struct pci_device *pdev, - struct velocity_info *vptr, - struct velocity_info_tbl *info); -static int velocity_get_pci_info(struct velocity_info *, - struct pci_device *pdev); -static int velocity_open(struct nic *nic, struct pci_device *pci); - -static int velocity_soft_reset(struct velocity_info *vptr); -static void velocity_init_cam_filter(struct velocity_info *vptr); -static void mii_init(struct velocity_info *vptr, u32 mii_status); -static u32 velocity_get_opt_media_mode(struct velocity_info *vptr); -static void velocity_print_link_status(struct velocity_info *vptr); -static void safe_disable_mii_autopoll(struct mac_regs *regs); -static void enable_flow_control_ability(struct velocity_info *vptr); -static void enable_mii_autopoll(struct mac_regs *regs); -static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata); -static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data); -static u32 mii_check_media_mode(struct mac_regs *regs); -static u32 check_connection_type(struct mac_regs *regs); -static int velocity_set_media_mode(struct velocity_info *vptr, - u32 mii_status); - - -/* - * Internal board variants. At the moment we have only one - */ - -static struct velocity_info_tbl chip_info_table[] = { - {CHIP_TYPE_VT6110, - "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1, - 0x00FFFFFFUL}, - {0, NULL, 0, 0, 0} -}; - -/** - * velocity_set_int_opt - parser for integer options - * @opt: pointer to option value - * @val: value the user requested (or -1 for default) - * @min: lowest value allowed - * @max: highest value allowed - * @def: default value - * @name: property name - * @dev: device name - * - * Set an integer property in the module options. This function does - * all the verification and checking as well as reporting so that - * we don't duplicate code for each option. - */ - -static void velocity_set_int_opt(int *opt, int val, int min, int max, - int def, char *name, const char *devname) -{ - if (val == -1) { - printf("%s: set value of parameter %s to %d\n", - devname, name, def); - *opt = def; - } else if (val < min || val > max) { - printf - ("%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n", - devname, name, min, max); - *opt = def; - } else { - printf("%s: set value of parameter %s to %d\n", - devname, name, val); - *opt = val; - } -} - -/** - * velocity_set_bool_opt - parser for boolean options - * @opt: pointer to option value - * @val: value the user requested (or -1 for default) - * @def: default value (yes/no) - * @flag: numeric value to set for true. - * @name: property name - * @dev: device name - * - * Set a boolean property in the module options. This function does - * all the verification and checking as well as reporting so that - * we don't duplicate code for each option. - */ - -static void velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag, - char *name, const char *devname) -{ - (*opt) &= (~flag); - if (val == -1) { - printf("%s: set parameter %s to %s\n", - devname, name, def ? "TRUE" : "FALSE"); - *opt |= (def ? flag : 0); - } else if (val < 0 || val > 1) { - printf - ("%s: the value of parameter %s is invalid, the valid range is (0-1)\n", - devname, name); - *opt |= (def ? flag : 0); - } else { - printf("%s: set parameter %s to %s\n", - devname, name, val ? "TRUE" : "FALSE"); - *opt |= (val ? flag : 0); - } -} - -/** - * velocity_get_options - set options on device - * @opts: option structure for the device - * @index: index of option to use in module options array - * @devname: device name - * - * Turn the module and command options into a single structure - * for the current device - */ - -static void velocity_get_options(struct velocity_opt *opts, int index, - const char *devname) -{ - - /* FIXME Do the options need to be configurable */ - velocity_set_int_opt(&opts->rx_thresh, -1, RX_THRESH_MIN, - RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", - devname); - velocity_set_int_opt(&opts->DMA_length, DMA_length[index], - DMA_LENGTH_MIN, DMA_LENGTH_MAX, - DMA_LENGTH_DEF, "DMA_length", devname); - velocity_set_int_opt(&opts->numrx, RxDescriptors[index], - RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF, - "RxDescriptors", devname); - velocity_set_int_opt(&opts->numtx, TxDescriptors[index], - TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF, - "TxDescriptors", devname); - velocity_set_int_opt(&opts->vid, VID_setting[index], VLAN_ID_MIN, - VLAN_ID_MAX, VLAN_ID_DEF, "VID_setting", - devname); - velocity_set_bool_opt(&opts->flags, enable_tagging[index], - TAGGING_DEF, VELOCITY_FLAGS_TAGGING, - "enable_tagging", devname); - velocity_set_bool_opt(&opts->flags, txcsum_offload[index], - TX_CSUM_DEF, VELOCITY_FLAGS_TX_CSUM, - "txcsum_offload", devname); - velocity_set_int_opt(&opts->flow_cntl, flow_control[index], - FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, - "flow_control", devname); - velocity_set_bool_opt(&opts->flags, IP_byte_align[index], - IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, - "IP_byte_align", devname); - velocity_set_bool_opt(&opts->flags, ValPktLen[index], - VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, - "ValPktLen", devname); - velocity_set_int_opt((void *) &opts->spd_dpx, speed_duplex[index], - MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, - "Media link mode", devname); - velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], - WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, - "Wake On Lan options", devname); - velocity_set_int_opt((int *) &opts->int_works, int_works[index], - INT_WORKS_MIN, INT_WORKS_MAX, INT_WORKS_DEF, - "Interrupt service works", devname); - opts->numrx = (opts->numrx & ~3); -} - -/** - * velocity_init_cam_filter - initialise CAM - * @vptr: velocity to program - * - * Initialize the content addressable memory used for filters. Load - * appropriately according to the presence of VLAN - */ - -static void velocity_init_cam_filter(struct velocity_info *vptr) -{ - struct mac_regs *regs = vptr->mac_regs; - - /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ - WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); - WORD_REG_BITS_ON(MCFG_VIDFR, ®s->MCFG); - - /* Disable all CAMs */ - memset(vptr->vCAMmask, 0, sizeof(u8) * 8); - memset(vptr->mCAMmask, 0, sizeof(u8) * 8); - mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM); - mac_set_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM); - - /* Enable first VCAM */ - if (vptr->flags & VELOCITY_FLAGS_TAGGING) { - /* If Tagging option is enabled and VLAN ID is not zero, then - turn on MCFG_RTGOPT also */ - if (vptr->options.vid != 0) - WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); - - mac_set_cam(regs, 0, (u8 *) & (vptr->options.vid), - VELOCITY_VLAN_ID_CAM); - vptr->vCAMmask[0] |= 1; - mac_set_cam_mask(regs, vptr->vCAMmask, - VELOCITY_VLAN_ID_CAM); - } else { - u16 temp = 0; - mac_set_cam(regs, 0, (u8 *) & temp, VELOCITY_VLAN_ID_CAM); - temp = 1; - mac_set_cam_mask(regs, (u8 *) & temp, - VELOCITY_VLAN_ID_CAM); - } -} - -static inline void velocity_give_many_rx_descs(struct velocity_info *vptr) -{ - struct mac_regs *regs = vptr->mac_regs; - int avail, dirty, unusable; - - /* - * RD number must be equal to 4X per hardware spec - * (programming guide rev 1.20, p.13) - */ - if (vptr->rd_filled < 4) - return; - - wmb(); - - unusable = vptr->rd_filled & 0x0003; - dirty = vptr->rd_dirty - unusable; - for (avail = vptr->rd_filled & 0xfffc; avail; avail--) { - dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1; -// printf("return dirty: %d\n", dirty); - vptr->rd_ring[dirty].rdesc0.owner = OWNED_BY_NIC; - } - - writew(vptr->rd_filled & 0xfffc, ®s->RBRDU); - vptr->rd_filled = unusable; -} - -static int velocity_rx_refill(struct velocity_info *vptr) -{ - int dirty = vptr->rd_dirty, done = 0, ret = 0; - -// printf("rx_refill - rd_curr = %d, dirty = %d\n", vptr->rd_curr, dirty); - do { - struct rx_desc *rd = vptr->rd_ring + dirty; - - /* Fine for an all zero Rx desc at init time as well */ - if (rd->rdesc0.owner == OWNED_BY_NIC) - break; -// printf("rx_refill - after owner %d\n", dirty); - - rd->inten = 1; - rd->pa_high = 0; - rd->rdesc0.len = cpu_to_le32(vptr->rx_buf_sz);; - - done++; - dirty = (dirty < vptr->options.numrx - 1) ? dirty + 1 : 0; - } while (dirty != vptr->rd_curr); - - if (done) { -// printf("\nGive Back Desc\n"); - vptr->rd_dirty = dirty; - vptr->rd_filled += done; - velocity_give_many_rx_descs(vptr); - } - - return ret; -} - -extern void hex_dump(const char *data, const unsigned int len); -/************************************************************************** -POLL - Wait for a frame -***************************************************************************/ -static int velocity_poll(struct nic *nic, int retrieve) -{ - /* Work out whether or not there's an ethernet packet ready to - * read. Return 0 if not. - */ - - int rd_curr = vptr->rd_curr % RX_DESC_DEF; - struct rx_desc *rd = &(vptr->rd_ring[rd_curr]); - - if (rd->rdesc0.owner == OWNED_BY_NIC) - return 0; - rmb(); - - if ( ! retrieve ) return 1; - - /* - * Don't drop CE or RL error frame although RXOK is off - */ - if ((rd->rdesc0.RSR & RSR_RXOK) - || (!(rd->rdesc0.RSR & RSR_RXOK) - && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) { - - nic->packetlen = rd->rdesc0.len; - // ptr->rxb + (rd_curr * PKT_BUF_SZ) - memcpy(nic->packet, bus_to_virt(rd->pa_low), - nic->packetlen - 4); - - vptr->rd_curr++; - vptr->rd_curr = vptr->rd_curr % RX_DESC_DEF; - velocity_rx_refill(vptr); - return 1; /* Remove this line once this method is implemented */ - } - return 0; -} - -#define TX_TIMEOUT (1000); -/************************************************************************** -TRANSMIT - Transmit a frame -***************************************************************************/ -static void velocity_transmit(struct nic *nic, const char *dest, /* Destination */ - unsigned int type, /* Type */ - unsigned int size, /* size */ - const char *packet) -{ /* Packet */ - u16 nstype; - u32 to; - u8 *ptxb; - unsigned int pktlen; - struct tx_desc *td_ptr; - - int entry = vptr->td_curr % TX_DESC_DEF; - td_ptr = &(vptr->td_rings[entry]); - - /* point to the current txb incase multiple tx_rings are used */ - ptxb = vptr->txb + (entry * PKT_BUF_SZ); - memcpy(ptxb, dest, ETH_ALEN); /* Destination */ - memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* Source */ - nstype = htons((u16) type); /* Type */ - memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* Type */ - memcpy(ptxb + ETH_HLEN, packet, size); - - td_ptr->tdesc1.TCPLS = TCPLS_NORMAL; - td_ptr->tdesc1.TCR = TCR0_TIC; - td_ptr->td_buf[0].queue = 0; - - size += ETH_HLEN; - while (size < ETH_ZLEN) /* pad to min length */ - ptxb[size++] = '\0'; - - if (size < ETH_ZLEN) { -// printf("Padd that packet\n"); - pktlen = ETH_ZLEN; -// memcpy(ptxb, skb->data, skb->len); - memset(ptxb + size, 0, ETH_ZLEN - size); - - vptr->td_rings[entry].tdesc0.pktsize = pktlen; - vptr->td_rings[entry].td_buf[0].pa_low = virt_to_bus(ptxb); - vptr->td_rings[entry].td_buf[0].pa_high &= - cpu_to_le32(0xffff0000UL); - vptr->td_rings[entry].td_buf[0].bufsize = - vptr->td_rings[entry].tdesc0.pktsize; - vptr->td_rings[entry].tdesc1.CMDZ = 2; - } else { -// printf("Correct size packet\n"); - td_ptr->tdesc0.pktsize = size; - td_ptr->td_buf[0].pa_low = virt_to_bus(ptxb); - td_ptr->td_buf[0].pa_high = 0; - td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize; -// tdinfo->nskb_dma = 1; - td_ptr->tdesc1.CMDZ = 2; - } - - if (vptr->flags & VELOCITY_FLAGS_TAGGING) { - td_ptr->tdesc1.pqinf.VID = (vptr->options.vid & 0xfff); - td_ptr->tdesc1.pqinf.priority = 0; - td_ptr->tdesc1.pqinf.CFI = 0; - td_ptr->tdesc1.TCR |= TCR0_VETAG; - } - - vptr->td_curr = (entry + 1); - - { - - int prev = entry - 1; - - if (prev < 0) - prev = TX_DESC_DEF - 1; - td_ptr->tdesc0.owner |= OWNED_BY_NIC; - td_ptr = &(vptr->td_rings[prev]); - td_ptr->td_buf[0].queue = 1; - mac_tx_queue_wake(vptr->mac_regs, 0); - - } - - to = currticks() + TX_TIMEOUT; - while ((td_ptr->tdesc0.owner & OWNED_BY_NIC) && (currticks() < to)); /* wait */ - - if (currticks() >= to) { - printf("TX Time Out"); - } - -} - -/************************************************************************** -DISABLE - Turn off ethernet interface -***************************************************************************/ -static void velocity_disable(struct nic *nic __unused) -{ - /* put the card in its initial state */ - /* This function serves 3 purposes. - * This disables DMA and interrupts so we don't receive - * unexpected packets or interrupts from the card after - * etherboot has finished. - * This frees resources so etherboot may use - * this driver on another interface - * This allows etherboot to reinitialize the interface - * if something is something goes wrong. - */ - struct mac_regs *regs = vptr->mac_regs; - mac_disable_int(regs); - writel(CR0_STOP, ®s->CR0Set); - writew(0xFFFF, ®s->TDCSRClr); - writeb(0xFF, ®s->RDCSRClr); - safe_disable_mii_autopoll(regs); - mac_clear_isr(regs); - - /* Power down the chip */ -// pci_set_power_state(vptr->pdev, PCI_D3hot); - - vptr->flags &= (~VELOCITY_FLAGS_OPENED); -} - -/************************************************************************** -IRQ - handle interrupts -***************************************************************************/ -static void velocity_irq(struct nic *nic __unused, irq_action_t action) -{ - /* This routine is somewhat optional. Etherboot itself - * doesn't use interrupts, but they are required under some - * circumstances when we're acting as a PXE stack. - * - * If you don't implement this routine, the only effect will - * be that your driver cannot be used via Etherboot's UNDI - * API. This won't affect programs that use only the UDP - * portion of the PXE API, such as pxelinux. - */ - - switch (action) { - case DISABLE: - case ENABLE: - /* Set receive interrupt enabled/disabled state */ - /* - outb ( action == ENABLE ? IntrMaskEnabled : IntrMaskDisabled, - nic->ioaddr + IntrMaskRegister ); - */ - break; - case FORCE: - /* Force NIC to generate a receive interrupt */ - /* - outb ( ForceInterrupt, nic->ioaddr + IntrForceRegister ); - */ - break; - } -} - -static struct nic_operations velocity_operations = { - .connect = dummy_connect, - .poll = velocity_poll, - .transmit = velocity_transmit, - .irq = velocity_irq, -}; - -/************************************************************************** -PROBE - Look for an adapter, this routine's visible to the outside -***************************************************************************/ -static int velocity_probe( struct nic *nic, struct pci_device *pci) -{ - int ret, i; - struct mac_regs *regs; - - printf("via-velocity.c: Found %s Vendor=0x%hX Device=0x%hX\n", - pci->id->name, pci->vendor, pci->device); - - /* point to private storage */ - vptr = &vptx; - info = chip_info_table; - - velocity_init_info(pci, vptr, info); - -//FIXME: pci_enable_device(pci); -//FIXME: pci_set_power_state(pci, PCI_D0); - - ret = velocity_get_pci_info(vptr, pci); - if (ret < 0) { - printf("Failed to find PCI device.\n"); - return 0; - } - - regs = ioremap(vptr->memaddr, vptr->io_size); - if (regs == NULL) { - printf("Unable to remap io\n"); - return 0; - } - - vptr->mac_regs = regs; - - BASE = vptr->ioaddr; - - printf("Chip ID: %hX\n", vptr->chip_id); - - for (i = 0; i < 6; i++) - nic->node_addr[i] = readb(®s->PAR[i]); - - DBG ( "%s: %s at ioaddr %#hX\n", pci->id->name, eth_ntoa ( nic->node_addr ), - (unsigned int) BASE ); - - velocity_get_options(&vptr->options, 0, pci->id->name); - - /* - * Mask out the options cannot be set to the chip - */ - vptr->options.flags &= 0x00FFFFFFUL; //info->flags = 0x00FFFFFFUL; - - /* - * Enable the chip specified capbilities - */ - - vptr->flags = - vptr->options. - flags | (0x00FFFFFFUL /*info->flags */ & 0xFF000000UL); - - vptr->wol_opts = vptr->options.wol_opts; - vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED; - - vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs); - - if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) { - printf("features missing\n"); - } - - /* and leave the chip powered down */ -// FIXME: pci_set_power_state(pci, PCI_D3hot); - - check_connection_type(vptr->mac_regs); - velocity_open(nic, pci); - - /* store NIC parameters */ - nic->nic_op = &velocity_operations; - return 1; -} - -//#define IORESOURCE_IO 0x00000100 /* Resource type */ - -/** - * velocity_init_info - init private data - * @pdev: PCI device - * @vptr: Velocity info - * @info: Board type - * - * Set up the initial velocity_info struct for the device that has been - * discovered. - */ - -static void velocity_init_info(struct pci_device *pdev, - struct velocity_info *vptr, - struct velocity_info_tbl *info) -{ - memset(vptr, 0, sizeof(struct velocity_info)); - - vptr->pdev = pdev; - vptr->chip_id = info->chip_id; - vptr->io_size = info->io_size; - vptr->num_txq = info->txqueue; - vptr->multicast_limit = MCAM_SIZE; - - printf - ("chip_id: 0x%hX, io_size: %d, num_txq %d, multicast_limit: %d\n", - vptr->chip_id, (unsigned int) vptr->io_size, vptr->num_txq, - vptr->multicast_limit); - printf("Name: %s\n", info->name); - -// spin_lock_init(&vptr->lock); -// INIT_LIST_HEAD(&vptr->list); -} - -/** - * velocity_get_pci_info - retrieve PCI info for device - * @vptr: velocity device - * @pdev: PCI device it matches - * - * Retrieve the PCI configuration space data that interests us from - * the kernel PCI layer - */ - -#define IORESOURCE_IO 0x00000100 /* Resource type */ -#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */ - -#define IORESOURCE_MEM 0x00000200 -#define BAR_0 0 -#define BAR_1 1 -#define BAR_5 5 -#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ -#define PCI_BASE_ADDRESS_SPACE_IO 0x01 -#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 -#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 -#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ -#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ -#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ -#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ -//#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) -// #define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) - -unsigned long pci_resource_flags(struct pci_device *pdev, unsigned int bar) -{ - uint32_t l, sz; - unsigned long flags = 0; - - pci_read_config_dword(pdev, bar, &l); - pci_write_config_dword(pdev, bar, ~0); - pci_read_config_dword(pdev, bar, &sz); - pci_write_config_dword(pdev, bar, l); - - if (!sz || sz == 0xffffffff) - printf("Weird size\n"); - if (l == 0xffffffff) - l = 0; - if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) { - /* sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK); - if (!sz) - continue; - res->start = l & PCI_BASE_ADDRESS_MEM_MASK; - */ flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; - printf("Memory Resource\n"); - } else { - // sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff); - /// if (!sz) - /// continue; -// res->start = l & PCI_BASE_ADDRESS_IO_MASK; - flags |= l & ~PCI_BASE_ADDRESS_IO_MASK; - printf("I/O Resource\n"); - } - if (flags & PCI_BASE_ADDRESS_SPACE_IO) { - printf("Why is it here\n"); - flags |= IORESOURCE_IO; - } else { - printf("here\n"); -//flags &= ~IORESOURCE_IO; - } - - - if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) - flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; - - - return flags; -} -static int velocity_get_pci_info(struct velocity_info *vptr, - struct pci_device *pdev) -{ - if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0) { - printf("DEBUG: pci_read_config_byte failed\n"); - return -1; - } - - adjust_pci_device(pdev); - - vptr->ioaddr = pci_bar_start(pdev, PCI_BASE_ADDRESS_0); - vptr->memaddr = pci_bar_start(pdev, PCI_BASE_ADDRESS_1); - - printf("Looking for I/O Resource - Found:"); - if (! - (pci_resource_flags(pdev, PCI_BASE_ADDRESS_0) & IORESOURCE_IO)) - { - printf - ("DEBUG: region #0 is not an I/O resource, aborting.\n"); - return -1; - } - - printf("Looking for Memory Resource - Found:"); - if ((pci_resource_flags(pdev, PCI_BASE_ADDRESS_1) & IORESOURCE_IO)) { - printf("DEBUG: region #1 is an I/O resource, aborting.\n"); - return -1; - } - - if (pci_bar_size(pdev, PCI_BASE_ADDRESS_1) < 256) { - printf("DEBUG: region #1 is too small.\n"); - return -1; - } - vptr->pdev = pdev; - - return 0; -} - -/** - * velocity_print_link_status - link status reporting - * @vptr: velocity to report on - * - * Turn the link status of the velocity card into a kernel log - * description of the new link state, detailing speed and duplex - * status - */ - -static void velocity_print_link_status(struct velocity_info *vptr) -{ - - if (vptr->mii_status & VELOCITY_LINK_FAIL) { - printf("failed to detect cable link\n"); - } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) { - printf("Link autonegation"); - - if (vptr->mii_status & VELOCITY_SPEED_1000) - printf(" speed 1000M bps"); - else if (vptr->mii_status & VELOCITY_SPEED_100) - printf(" speed 100M bps"); - else - printf(" speed 10M bps"); - - if (vptr->mii_status & VELOCITY_DUPLEX_FULL) - printf(" full duplex\n"); - else - printf(" half duplex\n"); - } else { - printf("Link forced"); - switch (vptr->options.spd_dpx) { - case SPD_DPX_100_HALF: - printf(" speed 100M bps half duplex\n"); - break; - case SPD_DPX_100_FULL: - printf(" speed 100M bps full duplex\n"); - break; - case SPD_DPX_10_HALF: - printf(" speed 10M bps half duplex\n"); - break; - case SPD_DPX_10_FULL: - printf(" speed 10M bps full duplex\n"); - break; - default: - break; - } - } -} - -/** - * velocity_rx_reset - handle a receive reset - * @vptr: velocity we are resetting - * - * Reset the ownership and status for the receive ring side. - * Hand all the receive queue to the NIC. - */ - -static void velocity_rx_reset(struct velocity_info *vptr) -{ - - struct mac_regs *regs = vptr->mac_regs; - int i; - -//ptr->rd_dirty = vptr->rd_filled = vptr->rd_curr = 0; - - /* - * Init state, all RD entries belong to the NIC - */ - for (i = 0; i < vptr->options.numrx; ++i) - vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC; - - writew(RX_DESC_DEF, ®s->RBRDU); - writel(virt_to_le32desc(vptr->rd_ring), ®s->RDBaseLo); - writew(0, ®s->RDIdx); - writew(RX_DESC_DEF - 1, ®s->RDCSize); -} - -/** - * velocity_init_registers - initialise MAC registers - * @vptr: velocity to init - * @type: type of initialisation (hot or cold) - * - * Initialise the MAC on a reset or on first set up on the - * hardware. - */ - -static void velocity_init_registers(struct nic *nic, - struct velocity_info *vptr, - enum velocity_init_type type) -{ - struct mac_regs *regs = vptr->mac_regs; - int i, mii_status; - - mac_wol_reset(regs); - - switch (type) { - case VELOCITY_INIT_RESET: - case VELOCITY_INIT_WOL: - -//netif_stop_queue(vptr->dev); - - /* - * Reset RX to prevent RX pointer not on the 4X location - */ - velocity_rx_reset(vptr); - mac_rx_queue_run(regs); - mac_rx_queue_wake(regs); - - mii_status = velocity_get_opt_media_mode(vptr); - - if (velocity_set_media_mode(vptr, mii_status) != - VELOCITY_LINK_CHANGE) { - velocity_print_link_status(vptr); - if (!(vptr->mii_status & VELOCITY_LINK_FAIL)) - printf("Link Failed\n"); -// netif_wake_queue(vptr->dev); - } - - enable_flow_control_ability(vptr); - - mac_clear_isr(regs); - writel(CR0_STOP, ®s->CR0Clr); - //writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), - writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), - ®s->CR0Set); - break; - - case VELOCITY_INIT_COLD: - default: - /* - * Do reset - */ - velocity_soft_reset(vptr); - mdelay(5); - - mac_eeprom_reload(regs); - for (i = 0; i < 6; i++) { - writeb(nic->node_addr[i], &(regs->PAR[i])); - } - /* - * clear Pre_ACPI bit. - */ - BYTE_REG_BITS_OFF(CFGA_PACPI, &(regs->CFGA)); - mac_set_rx_thresh(regs, vptr->options.rx_thresh); - mac_set_dma_length(regs, vptr->options.DMA_length); - - writeb(WOLCFG_SAM | WOLCFG_SAB, ®s->WOLCFGSet); - /* - * Back off algorithm use original IEEE standard - */ - BYTE_REG_BITS_SET(CFGB_OFSET, - (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | - CFGB_BAKOPT), ®s->CFGB); - - /* - * Init CAM filter - */ - velocity_init_cam_filter(vptr); - - /* - * Set packet filter: Receive directed and broadcast address - */ -//FIXME Multicast velocity_set_multi(nic); - - /* - * Enable MII auto-polling - */ - enable_mii_autopoll(regs); - - vptr->int_mask = INT_MASK_DEF; - - writel(virt_to_le32desc(vptr->rd_ring), ®s->RDBaseLo); - writew(vptr->options.numrx - 1, ®s->RDCSize); - mac_rx_queue_run(regs); - mac_rx_queue_wake(regs); - - writew(vptr->options.numtx - 1, ®s->TDCSize); - -// for (i = 0; i < vptr->num_txq; i++) { - writel(virt_to_le32desc(vptr->td_rings), - &(regs->TDBaseLo[0])); - mac_tx_queue_run(regs, 0); -// } - - init_flow_control_register(vptr); - - writel(CR0_STOP, ®s->CR0Clr); - writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), - ®s->CR0Set); - - mii_status = velocity_get_opt_media_mode(vptr); -// netif_stop_queue(vptr->dev); - - mii_init(vptr, mii_status); - - if (velocity_set_media_mode(vptr, mii_status) != - VELOCITY_LINK_CHANGE) { - velocity_print_link_status(vptr); - if (!(vptr->mii_status & VELOCITY_LINK_FAIL)) - printf("Link Faaailll\n"); -// netif_wake_queue(vptr->dev); - } - - enable_flow_control_ability(vptr); - mac_hw_mibs_init(regs); - mac_write_int_mask(vptr->int_mask, regs); - mac_clear_isr(regs); - - - } - velocity_print_link_status(vptr); -} - -/** - * velocity_soft_reset - soft reset - * @vptr: velocity to reset - * - * Kick off a soft reset of the velocity adapter and then poll - * until the reset sequence has completed before returning. - */ - -static int velocity_soft_reset(struct velocity_info *vptr) -{ - struct mac_regs *regs = vptr->mac_regs; - unsigned int i = 0; - - writel(CR0_SFRST, ®s->CR0Set); - - for (i = 0; i < W_MAX_TIMEOUT; i++) { - udelay(5); - if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, ®s->CR0Set)) - break; - } - - if (i == W_MAX_TIMEOUT) { - writel(CR0_FORSRST, ®s->CR0Set); - /* FIXME: PCI POSTING */ - /* delay 2ms */ - mdelay(2); - } - return 0; -} - -/** - * velocity_init_rings - set up DMA rings - * @vptr: Velocity to set up - * - * Allocate PCI mapped DMA rings for the receive and transmit layer - * to use. - */ - -static int velocity_init_rings(struct velocity_info *vptr) -{ - - int idx; - - vptr->rd_curr = 0; - vptr->td_curr = 0; - memset(vptr->td_rings, 0, TX_DESC_DEF * sizeof(struct tx_desc)); - memset(vptr->rd_ring, 0, RX_DESC_DEF * sizeof(struct rx_desc)); -// memset(vptr->tx_buffs, 0, TX_DESC_DEF * PKT_BUF_SZ); - - - for (idx = 0; idx < RX_DESC_DEF; idx++) { - vptr->rd_ring[idx].rdesc0.RSR = 0; - vptr->rd_ring[idx].rdesc0.len = 0; - vptr->rd_ring[idx].rdesc0.reserved = 0; - vptr->rd_ring[idx].rdesc0.owner = 0; - vptr->rd_ring[idx].len = cpu_to_le32(vptr->rx_buf_sz); - vptr->rd_ring[idx].inten = 1; - vptr->rd_ring[idx].pa_low = - virt_to_bus(vptr->rxb + (RX_DESC_DEF * idx)); - vptr->rd_ring[idx].pa_high = 0; - vptr->rd_ring[idx].rdesc0.owner = OWNED_BY_NIC; - } - -/* for (i = 0; idx < TX_DESC_DEF; idx++ ) { - vptr->td_rings[idx].tdesc1.TCPLS = TCPLS_NORMAL; - vptr->td_rings[idx].tdesc1.TCR = TCR0_TIC; - vptr->td_rings[idx].td_buf[0].queue = 0; - vptr->td_rings[idx].tdesc0.owner = ~OWNED_BY_NIC; - vptr->td_rings[idx].tdesc0.pktsize = 0; - vptr->td_rings[idx].td_buf[0].pa_low = cpu_to_le32(virt_to_bus(vptr->txb + (idx * PKT_BUF_SZ))); - vptr->td_rings[idx].td_buf[0].pa_high = 0; - vptr->td_rings[idx].td_buf[0].bufsize = 0; - vptr->td_rings[idx].tdesc1.CMDZ = 2; - } -*/ - return 0; -} - -/** - * velocity_open - interface activation callback - * @dev: network layer device to open - * - * Called when the network layer brings the interface up. Returns - * a negative posix error code on failure, or zero on success. - * - * All the ring allocation and set up is done on open for this - * adapter to minimise memory usage when inactive - */ - -#define PCI_BYTE_REG_BITS_ON(x,i,p) do{\ - u8 byReg;\ - pci_read_config_byte((p), (i), &(byReg));\ - (byReg) |= (x);\ - pci_write_config_byte((p), (i), (byReg));\ -} while (0) - -// -// Registers in the PCI configuration space -// -#define PCI_REG_COMMAND 0x04 // -#define PCI_REG_MODE0 0x60 // -#define PCI_REG_MODE1 0x61 // -#define PCI_REG_MODE2 0x62 // -#define PCI_REG_MODE3 0x63 // -#define PCI_REG_DELAY_TIMER 0x64 // - -// Bits in the (MODE2, 0x62) register -// -#define MODE2_PCEROPT 0x80 // take PCI bus ERror as a fatal and shutdown from software control -#define MODE2_TXQ16 0x40 // TX write-back Queue control. 0->32 entries available in Tx write-back queue, 1->16 entries -#define MODE2_TXPOST 0x08 // (Not support in VT3119) -#define MODE2_AUTOOPT 0x04 // (VT3119 GHCI without such behavior) -#define MODE2_MODE10T 0x02 // used to control tx Threshold for 10M case -#define MODE2_TCPLSOPT 0x01 // TCP large send field update disable, hardware will not update related fields, leave it to software. - -// -// Bits in the MODE3 register -// -#define MODE3_MIION 0x04 // MII symbol codine error detect enable ?? - -// Bits in the (COMMAND, 0x04) register -#define COMMAND_BUSM 0x04 -#define COMMAND_WAIT 0x80 -static int velocity_open(struct nic *nic, struct pci_device *pci __unused) -{ - u8 diff; - u32 TxPhyAddr, RxPhyAddr; - u32 TxBufPhyAddr, RxBufPhyAddr; - vptr->TxDescArrays = tx_ring; - if (vptr->TxDescArrays == NULL) - printf("Allot Error"); - - /* Tx Descriptor needs 64 bytes alignment; */ - TxPhyAddr = virt_to_bus(vptr->TxDescArrays); - printf("Unaligned Address : %X\n", TxPhyAddr); - diff = 64 - (TxPhyAddr - ((TxPhyAddr >> 6) << 6)); - TxPhyAddr += diff; - vptr->td_rings = (struct tx_desc *) (vptr->TxDescArrays + diff); - - printf("Aligned Address: %lX\n", virt_to_bus(vptr->td_rings)); - vptr->tx_buffs = txb; - /* Rx Buffer needs 64 bytes alignment; */ - TxBufPhyAddr = virt_to_bus(vptr->tx_buffs); - diff = 64 - (TxBufPhyAddr - ((TxBufPhyAddr >> 6) << 6)); - TxBufPhyAddr += diff; - vptr->txb = (unsigned char *) (vptr->tx_buffs + diff); - - vptr->RxDescArrays = rx_ring; - /* Rx Descriptor needs 64 bytes alignment; */ - RxPhyAddr = virt_to_bus(vptr->RxDescArrays); - diff = 64 - (RxPhyAddr - ((RxPhyAddr >> 6) << 6)); - RxPhyAddr += diff; - vptr->rd_ring = (struct rx_desc *) (vptr->RxDescArrays + diff); - - vptr->rx_buffs = rxb; - /* Rx Buffer needs 64 bytes alignment; */ - RxBufPhyAddr = virt_to_bus(vptr->rx_buffs); - diff = 64 - (RxBufPhyAddr - ((RxBufPhyAddr >> 6) << 6)); - RxBufPhyAddr += diff; - vptr->rxb = (unsigned char *) (vptr->rx_buffs + diff); - - if (vptr->RxDescArrays == NULL || vptr->RxDescArrays == NULL) { - printf("Allocate tx_ring or rd_ring failed\n"); - return 0; - } - - vptr->rx_buf_sz = PKT_BUF_SZ; -/* - // turn this on to avoid retry forever - PCI_BYTE_REG_BITS_ON(MODE2_PCEROPT, PCI_REG_MODE2, pci); - // for some legacy BIOS and OS don't open BusM - // bit in PCI configuration space. So, turn it on. - PCI_BYTE_REG_BITS_ON(COMMAND_BUSM, PCI_REG_COMMAND, pci); - // turn this on to detect MII coding error - PCI_BYTE_REG_BITS_ON(MODE3_MIION, PCI_REG_MODE3, pci); - */ - velocity_init_rings(vptr); - - /* Ensure chip is running */ -//FIXME: pci_set_power_state(vptr->pdev, PCI_D0); - - velocity_init_registers(nic, vptr, VELOCITY_INIT_COLD); - mac_write_int_mask(0, vptr->mac_regs); -// _int(vptr->mac_regs); - //mac_enable_int(vptr->mac_regs); - - vptr->flags |= VELOCITY_FLAGS_OPENED; - return 1; - -} - -/* - * MII access , media link mode setting functions - */ - - -/** - * mii_init - set up MII - * @vptr: velocity adapter - * @mii_status: links tatus - * - * Set up the PHY for the current link state. - */ - -static void mii_init(struct velocity_info *vptr, u32 mii_status __unused) -{ - u16 BMCR; - - switch (PHYID_GET_PHY_ID(vptr->phy_id)) { - case PHYID_CICADA_CS8201: - /* - * Reset to hardware default - */ - MII_REG_BITS_OFF((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, - vptr->mac_regs); - /* - * Turn on ECHODIS bit in NWay-forced full mode and turn it - * off it in NWay-forced half mode for NWay-forced v.s. - * legacy-forced issue. - */ - if (vptr->mii_status & VELOCITY_DUPLEX_FULL) - MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, - vptr->mac_regs); - else - MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, - vptr->mac_regs); - /* - * Turn on Link/Activity LED enable bit for CIS8201 - */ - MII_REG_BITS_ON(PLED_LALBE, MII_REG_PLED, vptr->mac_regs); - break; - case PHYID_VT3216_32BIT: - case PHYID_VT3216_64BIT: - /* - * Reset to hardware default - */ - MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, - vptr->mac_regs); - /* - * Turn on ECHODIS bit in NWay-forced full mode and turn it - * off it in NWay-forced half mode for NWay-forced v.s. - * legacy-forced issue - */ - if (vptr->mii_status & VELOCITY_DUPLEX_FULL) - MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, - vptr->mac_regs); - else - MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, - vptr->mac_regs); - break; - - case PHYID_MARVELL_1000: - case PHYID_MARVELL_1000S: - /* - * Assert CRS on Transmit - */ - MII_REG_BITS_ON(PSCR_ACRSTX, MII_REG_PSCR, vptr->mac_regs); - /* - * Reset to hardware default - */ - MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, - vptr->mac_regs); - break; - default: - ; - } - velocity_mii_read(vptr->mac_regs, MII_REG_BMCR, &BMCR); - if (BMCR & BMCR_ISO) { - BMCR &= ~BMCR_ISO; - velocity_mii_write(vptr->mac_regs, MII_REG_BMCR, BMCR); - } -} - -/** - * safe_disable_mii_autopoll - autopoll off - * @regs: velocity registers - * - * Turn off the autopoll and wait for it to disable on the chip - */ - -static void safe_disable_mii_autopoll(struct mac_regs *regs) -{ - u16 ww; - - /* turn off MAUTO */ - writeb(0, ®s->MIICR); - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - udelay(1); - if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, ®s->MIISR)) - break; - } -} - -/** - * enable_mii_autopoll - turn on autopolling - * @regs: velocity registers - * - * Enable the MII link status autopoll feature on the Velocity - * hardware. Wait for it to enable. - */ - -static void enable_mii_autopoll(struct mac_regs *regs) -{ - unsigned int ii; - - writeb(0, &(regs->MIICR)); - writeb(MIIADR_SWMPL, ®s->MIIADR); - - for (ii = 0; ii < W_MAX_TIMEOUT; ii++) { - udelay(1); - if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, ®s->MIISR)) - break; - } - - writeb(MIICR_MAUTO, ®s->MIICR); - - for (ii = 0; ii < W_MAX_TIMEOUT; ii++) { - udelay(1); - if (!BYTE_REG_BITS_IS_ON(MIISR_MIDLE, ®s->MIISR)) - break; - } - -} - -/** - * velocity_mii_read - read MII data - * @regs: velocity registers - * @index: MII register index - * @data: buffer for received data - * - * Perform a single read of an MII 16bit register. Returns zero - * on success or -ETIMEDOUT if the PHY did not respond. - */ - -static int velocity_mii_read(struct mac_regs *regs, u8 index, u16 * data) -{ - u16 ww; - - /* - * Disable MIICR_MAUTO, so that mii addr can be set normally - */ - safe_disable_mii_autopoll(regs); - - writeb(index, ®s->MIIADR); - - BYTE_REG_BITS_ON(MIICR_RCMD, ®s->MIICR); - - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(readb(®s->MIICR) & MIICR_RCMD)) - break; - } - - *data = readw(®s->MIIDATA); - - enable_mii_autopoll(regs); - if (ww == W_MAX_TIMEOUT) - return -1; - return 0; -} - -/** - * velocity_mii_write - write MII data - * @regs: velocity registers - * @index: MII register index - * @data: 16bit data for the MII register - * - * Perform a single write to an MII 16bit register. Returns zero - * on success or -ETIMEDOUT if the PHY did not respond. - */ - -static int velocity_mii_write(struct mac_regs *regs, u8 mii_addr, u16 data) -{ - u16 ww; - - /* - * Disable MIICR_MAUTO, so that mii addr can be set normally - */ - safe_disable_mii_autopoll(regs); - - /* MII reg offset */ - writeb(mii_addr, ®s->MIIADR); - /* set MII data */ - writew(data, ®s->MIIDATA); - - /* turn on MIICR_WCMD */ - BYTE_REG_BITS_ON(MIICR_WCMD, ®s->MIICR); - - /* W_MAX_TIMEOUT is the timeout period */ - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - udelay(5); - if (!(readb(®s->MIICR) & MIICR_WCMD)) - break; - } - enable_mii_autopoll(regs); - - if (ww == W_MAX_TIMEOUT) - return -1; - return 0; -} - -/** - * velocity_get_opt_media_mode - get media selection - * @vptr: velocity adapter - * - * Get the media mode stored in EEPROM or module options and load - * mii_status accordingly. The requested link state information - * is also returned. - */ - -static u32 velocity_get_opt_media_mode(struct velocity_info *vptr) -{ - u32 status = 0; - - switch (vptr->options.spd_dpx) { - case SPD_DPX_AUTO: - status = VELOCITY_AUTONEG_ENABLE; - break; - case SPD_DPX_100_FULL: - status = VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL; - break; - case SPD_DPX_10_FULL: - status = VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL; - break; - case SPD_DPX_100_HALF: - status = VELOCITY_SPEED_100; - break; - case SPD_DPX_10_HALF: - status = VELOCITY_SPEED_10; - break; - } - vptr->mii_status = status; - return status; -} - -/** - * mii_set_auto_on - autonegotiate on - * @vptr: velocity - * - * Enable autonegotation on this interface - */ - -static void mii_set_auto_on(struct velocity_info *vptr) -{ - if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs)) - MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs); - else - MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); -} - - -/* -static void mii_set_auto_off(struct velocity_info * vptr) -{ - MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); -} -*/ - -/** - * set_mii_flow_control - flow control setup - * @vptr: velocity interface - * - * Set up the flow control on this interface according to - * the supplied user/eeprom options. - */ - -static void set_mii_flow_control(struct velocity_info *vptr) -{ - /*Enable or Disable PAUSE in ANAR */ - switch (vptr->options.flow_cntl) { - case FLOW_CNTL_TX: - MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs); - MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs); - break; - - case FLOW_CNTL_RX: - MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs); - MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs); - break; - - case FLOW_CNTL_TX_RX: - MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs); - MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs); - break; - - case FLOW_CNTL_DISABLE: - MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs); - MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR, - vptr->mac_regs); - break; - default: - break; - } -} - -/** - * velocity_set_media_mode - set media mode - * @mii_status: old MII link state - * - * Check the media link state and configure the flow control - * PHY and also velocity hardware setup accordingly. In particular - * we need to set up CD polling and frame bursting. - */ - -static int velocity_set_media_mode(struct velocity_info *vptr, - u32 mii_status) -{ - struct mac_regs *regs = vptr->mac_regs; - - vptr->mii_status = mii_check_media_mode(vptr->mac_regs); - - /* Set mii link status */ - set_mii_flow_control(vptr); - - if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201) { - MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, - vptr->mac_regs); - } - - /* - * If connection type is AUTO - */ - if (mii_status & VELOCITY_AUTONEG_ENABLE) { - printf("Velocity is AUTO mode\n"); - /* clear force MAC mode bit */ - BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, ®s->CHIPGCR); - /* set duplex mode of MAC according to duplex mode of MII */ - MII_REG_BITS_ON(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10, - MII_REG_ANAR, vptr->mac_regs); - MII_REG_BITS_ON(G1000CR_1000FD | G1000CR_1000, - MII_REG_G1000CR, vptr->mac_regs); - MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR, - vptr->mac_regs); - - /* enable AUTO-NEGO mode */ - mii_set_auto_on(vptr); - } else { - u16 ANAR; - u8 CHIPGCR; - - /* - * 1. if it's 3119, disable frame bursting in halfduplex mode - * and enable it in fullduplex mode - * 2. set correct MII/GMII and half/full duplex mode in CHIPGCR - * 3. only enable CD heart beat counter in 10HD mode - */ - - /* set force MAC mode bit */ - BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR); - - CHIPGCR = readb(®s->CHIPGCR); - CHIPGCR &= ~CHIPGCR_FCGMII; - - if (mii_status & VELOCITY_DUPLEX_FULL) { - CHIPGCR |= CHIPGCR_FCFDX; - writeb(CHIPGCR, ®s->CHIPGCR); - printf - ("DEBUG: set Velocity to forced full mode\n"); - if (vptr->rev_id < REV_ID_VT3216_A0) - BYTE_REG_BITS_OFF(TCR_TB2BDIS, ®s->TCR); - } else { - CHIPGCR &= ~CHIPGCR_FCFDX; - printf - ("DEBUG: set Velocity to forced half mode\n"); - writeb(CHIPGCR, ®s->CHIPGCR); - if (vptr->rev_id < REV_ID_VT3216_A0) - BYTE_REG_BITS_ON(TCR_TB2BDIS, ®s->TCR); - } - - MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000, - MII_REG_G1000CR, vptr->mac_regs); - - if (!(mii_status & VELOCITY_DUPLEX_FULL) - && (mii_status & VELOCITY_SPEED_10)) { - BYTE_REG_BITS_OFF(TESTCFG_HBDIS, ®s->TESTCFG); - } else { - BYTE_REG_BITS_ON(TESTCFG_HBDIS, ®s->TESTCFG); - } - /* MII_REG_BITS_OFF(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); */ - velocity_mii_read(vptr->mac_regs, MII_REG_ANAR, &ANAR); - ANAR &= (~(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)); - if (mii_status & VELOCITY_SPEED_100) { - if (mii_status & VELOCITY_DUPLEX_FULL) - ANAR |= ANAR_TXFD; - else - ANAR |= ANAR_TX; - } else { - if (mii_status & VELOCITY_DUPLEX_FULL) - ANAR |= ANAR_10FD; - else - ANAR |= ANAR_10; - } - velocity_mii_write(vptr->mac_regs, MII_REG_ANAR, ANAR); - /* enable AUTO-NEGO mode */ - mii_set_auto_on(vptr); - /* MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); */ - } - /* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */ - /* vptr->mii_status=check_connection_type(vptr->mac_regs); */ - return VELOCITY_LINK_CHANGE; -} - -/** - * mii_check_media_mode - check media state - * @regs: velocity registers - * - * Check the current MII status and determine the link status - * accordingly - */ - -static u32 mii_check_media_mode(struct mac_regs *regs) -{ - u32 status = 0; - u16 ANAR; - - if (!MII_REG_BITS_IS_ON(BMSR_LNK, MII_REG_BMSR, regs)) - status |= VELOCITY_LINK_FAIL; - - if (MII_REG_BITS_IS_ON(G1000CR_1000FD, MII_REG_G1000CR, regs)) - status |= VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL; - else if (MII_REG_BITS_IS_ON(G1000CR_1000, MII_REG_G1000CR, regs)) - status |= (VELOCITY_SPEED_1000); - else { - velocity_mii_read(regs, MII_REG_ANAR, &ANAR); - if (ANAR & ANAR_TXFD) - status |= - (VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL); - else if (ANAR & ANAR_TX) - status |= VELOCITY_SPEED_100; - else if (ANAR & ANAR_10FD) - status |= - (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL); - else - status |= (VELOCITY_SPEED_10); - } - - if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) { - velocity_mii_read(regs, MII_REG_ANAR, &ANAR); - if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) - == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) { - if (MII_REG_BITS_IS_ON - (G1000CR_1000 | G1000CR_1000FD, - MII_REG_G1000CR, regs)) - status |= VELOCITY_AUTONEG_ENABLE; - } - } - - return status; -} - -static u32 check_connection_type(struct mac_regs *regs) -{ - u32 status = 0; - u8 PHYSR0; - u16 ANAR; - PHYSR0 = readb(®s->PHYSR0); - - /* - if (!(PHYSR0 & PHYSR0_LINKGD)) - status|=VELOCITY_LINK_FAIL; - */ - - if (PHYSR0 & PHYSR0_FDPX) - status |= VELOCITY_DUPLEX_FULL; - - if (PHYSR0 & PHYSR0_SPDG) - status |= VELOCITY_SPEED_1000; - if (PHYSR0 & PHYSR0_SPD10) - status |= VELOCITY_SPEED_10; - else - status |= VELOCITY_SPEED_100; - - if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) { - velocity_mii_read(regs, MII_REG_ANAR, &ANAR); - if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) - == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) { - if (MII_REG_BITS_IS_ON - (G1000CR_1000 | G1000CR_1000FD, - MII_REG_G1000CR, regs)) - status |= VELOCITY_AUTONEG_ENABLE; - } - } - - return status; -} - -/** - * enable_flow_control_ability - flow control - * @vptr: veloity to configure - * - * Set up flow control according to the flow control options - * determined by the eeprom/configuration. - */ - -static void enable_flow_control_ability(struct velocity_info *vptr) -{ - - struct mac_regs *regs = vptr->mac_regs; - - switch (vptr->options.flow_cntl) { - - case FLOW_CNTL_DEFAULT: - if (BYTE_REG_BITS_IS_ON(PHYSR0_RXFLC, ®s->PHYSR0)) - writel(CR0_FDXRFCEN, ®s->CR0Set); - else - writel(CR0_FDXRFCEN, ®s->CR0Clr); - - if (BYTE_REG_BITS_IS_ON(PHYSR0_TXFLC, ®s->PHYSR0)) - writel(CR0_FDXTFCEN, ®s->CR0Set); - else - writel(CR0_FDXTFCEN, ®s->CR0Clr); - break; - - case FLOW_CNTL_TX: - writel(CR0_FDXTFCEN, ®s->CR0Set); - writel(CR0_FDXRFCEN, ®s->CR0Clr); - break; - - case FLOW_CNTL_RX: - writel(CR0_FDXRFCEN, ®s->CR0Set); - writel(CR0_FDXTFCEN, ®s->CR0Clr); - break; - - case FLOW_CNTL_TX_RX: - writel(CR0_FDXTFCEN, ®s->CR0Set); - writel(CR0_FDXRFCEN, ®s->CR0Set); - break; - - case FLOW_CNTL_DISABLE: - writel(CR0_FDXRFCEN, ®s->CR0Clr); - writel(CR0_FDXTFCEN, ®s->CR0Clr); - break; - - default: - break; - } - -} - -/* FIXME: Move to pci.c */ -/** - * pci_set_power_state - Set the power state of a PCI device - * @dev: PCI device to be suspended - * @state: Power state we're entering - * - * Transition a device to a new power state, using the Power Management - * Capabilities in the device's config space. - * - * RETURN VALUE: - * -EINVAL if trying to enter a lower state than we're already in. - * 0 if we're already in the requested state. - * -EIO if device does not support PCI PM. - * 0 if we can successfully change the power state. - */ - -int pci_set_power_state(struct pci_device *dev, int state) -{ - int pm; - u16 pmcsr; - int current_state = 0; - - /* bound the state we're entering */ - if (state > 3) - state = 3; - - /* Validate current state: - * Can enter D0 from any state, but if we can only go deeper - * to sleep if we're already in a low power state - */ - if (state > 0 && current_state > state) - return -1; - else if (current_state == state) - return 0; /* we're already there */ - - /* find PCI PM capability in list */ - pm = pci_find_capability(dev, PCI_CAP_ID_PM); - - /* abort if the device doesn't support PM capabilities */ - if (!pm) - return -2; - - /* check if this device supports the desired state */ - if (state == 1 || state == 2) { - u16 pmc; - pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc); - if (state == 1 && !(pmc & PCI_PM_CAP_D1)) - return -2; - else if (state == 2 && !(pmc & PCI_PM_CAP_D2)) - return -2; - } - - /* If we're in D3, force entire word to 0. - * This doesn't affect PME_Status, disables PME_En, and - * sets PowerState to 0. - */ - if (current_state >= 3) - pmcsr = 0; - else { - pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); - pmcsr &= ~PCI_PM_CTRL_STATE_MASK; - pmcsr |= state; - } - - /* enter specified state */ - pci_write_config_word(dev, pm + PCI_PM_CTRL, pmcsr); - - /* Mandatory power management transition delays */ - /* see PCI PM 1.1 5.6.1 table 18 */ - if (state == 3 || current_state == 3) - mdelay(10); - else if (state == 2 || current_state == 2) - udelay(200); - current_state = state; - - return 0; -} - -static struct pci_device_id velocity_nics[] = { - PCI_ROM(0x1106, 0x3119, "via-velocity", "VIA Networking Velocity Family Gigabit Ethernet Adapter", 0), -}; - -PCI_DRIVER ( velocity_driver, velocity_nics, PCI_NO_CLASS ); - -DRIVER ( "VIA-VELOCITY/PCI", nic_driver, pci_driver, velocity_driver, - velocity_probe, velocity_disable ); diff --git a/src/drivers/net/via-velocity.h b/src/drivers/net/via-velocity.h deleted file mode 100644 index 753fe445..00000000 --- a/src/drivers/net/via-velocity.h +++ /dev/null @@ -1,1932 +0,0 @@ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * This software may be redistributed and/or modified under - * the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * File: via-velocity.h - * - * Purpose: Header file to define driver's private structures. - * - * Author: Chuang Liang-Shing, AJ Jiang - * - * Date: Jan 24, 2003 - * - * Changes for Etherboot Port: - * Copyright (c) 2006 by Timothy Legge <tlegge@rogers.com> - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef VELOCITY_H -#define VELOCITY_H - -#define VELOCITY_TX_CSUM_SUPPORT - -#define VELOCITY_NAME "via-velocity" -#define VELOCITY_FULL_DRV_NAM "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver" -#define VELOCITY_VERSION "1.13" - -#define PKT_BUF_SZ 1564 - -#define MAX_UNITS 8 -#define OPTION_DEFAULT { [0 ... MAX_UNITS-1] = -1} - -#define REV_ID_VT6110 (0) - -#define BYTE_REG_BITS_ON(x,p) do { writeb(readb((p))|(x),(p));} while (0) -#define WORD_REG_BITS_ON(x,p) do { writew(readw((p))|(x),(p));} while (0) -#define DWORD_REG_BITS_ON(x,p) do { writel(readl((p))|(x),(p));} while (0) - -#define BYTE_REG_BITS_IS_ON(x,p) (readb((p)) & (x)) -#define WORD_REG_BITS_IS_ON(x,p) (readw((p)) & (x)) -#define DWORD_REG_BITS_IS_ON(x,p) (readl((p)) & (x)) - -#define BYTE_REG_BITS_OFF(x,p) do { writeb(readb((p)) & (~(x)),(p));} while (0) -#define WORD_REG_BITS_OFF(x,p) do { writew(readw((p)) & (~(x)),(p));} while (0) -#define DWORD_REG_BITS_OFF(x,p) do { writel(readl((p)) & (~(x)),(p));} while (0) - -#define BYTE_REG_BITS_SET(x,m,p) do { writeb( (readb((p)) & (~(m))) |(x),(p));} while (0) -#define WORD_REG_BITS_SET(x,m,p) do { writew( (readw((p)) & (~(m))) |(x),(p));} while (0) -#define DWORD_REG_BITS_SET(x,m,p) do { writel( (readl((p)) & (~(m)))|(x),(p));} while (0) - -#define VAR_USED(p) do {(p)=(p);} while (0) - -/* - * Purpose: Structures for MAX RX/TX descriptors. - */ - - -#define B_OWNED_BY_CHIP 1 -#define B_OWNED_BY_HOST 0 - -/* - * Bits in the RSR0 register - */ - -#define RSR_DETAG 0x0080 -#define RSR_SNTAG 0x0040 -#define RSR_RXER 0x0020 -#define RSR_RL 0x0010 -#define RSR_CE 0x0008 -#define RSR_FAE 0x0004 -#define RSR_CRC 0x0002 -#define RSR_VIDM 0x0001 - -/* - * Bits in the RSR1 register - */ - -#define RSR_RXOK 0x8000 // rx OK -#define RSR_PFT 0x4000 // Perfect filtering address match -#define RSR_MAR 0x2000 // MAC accept multicast address packet -#define RSR_BAR 0x1000 // MAC accept broadcast address packet -#define RSR_PHY 0x0800 // MAC accept physical address packet -#define RSR_VTAG 0x0400 // 802.1p/1q tagging packet indicator -#define RSR_STP 0x0200 // start of packet -#define RSR_EDP 0x0100 // end of packet - -/* - * Bits in the RSR1 register - */ - -#define RSR1_RXOK 0x80 // rx OK -#define RSR1_PFT 0x40 // Perfect filtering address match -#define RSR1_MAR 0x20 // MAC accept multicast address packet -#define RSR1_BAR 0x10 // MAC accept broadcast address packet -#define RSR1_PHY 0x08 // MAC accept physical address packet -#define RSR1_VTAG 0x04 // 802.1p/1q tagging packet indicator -#define RSR1_STP 0x02 // start of packet -#define RSR1_EDP 0x01 // end of packet - -/* - * Bits in the CSM register - */ - -#define CSM_IPOK 0x40 //IP Checkusm validatiaon ok -#define CSM_TUPOK 0x20 //TCP/UDP Checkusm validatiaon ok -#define CSM_FRAG 0x10 //Fragment IP datagram -#define CSM_IPKT 0x04 //Received an IP packet -#define CSM_TCPKT 0x02 //Received a TCP packet -#define CSM_UDPKT 0x01 //Received a UDP packet - -/* - * Bits in the TSR0 register - */ - -#define TSR0_ABT 0x0080 // Tx abort because of excessive collision -#define TSR0_OWT 0x0040 // Jumbo frame Tx abort -#define TSR0_OWC 0x0020 // Out of window collision -#define TSR0_COLS 0x0010 // experience collision in this transmit event -#define TSR0_NCR3 0x0008 // collision retry counter[3] -#define TSR0_NCR2 0x0004 // collision retry counter[2] -#define TSR0_NCR1 0x0002 // collision retry counter[1] -#define TSR0_NCR0 0x0001 // collision retry counter[0] -#define TSR0_TERR 0x8000 // -#define TSR0_FDX 0x4000 // current transaction is serviced by full duplex mode -#define TSR0_GMII 0x2000 // current transaction is serviced by GMII mode -#define TSR0_LNKFL 0x1000 // packet serviced during link down -#define TSR0_SHDN 0x0400 // shutdown case -#define TSR0_CRS 0x0200 // carrier sense lost -#define TSR0_CDH 0x0100 // AQE test fail (CD heartbeat) - -/* - * Bits in the TSR1 register - */ - -#define TSR1_TERR 0x80 // -#define TSR1_FDX 0x40 // current transaction is serviced by full duplex mode -#define TSR1_GMII 0x20 // current transaction is serviced by GMII mode -#define TSR1_LNKFL 0x10 // packet serviced during link down -#define TSR1_SHDN 0x04 // shutdown case -#define TSR1_CRS 0x02 // carrier sense lost -#define TSR1_CDH 0x01 // AQE test fail (CD heartbeat) - -// -// Bits in the TCR0 register -// -#define TCR0_TIC 0x80 // assert interrupt immediately while descriptor has been send complete -#define TCR0_PIC 0x40 // priority interrupt request, INA# is issued over adaptive interrupt scheme -#define TCR0_VETAG 0x20 // enable VLAN tag -#define TCR0_IPCK 0x10 // request IP checksum calculation. -#define TCR0_UDPCK 0x08 // request UDP checksum calculation. -#define TCR0_TCPCK 0x04 // request TCP checksum calculation. -#define TCR0_JMBO 0x02 // indicate a jumbo packet in GMAC side -#define TCR0_CRC 0x01 // disable CRC generation - -#define TCPLS_NORMAL 3 -#define TCPLS_START 2 -#define TCPLS_END 1 -#define TCPLS_MED 0 - - -// max transmit or receive buffer size -#define CB_RX_BUF_SIZE 2048UL // max buffer size - // NOTE: must be multiple of 4 - -#define CB_MAX_RD_NUM 512 // MAX # of RD -#define CB_MAX_TD_NUM 256 // MAX # of TD - -#define CB_INIT_RD_NUM_3119 128 // init # of RD, for setup VT3119 -#define CB_INIT_TD_NUM_3119 64 // init # of TD, for setup VT3119 - -#define CB_INIT_RD_NUM 128 // init # of RD, for setup default -#define CB_INIT_TD_NUM 64 // init # of TD, for setup default - -// for 3119 -#define CB_TD_RING_NUM 4 // # of TD rings. -#define CB_MAX_SEG_PER_PKT 7 // max data seg per packet (Tx) - - -/* - * If collisions excess 15 times , tx will abort, and - * if tx fifo underflow, tx will fail - * we should try to resend it - */ - -#define CB_MAX_TX_ABORT_RETRY 3 - -/* - * Receive descriptor - */ - -struct rdesc0 { - u16 RSR; /* Receive status */ - u16 len:14; /* Received packet length */ - u16 reserved:1; - u16 owner:1; /* Who owns this buffer ? */ -}; - -struct rdesc1 { - u16 PQTAG; - u8 CSM; - u8 IPKT; -}; - -struct rx_desc { - struct rdesc0 rdesc0; - struct rdesc1 rdesc1; - u32 pa_low; /* Low 32 bit PCI address */ - u16 pa_high; /* Next 16 bit PCI address (48 total) */ - u16 len:15; /* Frame size */ - u16 inten:1; /* Enable interrupt */ -} __attribute__ ((__packed__)); - -/* - * Transmit descriptor - */ - -struct tdesc0 { - u16 TSR; /* Transmit status register */ - u16 pktsize:14; /* Size of frame */ - u16 reserved:1; - u16 owner:1; /* Who owns the buffer */ -}; - -struct pqinf { /* Priority queue info */ - u16 VID:12; - u16 CFI:1; - u16 priority:3; -} __attribute__ ((__packed__)); - -struct tdesc1 { - struct pqinf pqinf; - u8 TCR; - u8 TCPLS:2; - u8 reserved:2; - u8 CMDZ:4; -} __attribute__ ((__packed__)); - -struct td_buf { - u32 pa_low; - u16 pa_high; - u16 bufsize:14; - u16 reserved:1; - u16 queue:1; -} __attribute__ ((__packed__)); - -struct tx_desc { - struct tdesc0 tdesc0; - struct tdesc1 tdesc1; - struct td_buf td_buf[7]; -}; - -#ifdef LINUX -struct velocity_rd_info { - struct sk_buff *skb; - dma_addr_t skb_dma; -}; - - -/** - * alloc_rd_info - allocate an rd info block - * - * Alocate and initialize a receive info structure used for keeping - * track of kernel side information related to each receive - * descriptor we are using - */ - -static inline struct velocity_rd_info *alloc_rd_info(void) -{ - struct velocity_rd_info *ptr; - if ((ptr = - kmalloc(sizeof(struct velocity_rd_info), GFP_ATOMIC)) == NULL) - return NULL; - else { - memset(ptr, 0, sizeof(struct velocity_rd_info)); - return ptr; - } -} - -/* - * Used to track transmit side buffers. - */ - -struct velocity_td_info { - struct sk_buff *skb; - u8 *buf; - int nskb_dma; - dma_addr_t skb_dma[7]; - dma_addr_t buf_dma; -}; - -#endif -enum { - OWNED_BY_HOST = 0, - OWNED_BY_NIC = 1 -} velocity_owner; - - -/* - * MAC registers and macros. - */ - - -#define MCAM_SIZE 64 -#define VCAM_SIZE 64 -#define TX_QUEUE_NO 4 - -#define MAX_HW_MIB_COUNTER 32 -#define VELOCITY_MIN_MTU (1514-14) -#define VELOCITY_MAX_MTU (9000) - -/* - * Registers in the MAC - */ - -#define MAC_REG_PAR 0x00 // physical address -#define MAC_REG_RCR 0x06 -#define MAC_REG_TCR 0x07 -#define MAC_REG_CR0_SET 0x08 -#define MAC_REG_CR1_SET 0x09 -#define MAC_REG_CR2_SET 0x0A -#define MAC_REG_CR3_SET 0x0B -#define MAC_REG_CR0_CLR 0x0C -#define MAC_REG_CR1_CLR 0x0D -#define MAC_REG_CR2_CLR 0x0E -#define MAC_REG_CR3_CLR 0x0F -#define MAC_REG_MAR 0x10 -#define MAC_REG_CAM 0x10 -#define MAC_REG_DEC_BASE_HI 0x18 -#define MAC_REG_DBF_BASE_HI 0x1C -#define MAC_REG_ISR_CTL 0x20 -#define MAC_REG_ISR_HOTMR 0x20 -#define MAC_REG_ISR_TSUPTHR 0x20 -#define MAC_REG_ISR_RSUPTHR 0x20 -#define MAC_REG_ISR_CTL1 0x21 -#define MAC_REG_TXE_SR 0x22 -#define MAC_REG_RXE_SR 0x23 -#define MAC_REG_ISR 0x24 -#define MAC_REG_ISR0 0x24 -#define MAC_REG_ISR1 0x25 -#define MAC_REG_ISR2 0x26 -#define MAC_REG_ISR3 0x27 -#define MAC_REG_IMR 0x28 -#define MAC_REG_IMR0 0x28 -#define MAC_REG_IMR1 0x29 -#define MAC_REG_IMR2 0x2A -#define MAC_REG_IMR3 0x2B -#define MAC_REG_TDCSR_SET 0x30 -#define MAC_REG_RDCSR_SET 0x32 -#define MAC_REG_TDCSR_CLR 0x34 -#define MAC_REG_RDCSR_CLR 0x36 -#define MAC_REG_RDBASE_LO 0x38 -#define MAC_REG_RDINDX 0x3C -#define MAC_REG_TDBASE_LO 0x40 -#define MAC_REG_RDCSIZE 0x50 -#define MAC_REG_TDCSIZE 0x52 -#define MAC_REG_TDINDX 0x54 -#define MAC_REG_TDIDX0 0x54 -#define MAC_REG_TDIDX1 0x56 -#define MAC_REG_TDIDX2 0x58 -#define MAC_REG_TDIDX3 0x5A -#define MAC_REG_PAUSE_TIMER 0x5C -#define MAC_REG_RBRDU 0x5E -#define MAC_REG_FIFO_TEST0 0x60 -#define MAC_REG_FIFO_TEST1 0x64 -#define MAC_REG_CAMADDR 0x68 -#define MAC_REG_CAMCR 0x69 -#define MAC_REG_GFTEST 0x6A -#define MAC_REG_FTSTCMD 0x6B -#define MAC_REG_MIICFG 0x6C -#define MAC_REG_MIISR 0x6D -#define MAC_REG_PHYSR0 0x6E -#define MAC_REG_PHYSR1 0x6F -#define MAC_REG_MIICR 0x70 -#define MAC_REG_MIIADR 0x71 -#define MAC_REG_MIIDATA 0x72 -#define MAC_REG_SOFT_TIMER0 0x74 -#define MAC_REG_SOFT_TIMER1 0x76 -#define MAC_REG_CFGA 0x78 -#define MAC_REG_CFGB 0x79 -#define MAC_REG_CFGC 0x7A -#define MAC_REG_CFGD 0x7B -#define MAC_REG_DCFG0 0x7C -#define MAC_REG_DCFG1 0x7D -#define MAC_REG_MCFG0 0x7E -#define MAC_REG_MCFG1 0x7F - -#define MAC_REG_TBIST 0x80 -#define MAC_REG_RBIST 0x81 -#define MAC_REG_PMCC 0x82 -#define MAC_REG_STICKHW 0x83 -#define MAC_REG_MIBCR 0x84 -#define MAC_REG_EERSV 0x85 -#define MAC_REG_REVID 0x86 -#define MAC_REG_MIBREAD 0x88 -#define MAC_REG_BPMA 0x8C -#define MAC_REG_EEWR_DATA 0x8C -#define MAC_REG_BPMD_WR 0x8F -#define MAC_REG_BPCMD 0x90 -#define MAC_REG_BPMD_RD 0x91 -#define MAC_REG_EECHKSUM 0x92 -#define MAC_REG_EECSR 0x93 -#define MAC_REG_EERD_DATA 0x94 -#define MAC_REG_EADDR 0x96 -#define MAC_REG_EMBCMD 0x97 -#define MAC_REG_JMPSR0 0x98 -#define MAC_REG_JMPSR1 0x99 -#define MAC_REG_JMPSR2 0x9A -#define MAC_REG_JMPSR3 0x9B -#define MAC_REG_CHIPGSR 0x9C -#define MAC_REG_TESTCFG 0x9D -#define MAC_REG_DEBUG 0x9E -#define MAC_REG_CHIPGCR 0x9F -#define MAC_REG_WOLCR0_SET 0xA0 -#define MAC_REG_WOLCR1_SET 0xA1 -#define MAC_REG_PWCFG_SET 0xA2 -#define MAC_REG_WOLCFG_SET 0xA3 -#define MAC_REG_WOLCR0_CLR 0xA4 -#define MAC_REG_WOLCR1_CLR 0xA5 -#define MAC_REG_PWCFG_CLR 0xA6 -#define MAC_REG_WOLCFG_CLR 0xA7 -#define MAC_REG_WOLSR0_SET 0xA8 -#define MAC_REG_WOLSR1_SET 0xA9 -#define MAC_REG_WOLSR0_CLR 0xAC -#define MAC_REG_WOLSR1_CLR 0xAD -#define MAC_REG_PATRN_CRC0 0xB0 -#define MAC_REG_PATRN_CRC1 0xB2 -#define MAC_REG_PATRN_CRC2 0xB4 -#define MAC_REG_PATRN_CRC3 0xB6 -#define MAC_REG_PATRN_CRC4 0xB8 -#define MAC_REG_PATRN_CRC5 0xBA -#define MAC_REG_PATRN_CRC6 0xBC -#define MAC_REG_PATRN_CRC7 0xBE -#define MAC_REG_BYTEMSK0_0 0xC0 -#define MAC_REG_BYTEMSK0_1 0xC4 -#define MAC_REG_BYTEMSK0_2 0xC8 -#define MAC_REG_BYTEMSK0_3 0xCC -#define MAC_REG_BYTEMSK1_0 0xD0 -#define MAC_REG_BYTEMSK1_1 0xD4 -#define MAC_REG_BYTEMSK1_2 0xD8 -#define MAC_REG_BYTEMSK1_3 0xDC -#define MAC_REG_BYTEMSK2_0 0xE0 -#define MAC_REG_BYTEMSK2_1 0xE4 -#define MAC_REG_BYTEMSK2_2 0xE8 -#define MAC_REG_BYTEMSK2_3 0xEC -#define MAC_REG_BYTEMSK3_0 0xF0 -#define MAC_REG_BYTEMSK3_1 0xF4 -#define MAC_REG_BYTEMSK3_2 0xF8 -#define MAC_REG_BYTEMSK3_3 0xFC - -/* - * Bits in the RCR register - */ - -#define RCR_AS 0x80 -#define RCR_AP 0x40 -#define RCR_AL 0x20 -#define RCR_PROM 0x10 -#define RCR_AB 0x08 -#define RCR_AM 0x04 -#define RCR_AR 0x02 -#define RCR_SEP 0x01 - -/* - * Bits in the TCR register - */ - -#define TCR_TB2BDIS 0x80 -#define TCR_COLTMC1 0x08 -#define TCR_COLTMC0 0x04 -#define TCR_LB1 0x02 /* loopback[1] */ -#define TCR_LB0 0x01 /* loopback[0] */ - -/* - * Bits in the CR0 register - */ - -#define CR0_TXON 0x00000008UL -#define CR0_RXON 0x00000004UL -#define CR0_STOP 0x00000002UL /* stop MAC, default = 1 */ -#define CR0_STRT 0x00000001UL /* start MAC */ -#define CR0_SFRST 0x00008000UL /* software reset */ -#define CR0_TM1EN 0x00004000UL -#define CR0_TM0EN 0x00002000UL -#define CR0_DPOLL 0x00000800UL /* disable rx/tx auto polling */ -#define CR0_DISAU 0x00000100UL -#define CR0_XONEN 0x00800000UL -#define CR0_FDXTFCEN 0x00400000UL /* full-duplex TX flow control enable */ -#define CR0_FDXRFCEN 0x00200000UL /* full-duplex RX flow control enable */ -#define CR0_HDXFCEN 0x00100000UL /* half-duplex flow control enable */ -#define CR0_XHITH1 0x00080000UL /* TX XON high threshold 1 */ -#define CR0_XHITH0 0x00040000UL /* TX XON high threshold 0 */ -#define CR0_XLTH1 0x00020000UL /* TX pause frame low threshold 1 */ -#define CR0_XLTH0 0x00010000UL /* TX pause frame low threshold 0 */ -#define CR0_GSPRST 0x80000000UL -#define CR0_FORSRST 0x40000000UL -#define CR0_FPHYRST 0x20000000UL -#define CR0_DIAG 0x10000000UL -#define CR0_INTPCTL 0x04000000UL -#define CR0_GINTMSK1 0x02000000UL -#define CR0_GINTMSK0 0x01000000UL - -/* - * Bits in the CR1 register - */ - -#define CR1_SFRST 0x80 /* software reset */ -#define CR1_TM1EN 0x40 -#define CR1_TM0EN 0x20 -#define CR1_DPOLL 0x08 /* disable rx/tx auto polling */ -#define CR1_DISAU 0x01 - -/* - * Bits in the CR2 register - */ - -#define CR2_XONEN 0x80 -#define CR2_FDXTFCEN 0x40 /* full-duplex TX flow control enable */ -#define CR2_FDXRFCEN 0x20 /* full-duplex RX flow control enable */ -#define CR2_HDXFCEN 0x10 /* half-duplex flow control enable */ -#define CR2_XHITH1 0x08 /* TX XON high threshold 1 */ -#define CR2_XHITH0 0x04 /* TX XON high threshold 0 */ -#define CR2_XLTH1 0x02 /* TX pause frame low threshold 1 */ -#define CR2_XLTH0 0x01 /* TX pause frame low threshold 0 */ - -/* - * Bits in the CR3 register - */ - -#define CR3_GSPRST 0x80 -#define CR3_FORSRST 0x40 -#define CR3_FPHYRST 0x20 -#define CR3_DIAG 0x10 -#define CR3_INTPCTL 0x04 -#define CR3_GINTMSK1 0x02 -#define CR3_GINTMSK0 0x01 - -#define ISRCTL_UDPINT 0x8000 -#define ISRCTL_TSUPDIS 0x4000 -#define ISRCTL_RSUPDIS 0x2000 -#define ISRCTL_PMSK1 0x1000 -#define ISRCTL_PMSK0 0x0800 -#define ISRCTL_INTPD 0x0400 -#define ISRCTL_HCRLD 0x0200 -#define ISRCTL_SCRLD 0x0100 - -/* - * Bits in the ISR_CTL1 register - */ - -#define ISRCTL1_UDPINT 0x80 -#define ISRCTL1_TSUPDIS 0x40 -#define ISRCTL1_RSUPDIS 0x20 -#define ISRCTL1_PMSK1 0x10 -#define ISRCTL1_PMSK0 0x08 -#define ISRCTL1_INTPD 0x04 -#define ISRCTL1_HCRLD 0x02 -#define ISRCTL1_SCRLD 0x01 - -/* - * Bits in the TXE_SR register - */ - -#define TXESR_TFDBS 0x08 -#define TXESR_TDWBS 0x04 -#define TXESR_TDRBS 0x02 -#define TXESR_TDSTR 0x01 - -/* - * Bits in the RXE_SR register - */ - -#define RXESR_RFDBS 0x08 -#define RXESR_RDWBS 0x04 -#define RXESR_RDRBS 0x02 -#define RXESR_RDSTR 0x01 - -/* - * Bits in the ISR register - */ - -#define ISR_ISR3 0x80000000UL -#define ISR_ISR2 0x40000000UL -#define ISR_ISR1 0x20000000UL -#define ISR_ISR0 0x10000000UL -#define ISR_TXSTLI 0x02000000UL -#define ISR_RXSTLI 0x01000000UL -#define ISR_HFLD 0x00800000UL -#define ISR_UDPI 0x00400000UL -#define ISR_MIBFI 0x00200000UL -#define ISR_SHDNI 0x00100000UL -#define ISR_PHYI 0x00080000UL -#define ISR_PWEI 0x00040000UL -#define ISR_TMR1I 0x00020000UL -#define ISR_TMR0I 0x00010000UL -#define ISR_SRCI 0x00008000UL -#define ISR_LSTPEI 0x00004000UL -#define ISR_LSTEI 0x00002000UL -#define ISR_OVFI 0x00001000UL -#define ISR_FLONI 0x00000800UL -#define ISR_RACEI 0x00000400UL -#define ISR_TXWB1I 0x00000200UL -#define ISR_TXWB0I 0x00000100UL -#define ISR_PTX3I 0x00000080UL -#define ISR_PTX2I 0x00000040UL -#define ISR_PTX1I 0x00000020UL -#define ISR_PTX0I 0x00000010UL -#define ISR_PTXI 0x00000008UL -#define ISR_PRXI 0x00000004UL -#define ISR_PPTXI 0x00000002UL -#define ISR_PPRXI 0x00000001UL - -/* - * Bits in the IMR register - */ - -#define IMR_TXSTLM 0x02000000UL -#define IMR_UDPIM 0x00400000UL -#define IMR_MIBFIM 0x00200000UL -#define IMR_SHDNIM 0x00100000UL -#define IMR_PHYIM 0x00080000UL -#define IMR_PWEIM 0x00040000UL -#define IMR_TMR1IM 0x00020000UL -#define IMR_TMR0IM 0x00010000UL - -#define IMR_SRCIM 0x00008000UL -#define IMR_LSTPEIM 0x00004000UL -#define IMR_LSTEIM 0x00002000UL -#define IMR_OVFIM 0x00001000UL -#define IMR_FLONIM 0x00000800UL -#define IMR_RACEIM 0x00000400UL -#define IMR_TXWB1IM 0x00000200UL -#define IMR_TXWB0IM 0x00000100UL - -#define IMR_PTX3IM 0x00000080UL -#define IMR_PTX2IM 0x00000040UL -#define IMR_PTX1IM 0x00000020UL -#define IMR_PTX0IM 0x00000010UL -#define IMR_PTXIM 0x00000008UL -#define IMR_PRXIM 0x00000004UL -#define IMR_PPTXIM 0x00000002UL -#define IMR_PPRXIM 0x00000001UL - -/* 0x0013FB0FUL = initial value of IMR */ - -#define INT_MASK_DEF ( IMR_PPTXIM|IMR_PPRXIM| IMR_PTXIM|IMR_PRXIM | \ - IMR_PWEIM|IMR_TXWB0IM|IMR_TXWB1IM|IMR_FLONIM| \ - IMR_OVFIM|IMR_LSTEIM|IMR_LSTPEIM|IMR_SRCIM|IMR_MIBFIM|\ - IMR_SHDNIM |IMR_TMR1IM|IMR_TMR0IM|IMR_TXSTLM ) - -/* - * Bits in the TDCSR0/1, RDCSR0 register - */ - -#define TRDCSR_DEAD 0x0008 -#define TRDCSR_WAK 0x0004 -#define TRDCSR_ACT 0x0002 -#define TRDCSR_RUN 0x0001 - -/* - * Bits in the CAMADDR register - */ - -#define CAMADDR_CAMEN 0x80 -#define CAMADDR_VCAMSL 0x40 - -/* - * Bits in the CAMCR register - */ - -#define CAMCR_PS1 0x80 -#define CAMCR_PS0 0x40 -#define CAMCR_AITRPKT 0x20 -#define CAMCR_AITR16 0x10 -#define CAMCR_CAMRD 0x08 -#define CAMCR_CAMWR 0x04 -#define CAMCR_PS_CAM_MASK 0x40 -#define CAMCR_PS_CAM_DATA 0x80 -#define CAMCR_PS_MAR 0x00 - -/* - * Bits in the MIICFG register - */ - -#define MIICFG_MPO1 0x80 -#define MIICFG_MPO0 0x40 -#define MIICFG_MFDC 0x20 - -/* - * Bits in the MIISR register - */ - -#define MIISR_MIDLE 0x80 - -/* - * Bits in the PHYSR0 register - */ - -#define PHYSR0_PHYRST 0x80 -#define PHYSR0_LINKGD 0x40 -#define PHYSR0_FDPX 0x10 -#define PHYSR0_SPDG 0x08 -#define PHYSR0_SPD10 0x04 -#define PHYSR0_RXFLC 0x02 -#define PHYSR0_TXFLC 0x01 - -/* - * Bits in the PHYSR1 register - */ - -#define PHYSR1_PHYTBI 0x01 - -/* - * Bits in the MIICR register - */ - -#define MIICR_MAUTO 0x80 -#define MIICR_RCMD 0x40 -#define MIICR_WCMD 0x20 -#define MIICR_MDPM 0x10 -#define MIICR_MOUT 0x08 -#define MIICR_MDO 0x04 -#define MIICR_MDI 0x02 -#define MIICR_MDC 0x01 - -/* - * Bits in the MIIADR register - */ - -#define MIIADR_SWMPL 0x80 - -/* - * Bits in the CFGA register - */ - -#define CFGA_PMHCTG 0x08 -#define CFGA_GPIO1PD 0x04 -#define CFGA_ABSHDN 0x02 -#define CFGA_PACPI 0x01 - -/* - * Bits in the CFGB register - */ - -#define CFGB_GTCKOPT 0x80 -#define CFGB_MIIOPT 0x40 -#define CFGB_CRSEOPT 0x20 -#define CFGB_OFSET 0x10 -#define CFGB_CRANDOM 0x08 -#define CFGB_CAP 0x04 -#define CFGB_MBA 0x02 -#define CFGB_BAKOPT 0x01 - -/* - * Bits in the CFGC register - */ - -#define CFGC_EELOAD 0x80 -#define CFGC_BROPT 0x40 -#define CFGC_DLYEN 0x20 -#define CFGC_DTSEL 0x10 -#define CFGC_BTSEL 0x08 -#define CFGC_BPS2 0x04 /* bootrom select[2] */ -#define CFGC_BPS1 0x02 /* bootrom select[1] */ -#define CFGC_BPS0 0x01 /* bootrom select[0] */ - -/* - * Bits in the CFGD register - */ - -#define CFGD_IODIS 0x80 -#define CFGD_MSLVDACEN 0x40 -#define CFGD_CFGDACEN 0x20 -#define CFGD_PCI64EN 0x10 -#define CFGD_HTMRL4 0x08 - -/* - * Bits in the DCFG1 register - */ - -#define DCFG_XMWI 0x8000 -#define DCFG_XMRM 0x4000 -#define DCFG_XMRL 0x2000 -#define DCFG_PERDIS 0x1000 -#define DCFG_MRWAIT 0x0400 -#define DCFG_MWWAIT 0x0200 -#define DCFG_LATMEN 0x0100 - -/* - * Bits in the MCFG0 register - */ - -#define MCFG_RXARB 0x0080 -#define MCFG_RFT1 0x0020 -#define MCFG_RFT0 0x0010 -#define MCFG_LOWTHOPT 0x0008 -#define MCFG_PQEN 0x0004 -#define MCFG_RTGOPT 0x0002 -#define MCFG_VIDFR 0x0001 - -/* - * Bits in the MCFG1 register - */ - -#define MCFG_TXARB 0x8000 -#define MCFG_TXQBK1 0x0800 -#define MCFG_TXQBK0 0x0400 -#define MCFG_TXQNOBK 0x0200 -#define MCFG_SNAPOPT 0x0100 - -/* - * Bits in the PMCC register - */ - -#define PMCC_DSI 0x80 -#define PMCC_D2_DIS 0x40 -#define PMCC_D1_DIS 0x20 -#define PMCC_D3C_EN 0x10 -#define PMCC_D3H_EN 0x08 -#define PMCC_D2_EN 0x04 -#define PMCC_D1_EN 0x02 -#define PMCC_D0_EN 0x01 - -/* - * Bits in STICKHW - */ - -#define STICKHW_SWPTAG 0x10 -#define STICKHW_WOLSR 0x08 -#define STICKHW_WOLEN 0x04 -#define STICKHW_DS1 0x02 /* R/W by software/cfg cycle */ -#define STICKHW_DS0 0x01 /* suspend well DS write port */ - -/* - * Bits in the MIBCR register - */ - -#define MIBCR_MIBISTOK 0x80 -#define MIBCR_MIBISTGO 0x40 -#define MIBCR_MIBINC 0x20 -#define MIBCR_MIBHI 0x10 -#define MIBCR_MIBFRZ 0x08 -#define MIBCR_MIBFLSH 0x04 -#define MIBCR_MPTRINI 0x02 -#define MIBCR_MIBCLR 0x01 - -/* - * Bits in the EERSV register - */ - -#define EERSV_BOOT_RPL ((u8) 0x01) /* Boot method selection for VT6110 */ - -#define EERSV_BOOT_MASK ((u8) 0x06) -#define EERSV_BOOT_INT19 ((u8) 0x00) -#define EERSV_BOOT_INT18 ((u8) 0x02) -#define EERSV_BOOT_LOCAL ((u8) 0x04) -#define EERSV_BOOT_BEV ((u8) 0x06) - - -/* - * Bits in BPCMD - */ - -#define BPCMD_BPDNE 0x80 -#define BPCMD_EBPWR 0x02 -#define BPCMD_EBPRD 0x01 - -/* - * Bits in the EECSR register - */ - -#define EECSR_EMBP 0x40 /* eeprom embedded programming */ -#define EECSR_RELOAD 0x20 /* eeprom content reload */ -#define EECSR_DPM 0x10 /* eeprom direct programming */ -#define EECSR_ECS 0x08 /* eeprom CS pin */ -#define EECSR_ECK 0x04 /* eeprom CK pin */ -#define EECSR_EDI 0x02 /* eeprom DI pin */ -#define EECSR_EDO 0x01 /* eeprom DO pin */ - -/* - * Bits in the EMBCMD register - */ - -#define EMBCMD_EDONE 0x80 -#define EMBCMD_EWDIS 0x08 -#define EMBCMD_EWEN 0x04 -#define EMBCMD_EWR 0x02 -#define EMBCMD_ERD 0x01 - -/* - * Bits in TESTCFG register - */ - -#define TESTCFG_HBDIS 0x80 - -/* - * Bits in CHIPGCR register - */ - -#define CHIPGCR_FCGMII 0x80 -#define CHIPGCR_FCFDX 0x40 -#define CHIPGCR_FCRESV 0x20 -#define CHIPGCR_FCMODE 0x10 -#define CHIPGCR_LPSOPT 0x08 -#define CHIPGCR_TM1US 0x04 -#define CHIPGCR_TM0US 0x02 -#define CHIPGCR_PHYINTEN 0x01 - -/* - * Bits in WOLCR0 - */ - -#define WOLCR_MSWOLEN7 0x0080 /* enable pattern match filtering */ -#define WOLCR_MSWOLEN6 0x0040 -#define WOLCR_MSWOLEN5 0x0020 -#define WOLCR_MSWOLEN4 0x0010 -#define WOLCR_MSWOLEN3 0x0008 -#define WOLCR_MSWOLEN2 0x0004 -#define WOLCR_MSWOLEN1 0x0002 -#define WOLCR_MSWOLEN0 0x0001 -#define WOLCR_ARP_EN 0x0001 - -/* - * Bits in WOLCR1 - */ - -#define WOLCR_LINKOFF_EN 0x0800 /* link off detected enable */ -#define WOLCR_LINKON_EN 0x0400 /* link on detected enable */ -#define WOLCR_MAGIC_EN 0x0200 /* magic packet filter enable */ -#define WOLCR_UNICAST_EN 0x0100 /* unicast filter enable */ - - -/* - * Bits in PWCFG - */ - -#define PWCFG_PHYPWOPT 0x80 /* internal MII I/F timing */ -#define PWCFG_PCISTICK 0x40 /* PCI sticky R/W enable */ -#define PWCFG_WOLTYPE 0x20 /* pulse(1) or button (0) */ -#define PWCFG_LEGCY_WOL 0x10 -#define PWCFG_PMCSR_PME_SR 0x08 -#define PWCFG_PMCSR_PME_EN 0x04 /* control by PCISTICK */ -#define PWCFG_LEGACY_WOLSR 0x02 /* Legacy WOL_SR shadow */ -#define PWCFG_LEGACY_WOLEN 0x01 /* Legacy WOL_EN shadow */ - -/* - * Bits in WOLCFG - */ - -#define WOLCFG_PMEOVR 0x80 /* for legacy use, force PMEEN always */ -#define WOLCFG_SAM 0x20 /* accept multicast case reset, default=0 */ -#define WOLCFG_SAB 0x10 /* accept broadcast case reset, default=0 */ -#define WOLCFG_SMIIACC 0x08 /* ?? */ -#define WOLCFG_SGENWH 0x02 -#define WOLCFG_PHYINTEN 0x01 /* 0:PHYINT trigger enable, 1:use internal MII - to report status change */ -/* - * Bits in WOLSR1 - */ - -#define WOLSR_LINKOFF_INT 0x0800 -#define WOLSR_LINKON_INT 0x0400 -#define WOLSR_MAGIC_INT 0x0200 -#define WOLSR_UNICAST_INT 0x0100 - -/* - * Ethernet address filter type - */ - -#define PKT_TYPE_NONE 0x0000 /* Turn off receiver */ -#define PKT_TYPE_DIRECTED 0x0001 /* obselete, directed address is always accepted */ -#define PKT_TYPE_MULTICAST 0x0002 -#define PKT_TYPE_ALL_MULTICAST 0x0004 -#define PKT_TYPE_BROADCAST 0x0008 -#define PKT_TYPE_PROMISCUOUS 0x0020 -#define PKT_TYPE_LONG 0x2000 /* NOTE.... the definition of LONG is >2048 bytes in our chip */ -#define PKT_TYPE_RUNT 0x4000 -#define PKT_TYPE_ERROR 0x8000 /* Accept error packets, e.g. CRC error */ - -/* - * Loopback mode - */ - -#define MAC_LB_NONE 0x00 -#define MAC_LB_INTERNAL 0x01 -#define MAC_LB_EXTERNAL 0x02 - -/* - * Enabled mask value of irq - */ - -#if defined(_SIM) -#define IMR_MASK_VALUE 0x0033FF0FUL /* initial value of IMR - set IMR0 to 0x0F according to spec */ - -#else -#define IMR_MASK_VALUE 0x0013FB0FUL /* initial value of IMR - ignore MIBFI,RACEI to - reduce intr. frequency - NOTE.... do not enable NoBuf int mask at driver driver - when (1) NoBuf -> RxThreshold = SF - (2) OK -> RxThreshold = original value - */ -#endif - -/* - * Revision id - */ - -#define REV_ID_VT3119_A0 0x00 -#define REV_ID_VT3119_A1 0x01 -#define REV_ID_VT3216_A0 0x10 - -/* - * Max time out delay time - */ - -#define W_MAX_TIMEOUT 0x0FFFU - - -/* - * MAC registers as a structure. Cannot be directly accessed this - * way but generates offsets for readl/writel() calls - */ - -struct mac_regs { - volatile u8 PAR[6]; /* 0x00 */ - volatile u8 RCR; - volatile u8 TCR; - - volatile u32 CR0Set; /* 0x08 */ - volatile u32 CR0Clr; /* 0x0C */ - - volatile u8 MARCAM[8]; /* 0x10 */ - - volatile u32 DecBaseHi; /* 0x18 */ - volatile u16 DbfBaseHi; /* 0x1C */ - volatile u16 reserved_1E; - - volatile u16 ISRCTL; /* 0x20 */ - volatile u8 TXESR; - volatile u8 RXESR; - - volatile u32 ISR; /* 0x24 */ - volatile u32 IMR; - - volatile u32 TDStatusPort; /* 0x2C */ - - volatile u16 TDCSRSet; /* 0x30 */ - volatile u8 RDCSRSet; - volatile u8 reserved_33; - volatile u16 TDCSRClr; - volatile u8 RDCSRClr; - volatile u8 reserved_37; - - volatile u32 RDBaseLo; /* 0x38 */ - volatile u16 RDIdx; /* 0x3C */ - volatile u16 reserved_3E; - - volatile u32 TDBaseLo[4]; /* 0x40 */ - - volatile u16 RDCSize; /* 0x50 */ - volatile u16 TDCSize; /* 0x52 */ - volatile u16 TDIdx[4]; /* 0x54 */ - volatile u16 tx_pause_timer; /* 0x5C */ - volatile u16 RBRDU; /* 0x5E */ - - volatile u32 FIFOTest0; /* 0x60 */ - volatile u32 FIFOTest1; /* 0x64 */ - - volatile u8 CAMADDR; /* 0x68 */ - volatile u8 CAMCR; /* 0x69 */ - volatile u8 GFTEST; /* 0x6A */ - volatile u8 FTSTCMD; /* 0x6B */ - - volatile u8 MIICFG; /* 0x6C */ - volatile u8 MIISR; - volatile u8 PHYSR0; - volatile u8 PHYSR1; - volatile u8 MIICR; - volatile u8 MIIADR; - volatile u16 MIIDATA; - - volatile u16 SoftTimer0; /* 0x74 */ - volatile u16 SoftTimer1; - - volatile u8 CFGA; /* 0x78 */ - volatile u8 CFGB; - volatile u8 CFGC; - volatile u8 CFGD; - - volatile u16 DCFG; /* 0x7C */ - volatile u16 MCFG; - - volatile u8 TBIST; /* 0x80 */ - volatile u8 RBIST; - volatile u8 PMCPORT; - volatile u8 STICKHW; - - volatile u8 MIBCR; /* 0x84 */ - volatile u8 reserved_85; - volatile u8 rev_id; - volatile u8 PORSTS; - - volatile u32 MIBData; /* 0x88 */ - - volatile u16 EEWrData; - - volatile u8 reserved_8E; - volatile u8 BPMDWr; - volatile u8 BPCMD; - volatile u8 BPMDRd; - - volatile u8 EECHKSUM; /* 0x92 */ - volatile u8 EECSR; - - volatile u16 EERdData; /* 0x94 */ - volatile u8 EADDR; - volatile u8 EMBCMD; - - - volatile u8 JMPSR0; /* 0x98 */ - volatile u8 JMPSR1; - volatile u8 JMPSR2; - volatile u8 JMPSR3; - volatile u8 CHIPGSR; /* 0x9C */ - volatile u8 TESTCFG; - volatile u8 DEBUG; - volatile u8 CHIPGCR; - - volatile u16 WOLCRSet; /* 0xA0 */ - volatile u8 PWCFGSet; - volatile u8 WOLCFGSet; - - volatile u16 WOLCRClr; /* 0xA4 */ - volatile u8 PWCFGCLR; - volatile u8 WOLCFGClr; - - volatile u16 WOLSRSet; /* 0xA8 */ - volatile u16 reserved_AA; - - volatile u16 WOLSRClr; /* 0xAC */ - volatile u16 reserved_AE; - - volatile u16 PatternCRC[8]; /* 0xB0 */ - volatile u32 ByteMask[4][4]; /* 0xC0 */ -} __attribute__ ((__packed__)); - - -enum hw_mib { - HW_MIB_ifRxAllPkts = 0, - HW_MIB_ifRxOkPkts, - HW_MIB_ifTxOkPkts, - HW_MIB_ifRxErrorPkts, - HW_MIB_ifRxRuntOkPkt, - HW_MIB_ifRxRuntErrPkt, - HW_MIB_ifRx64Pkts, - HW_MIB_ifTx64Pkts, - HW_MIB_ifRx65To127Pkts, - HW_MIB_ifTx65To127Pkts, - HW_MIB_ifRx128To255Pkts, - HW_MIB_ifTx128To255Pkts, - HW_MIB_ifRx256To511Pkts, - HW_MIB_ifTx256To511Pkts, - HW_MIB_ifRx512To1023Pkts, - HW_MIB_ifTx512To1023Pkts, - HW_MIB_ifRx1024To1518Pkts, - HW_MIB_ifTx1024To1518Pkts, - HW_MIB_ifTxEtherCollisions, - HW_MIB_ifRxPktCRCE, - HW_MIB_ifRxJumboPkts, - HW_MIB_ifTxJumboPkts, - HW_MIB_ifRxMacControlFrames, - HW_MIB_ifTxMacControlFrames, - HW_MIB_ifRxPktFAE, - HW_MIB_ifRxLongOkPkt, - HW_MIB_ifRxLongPktErrPkt, - HW_MIB_ifTXSQEErrors, - HW_MIB_ifRxNobuf, - HW_MIB_ifRxSymbolErrors, - HW_MIB_ifInRangeLengthErrors, - HW_MIB_ifLateCollisions, - HW_MIB_SIZE -}; - -enum chip_type { - CHIP_TYPE_VT6110 = 1, -}; - -struct velocity_info_tbl { - enum chip_type chip_id; - char *name; - int io_size; - int txqueue; - u32 flags; -}; - -static struct velocity_info_tbl *info; - -#define mac_hw_mibs_init(regs) {\ - BYTE_REG_BITS_ON(MIBCR_MIBFRZ,&((regs)->MIBCR));\ - BYTE_REG_BITS_ON(MIBCR_MIBCLR,&((regs)->MIBCR));\ - do {}\ - while (BYTE_REG_BITS_IS_ON(MIBCR_MIBCLR,&((regs)->MIBCR)));\ - BYTE_REG_BITS_OFF(MIBCR_MIBFRZ,&((regs)->MIBCR));\ -} - -#define mac_read_isr(regs) readl(&((regs)->ISR)) -#define mac_write_isr(regs, x) writel((x),&((regs)->ISR)) -#define mac_clear_isr(regs) writel(0xffffffffL,&((regs)->ISR)) - -#define mac_write_int_mask(mask, regs) writel((mask),&((regs)->IMR)); -#define mac_disable_int(regs) writel(CR0_GINTMSK1,&((regs)->CR0Clr)) -#define mac_enable_int(regs) writel(CR0_GINTMSK1,&((regs)->CR0Set)) - -#define mac_hw_mibs_read(regs, MIBs) {\ - int i;\ - BYTE_REG_BITS_ON(MIBCR_MPTRINI,&((regs)->MIBCR));\ - for (i=0;i<HW_MIB_SIZE;i++) {\ - (MIBs)[i]=readl(&((regs)->MIBData));\ - }\ -} - -#define mac_set_dma_length(regs, n) {\ - BYTE_REG_BITS_SET((n),0x07,&((regs)->DCFG));\ -} - -#define mac_set_rx_thresh(regs, n) {\ - BYTE_REG_BITS_SET((n),(MCFG_RFT0|MCFG_RFT1),&((regs)->MCFG));\ -} - -#define mac_rx_queue_run(regs) {\ - writeb(TRDCSR_RUN, &((regs)->RDCSRSet));\ -} - -#define mac_rx_queue_wake(regs) {\ - writeb(TRDCSR_WAK, &((regs)->RDCSRSet));\ -} - -#define mac_tx_queue_run(regs, n) {\ - writew(TRDCSR_RUN<<((n)*4),&((regs)->TDCSRSet));\ -} - -#define mac_tx_queue_wake(regs, n) {\ - writew(TRDCSR_WAK<<(n*4),&((regs)->TDCSRSet));\ -} - -#define mac_eeprom_reload(regs) {\ - int i=0;\ - BYTE_REG_BITS_ON(EECSR_RELOAD,&((regs)->EECSR));\ - do {\ - udelay(10);\ - if (i++>0x1000) {\ - break;\ - }\ - }while (BYTE_REG_BITS_IS_ON(EECSR_RELOAD,&((regs)->EECSR)));\ -} - -enum velocity_cam_type { - VELOCITY_VLAN_ID_CAM = 0, - VELOCITY_MULTICAST_CAM -}; - -/** - * mac_get_cam_mask - Read a CAM mask - * @regs: register block for this velocity - * @mask: buffer to store mask - * @cam_type: CAM to fetch - * - * Fetch the mask bits of the selected CAM and store them into the - * provided mask buffer. - */ - -static inline void mac_get_cam_mask(struct mac_regs *regs, u8 * mask, - enum velocity_cam_type cam_type) -{ - int i; - /* Select CAM mask */ - BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, - ®s->CAMCR); - - if (cam_type == VELOCITY_VLAN_ID_CAM) - writeb(CAMADDR_VCAMSL, ®s->CAMADDR); - else - writeb(0, ®s->CAMADDR); - - /* read mask */ - for (i = 0; i < 8; i++) - *mask++ = readb(&(regs->MARCAM[i])); - - /* disable CAMEN */ - writeb(0, ®s->CAMADDR); - - /* Select mar */ - BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, - ®s->CAMCR); - -} - -/** - * mac_set_cam_mask - Set a CAM mask - * @regs: register block for this velocity - * @mask: CAM mask to load - * @cam_type: CAM to store - * - * Store a new mask into a CAM - */ - -static inline void mac_set_cam_mask(struct mac_regs *regs, u8 * mask, - enum velocity_cam_type cam_type) -{ - int i; - /* Select CAM mask */ - BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, - ®s->CAMCR); - - if (cam_type == VELOCITY_VLAN_ID_CAM) - writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL, ®s->CAMADDR); - else - writeb(CAMADDR_CAMEN, ®s->CAMADDR); - - for (i = 0; i < 8; i++) { - writeb(*mask++, &(regs->MARCAM[i])); - } - /* disable CAMEN */ - writeb(0, ®s->CAMADDR); - - /* Select mar */ - BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, - ®s->CAMCR); -} - -/** - * mac_set_cam - set CAM data - * @regs: register block of this velocity - * @idx: Cam index - * @addr: 2 or 6 bytes of CAM data - * @cam_type: CAM to load - * - * Load an address or vlan tag into a CAM - */ - -static inline void mac_set_cam(struct mac_regs *regs, int idx, u8 * addr, - enum velocity_cam_type cam_type) -{ - int i; - - /* Select CAM mask */ - BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0, - ®s->CAMCR); - - idx &= (64 - 1); - - if (cam_type == VELOCITY_VLAN_ID_CAM) - writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, - ®s->CAMADDR); - else - writeb(CAMADDR_CAMEN | idx, ®s->CAMADDR); - - if (cam_type == VELOCITY_VLAN_ID_CAM) - writew(*((u16 *) addr), ®s->MARCAM[0]); - else { - for (i = 0; i < 6; i++) { - writeb(*addr++, &(regs->MARCAM[i])); - } - } - BYTE_REG_BITS_ON(CAMCR_CAMWR, ®s->CAMCR); - - udelay(10); - - writeb(0, ®s->CAMADDR); - - /* Select mar */ - BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, - ®s->CAMCR); -} - -/** - * mac_get_cam - fetch CAM data - * @regs: register block of this velocity - * @idx: Cam index - * @addr: buffer to hold up to 6 bytes of CAM data - * @cam_type: CAM to load - * - * Load an address or vlan tag from a CAM into the buffer provided by - * the caller. VLAN tags are 2 bytes the address cam entries are 6. - */ - -static inline void mac_get_cam(struct mac_regs *regs, int idx, u8 * addr, - enum velocity_cam_type cam_type) -{ - int i; - - /* Select CAM mask */ - BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0, - ®s->CAMCR); - - idx &= (64 - 1); - - if (cam_type == VELOCITY_VLAN_ID_CAM) - writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, - ®s->CAMADDR); - else - writeb(CAMADDR_CAMEN | idx, ®s->CAMADDR); - - BYTE_REG_BITS_ON(CAMCR_CAMRD, ®s->CAMCR); - - udelay(10); - - if (cam_type == VELOCITY_VLAN_ID_CAM) - *((u16 *) addr) = readw(&(regs->MARCAM[0])); - else - for (i = 0; i < 6; i++, addr++) - *((u8 *) addr) = readb(&(regs->MARCAM[i])); - - writeb(0, ®s->CAMADDR); - - /* Select mar */ - BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, - ®s->CAMCR); -} - -/** - * mac_wol_reset - reset WOL after exiting low power - * @regs: register block of this velocity - * - * Called after we drop out of wake on lan mode in order to - * reset the Wake on lan features. This function doesn't restore - * the rest of the logic from the result of sleep/wakeup - */ - -inline static void mac_wol_reset(struct mac_regs *regs) -{ - - /* Turn off SWPTAG right after leaving power mode */ - BYTE_REG_BITS_OFF(STICKHW_SWPTAG, ®s->STICKHW); - /* clear sticky bits */ - BYTE_REG_BITS_OFF((STICKHW_DS1 | STICKHW_DS0), ®s->STICKHW); - - BYTE_REG_BITS_OFF(CHIPGCR_FCGMII, ®s->CHIPGCR); - BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, ®s->CHIPGCR); - /* disable force PME-enable */ - writeb(WOLCFG_PMEOVR, ®s->WOLCFGClr); - /* disable power-event config bit */ - writew(0xFFFF, ®s->WOLCRClr); - /* clear power status */ - writew(0xFFFF, ®s->WOLSRClr); -} - - -/* - * Header for WOL definitions. Used to compute hashes - */ - -typedef u8 MCAM_ADDR[ETH_ALEN]; - -struct arp_packet { - u8 dest_mac[ETH_ALEN]; - u8 src_mac[ETH_ALEN]; - u16 type; - u16 ar_hrd; - u16 ar_pro; - u8 ar_hln; - u8 ar_pln; - u16 ar_op; - u8 ar_sha[ETH_ALEN]; - u8 ar_sip[4]; - u8 ar_tha[ETH_ALEN]; - u8 ar_tip[4]; -} __attribute__ ((__packed__)); - -struct _magic_packet { - u8 dest_mac[6]; - u8 src_mac[6]; - u16 type; - u8 MAC[16][6]; - u8 password[6]; -} __attribute__ ((__packed__)); - -/* - * Store for chip context when saving and restoring status. Not - * all fields are saved/restored currently. - */ - -struct velocity_context { - u8 mac_reg[256]; - MCAM_ADDR cam_addr[MCAM_SIZE]; - u16 vcam[VCAM_SIZE]; - u32 cammask[2]; - u32 patcrc[2]; - u32 pattern[8]; -}; - - -/* - * MII registers. - */ - - -/* - * Registers in the MII (offset unit is WORD) - */ - -#define MII_REG_BMCR 0x00 // physical address -#define MII_REG_BMSR 0x01 // -#define MII_REG_PHYID1 0x02 // OUI -#define MII_REG_PHYID2 0x03 // OUI + Module ID + REV ID -#define MII_REG_ANAR 0x04 // -#define MII_REG_ANLPAR 0x05 // -#define MII_REG_G1000CR 0x09 // -#define MII_REG_G1000SR 0x0A // -#define MII_REG_MODCFG 0x10 // -#define MII_REG_TCSR 0x16 // -#define MII_REG_PLED 0x1B // -// NS, MYSON only -#define MII_REG_PCR 0x17 // -// ESI only -#define MII_REG_PCSR 0x17 // -#define MII_REG_AUXCR 0x1C // - -// Marvell 88E1000/88E1000S -#define MII_REG_PSCR 0x10 // PHY specific control register - -// -// Bits in the BMCR register -// -#define BMCR_RESET 0x8000 // -#define BMCR_LBK 0x4000 // -#define BMCR_SPEED100 0x2000 // -#define BMCR_AUTO 0x1000 // -#define BMCR_PD 0x0800 // -#define BMCR_ISO 0x0400 // -#define BMCR_REAUTO 0x0200 // -#define BMCR_FDX 0x0100 // -#define BMCR_SPEED1G 0x0040 // -// -// Bits in the BMSR register -// -#define BMSR_AUTOCM 0x0020 // -#define BMSR_LNK 0x0004 // - -// -// Bits in the ANAR register -// -#define ANAR_ASMDIR 0x0800 // Asymmetric PAUSE support -#define ANAR_PAUSE 0x0400 // Symmetric PAUSE Support -#define ANAR_T4 0x0200 // -#define ANAR_TXFD 0x0100 // -#define ANAR_TX 0x0080 // -#define ANAR_10FD 0x0040 // -#define ANAR_10 0x0020 // -// -// Bits in the ANLPAR register -// -#define ANLPAR_ASMDIR 0x0800 // Asymmetric PAUSE support -#define ANLPAR_PAUSE 0x0400 // Symmetric PAUSE Support -#define ANLPAR_T4 0x0200 // -#define ANLPAR_TXFD 0x0100 // -#define ANLPAR_TX 0x0080 // -#define ANLPAR_10FD 0x0040 // -#define ANLPAR_10 0x0020 // - -// -// Bits in the G1000CR register -// -#define G1000CR_1000FD 0x0200 // PHY is 1000-T Full-duplex capable -#define G1000CR_1000 0x0100 // PHY is 1000-T Half-duplex capable - -// -// Bits in the G1000SR register -// -#define G1000SR_1000FD 0x0800 // LP PHY is 1000-T Full-duplex capable -#define G1000SR_1000 0x0400 // LP PHY is 1000-T Half-duplex capable - -#define TCSR_ECHODIS 0x2000 // -#define AUXCR_MDPPS 0x0004 // - -// Bits in the PLED register -#define PLED_LALBE 0x0004 // - -// Marvell 88E1000/88E1000S Bits in the PHY specific control register (10h) -#define PSCR_ACRSTX 0x0800 // Assert CRS on Transmit - -#define PHYID_CICADA_CS8201 0x000FC410UL -#define PHYID_VT3216_32BIT 0x000FC610UL -#define PHYID_VT3216_64BIT 0x000FC600UL -#define PHYID_MARVELL_1000 0x01410C50UL -#define PHYID_MARVELL_1000S 0x01410C40UL - -#define PHYID_REV_ID_MASK 0x0000000FUL - -#define PHYID_GET_PHY_REV_ID(i) ((i) & PHYID_REV_ID_MASK) -#define PHYID_GET_PHY_ID(i) ((i) & ~PHYID_REV_ID_MASK) - -#define MII_REG_BITS_ON(x,i,p) do {\ - u16 w;\ - velocity_mii_read((p),(i),&(w));\ - (w)|=(x);\ - velocity_mii_write((p),(i),(w));\ -} while (0) - -#define MII_REG_BITS_OFF(x,i,p) do {\ - u16 w;\ - velocity_mii_read((p),(i),&(w));\ - (w)&=(~(x));\ - velocity_mii_write((p),(i),(w));\ -} while (0) - -#define MII_REG_BITS_IS_ON(x,i,p) ({\ - u16 w;\ - velocity_mii_read((p),(i),&(w));\ - ((int) ((w) & (x)));}) - -#define MII_GET_PHY_ID(p) ({\ - u32 id; \ - u16 id2; \ - u16 id1; \ - velocity_mii_read((p),MII_REG_PHYID2, &id2);\ - velocity_mii_read((p),MII_REG_PHYID1, &id1);\ - id = ( ( (u32)id2 ) << 16 ) | id1; \ - (id);}) - -#ifdef LINUX -/* - * Inline debug routine - */ - - -enum velocity_msg_level { - MSG_LEVEL_ERR = 0, //Errors that will cause abnormal operation. - MSG_LEVEL_NOTICE = 1, //Some errors need users to be notified. - MSG_LEVEL_INFO = 2, //Normal message. - MSG_LEVEL_VERBOSE = 3, //Will report all trival errors. - MSG_LEVEL_DEBUG = 4 //Only for debug purpose. -}; - -#ifdef VELOCITY_DEBUG -#define ASSERT(x) { \ - if (!(x)) { \ - printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\ - __FUNCTION__, __LINE__);\ - BUG(); \ - }\ -} -#define VELOCITY_DBG(p,args...) printk(p, ##args) -#else -#define ASSERT(x) -#define VELOCITY_DBG(x) -#endif - -#define VELOCITY_PRT(l, p, args...) do {if (l<=msglevel) printf( p ,##args);} while (0) - -#define VELOCITY_PRT_CAMMASK(p,t) {\ - int i;\ - if ((t)==VELOCITY_MULTICAST_CAM) {\ - for (i=0;i<(MCAM_SIZE/8);i++)\ - printk("%02X",(p)->mCAMmask[i]);\ - }\ - else {\ - for (i=0;i<(VCAM_SIZE/8);i++)\ - printk("%02X",(p)->vCAMmask[i]);\ - }\ - printk("\n");\ -} - -#endif - -#define VELOCITY_WOL_MAGIC 0x00000000UL -#define VELOCITY_WOL_PHY 0x00000001UL -#define VELOCITY_WOL_ARP 0x00000002UL -#define VELOCITY_WOL_UCAST 0x00000004UL -#define VELOCITY_WOL_BCAST 0x00000010UL -#define VELOCITY_WOL_MCAST 0x00000020UL -#define VELOCITY_WOL_MAGIC_SEC 0x00000040UL - -/* - * Flags for options - */ - -#define VELOCITY_FLAGS_TAGGING 0x00000001UL -#define VELOCITY_FLAGS_TX_CSUM 0x00000002UL -#define VELOCITY_FLAGS_RX_CSUM 0x00000004UL -#define VELOCITY_FLAGS_IP_ALIGN 0x00000008UL -#define VELOCITY_FLAGS_VAL_PKT_LEN 0x00000010UL - -#define VELOCITY_FLAGS_FLOW_CTRL 0x01000000UL - -/* - * Flags for driver status - */ - -#define VELOCITY_FLAGS_OPENED 0x00010000UL -#define VELOCITY_FLAGS_VMNS_CONNECTED 0x00020000UL -#define VELOCITY_FLAGS_VMNS_COMMITTED 0x00040000UL -#define VELOCITY_FLAGS_WOL_ENABLED 0x00080000UL - -/* - * Flags for MII status - */ - -#define VELOCITY_LINK_FAIL 0x00000001UL -#define VELOCITY_SPEED_10 0x00000002UL -#define VELOCITY_SPEED_100 0x00000004UL -#define VELOCITY_SPEED_1000 0x00000008UL -#define VELOCITY_DUPLEX_FULL 0x00000010UL -#define VELOCITY_AUTONEG_ENABLE 0x00000020UL -#define VELOCITY_FORCED_BY_EEPROM 0x00000040UL - -/* - * For velocity_set_media_duplex - */ - -#define VELOCITY_LINK_CHANGE 0x00000001UL - -enum speed_opt { - SPD_DPX_AUTO = 0, - SPD_DPX_100_HALF = 1, - SPD_DPX_100_FULL = 2, - SPD_DPX_10_HALF = 3, - SPD_DPX_10_FULL = 4 -}; - -enum velocity_init_type { - VELOCITY_INIT_COLD = 0, - VELOCITY_INIT_RESET, - VELOCITY_INIT_WOL -}; - -enum velocity_flow_cntl_type { - FLOW_CNTL_DEFAULT = 1, - FLOW_CNTL_TX, - FLOW_CNTL_RX, - FLOW_CNTL_TX_RX, - FLOW_CNTL_DISABLE, -}; - -struct velocity_opt { - int numrx; /* Number of RX descriptors */ - int numtx; /* Number of TX descriptors */ - enum speed_opt spd_dpx; /* Media link mode */ - int vid; /* vlan id */ - int DMA_length; /* DMA length */ - int rx_thresh; /* RX_THRESH */ - int flow_cntl; - int wol_opts; /* Wake on lan options */ - int td_int_count; - int int_works; - int rx_bandwidth_hi; - int rx_bandwidth_lo; - int rx_bandwidth_en; - u32 flags; -}; - -#define RX_DESC_MIN 4 -#define RX_DESC_MAX 255 -#define RX_DESC_DEF RX_DESC_MIN - -#define TX_DESC_MIN 1 -#define TX_DESC_MAX 256 -#define TX_DESC_DEF TX_DESC_MIN - -static struct velocity_info { -// struct list_head list; - - struct pci_device *pdev; -// struct net_device *dev; -// struct net_device_stats stats; - -#ifdef CONFIG_PM - u32 pci_state[16]; -#endif - -// dma_addr_t rd_pool_dma; -// dma_addr_t td_pool_dma[TX_QUEUE_NO]; - -// dma_addr_t tx_bufs_dma; - u8 *tx_bufs; - - u8 ip_addr[4]; - enum chip_type chip_id; - - struct mac_regs *mac_regs; - unsigned long memaddr; - unsigned long ioaddr; - u32 io_size; - - u8 rev_id; - -#define AVAIL_TD(p,q) ((p)->options.numtx-((p)->td_used[(q)])) - - int num_txq; - - volatile int td_used[TX_QUEUE_NO]; - int td_curr; - int td_tail[TX_QUEUE_NO]; - unsigned char *TxDescArrays; /* Index of Tx Descriptor buffer */ - unsigned char *RxDescArrays; /* Index of Rx Descriptor buffer */ - unsigned char *tx_buffs; - unsigned char *rx_buffs; - - unsigned char *txb; - unsigned char *rxb; - struct tx_desc *td_rings; - struct velocity_td_info *td_infos[TX_QUEUE_NO]; - - int rd_curr; - int rd_dirty; - u32 rd_filled; - struct rx_desc *rd_ring; - struct velocity_rd_info *rd_info; /* It's an array */ - -#define GET_RD_BY_IDX(vptr, idx) (vptr->rd_ring[idx]) - u32 mib_counter[MAX_HW_MIB_COUNTER]; - struct velocity_opt options; - - u32 int_mask; - - u32 flags; - - int rx_buf_sz; - u32 mii_status; - u32 phy_id; - int multicast_limit; - - u8 vCAMmask[(VCAM_SIZE / 8)]; - u8 mCAMmask[(MCAM_SIZE / 8)]; - -// spinlock_t lock; - - int wol_opts; - u8 wol_passwd[6]; - - struct velocity_context context; - - u32 ticks; - u32 rx_bytes; - -} vptx; - -static struct velocity_info *vptr; - -#ifdef LINUX -/** - * velocity_get_ip - find an IP address for the device - * @vptr: Velocity to query - * - * Dig out an IP address for this interface so that we can - * configure wakeup with WOL for ARP. If there are multiple IP - * addresses on this chain then we use the first - multi-IP WOL is not - * supported. - * - * CHECK ME: locking - */ - -inline static int velocity_get_ip(struct velocity_info *vptr) -{ - struct in_device *in_dev = (struct in_device *) vptr->dev->ip_ptr; - struct in_ifaddr *ifa; - - if (in_dev != NULL) { - ifa = (struct in_ifaddr *) in_dev->ifa_list; - if (ifa != NULL) { - memcpy(vptr->ip_addr, &ifa->ifa_address, 4); - return 0; - } - } - return -ENOENT; -} - -/** - * velocity_update_hw_mibs - fetch MIB counters from chip - * @vptr: velocity to update - * - * The velocity hardware keeps certain counters in the hardware - * side. We need to read these when the user asks for statistics - * or when they overflow (causing an interrupt). The read of the - * statistic clears it, so we keep running master counters in user - * space. - */ - -static inline void velocity_update_hw_mibs(struct velocity_info *vptr) -{ - u32 tmp; - int i; - BYTE_REG_BITS_ON(MIBCR_MIBFLSH, &(vptr->mac_regs->MIBCR)); - - while (BYTE_REG_BITS_IS_ON - (MIBCR_MIBFLSH, &(vptr->mac_regs->MIBCR))); - - BYTE_REG_BITS_ON(MIBCR_MPTRINI, &(vptr->mac_regs->MIBCR)); - for (i = 0; i < HW_MIB_SIZE; i++) { - tmp = readl(&(vptr->mac_regs->MIBData)) & 0x00FFFFFFUL; - vptr->mib_counter[i] += tmp; - } -} -#endif -/** - * init_flow_control_register - set up flow control - * @vptr: velocity to configure - * - * Configure the flow control registers for this velocity device. - */ - -static inline void init_flow_control_register(struct velocity_info *vptr) -{ - struct mac_regs *regs = vptr->mac_regs; - - /* Set {XHITH1, XHITH0, XLTH1, XLTH0} in FlowCR1 to {1, 0, 1, 1} - depend on RD=64, and Turn on XNOEN in FlowCR1 */ - writel((CR0_XONEN | CR0_XHITH1 | CR0_XLTH1 | CR0_XLTH0), - ®s->CR0Set); - writel((CR0_FDXTFCEN | CR0_FDXRFCEN | CR0_HDXFCEN | CR0_XHITH0), - ®s->CR0Clr); - - /* Set TxPauseTimer to 0xFFFF */ - writew(0xFFFF, ®s->tx_pause_timer); - - /* Initialize RBRDU to Rx buffer count. */ - writew(vptr->options.numrx, ®s->RBRDU); -} - - -#endif diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 2c4c9920..c6b0e794 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -114,7 +114,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_tlan ( ERRFILE_DRIVER | 0x00420000 ) #define ERRFILE_tulip ( ERRFILE_DRIVER | 0x00430000 ) #define ERRFILE_rhine ( ERRFILE_DRIVER | 0x00440000 ) -#define ERRFILE_via_velocity ( ERRFILE_DRIVER | 0x00450000 ) +#define ERRFILE_velocity ( ERRFILE_DRIVER | 0x00450000 ) #define ERRFILE_w89c840 ( ERRFILE_DRIVER | 0x00460000 ) #define ERRFILE_ipoib ( ERRFILE_DRIVER | 0x00470000 ) #define ERRFILE_e1000_main ( ERRFILE_DRIVER | 0x00480000 ) |