iPXE
Defines | Functions | Variables
velocity.c File Reference

VIA Velocity network driver. More...

#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"

Go to the source code of this file.

Defines

#define velocity_setbit(_reg, _mask)   writeb ( readb ( _reg ) | _mask, _reg )
#define virt_to_le32bus(x)   ( cpu_to_le32 ( virt_to_bus ( x ) ) )

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static int velocity_autopoll_stop (struct velocity_nic *vlc)
 Stop MII auto-polling.
static int velocity_autopoll_start (struct velocity_nic *vlc)
 Start MII auto-polling.
static int velocity_mii_read (struct mii_interface *mdio, unsigned int phy __unused, unsigned int reg)
 Read from MII register.
static int velocity_mii_write (struct mii_interface *mdio, unsigned int phy __unused, unsigned int reg, unsigned int data)
 Write to MII register.
static void velocity_set_link (struct velocity_nic *vlc)
 Set Link speed.
static int velocity_reload_eeprom (struct velocity_nic *vlc)
 Reload eeprom contents.
static int velocity_reset (struct velocity_nic *vlc)
 Reset hardware.
static void velocity_check_link (struct net_device *netdev)
 Check link state.
static int velocity_alloc_rings (struct velocity_nic *vlc)
 Allocate descriptor rings.
static void velocity_refill_rx (struct velocity_nic *vlc)
 Refill receive descriptor ring.
static int velocity_open (struct net_device *netdev)
 Open network device.
static void velocity_close (struct net_device *netdev)
 Close network device.
static int velocity_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet.
static void velocity_poll_rx (struct velocity_nic *vlc)
 Poll for received packets.
static void velocity_poll_tx (struct velocity_nic *vlc)
 Poll for completed packets.
static void velocity_poll (struct net_device *netdev)
 Poll for completed and received packets.
static void velocity_irq (struct net_device *netdev, int enable)
 Enable or disable interrupts.
static int velocity_probe (struct pci_device *pci)
 Probe PCI device.
static void velocity_remove (struct pci_device *pci)
 Remove PCI device.

Variables

static struct mii_operations velocity_mii_operations
 Velocity MII operations.
static struct net_device_operations velocity_operations
 Velocity network device operations.
static struct pci_device_id velocity_nics []
 Velocity PCI device IDs.
struct pci_driver velocity_driver __pci_driver
 Velocity PCI driver.

Detailed Description

VIA Velocity network driver.

Definition in file velocity.c.


Define Documentation

#define velocity_setbit (   _reg,
  _mask 
)    writeb ( readb ( _reg ) | _mask, _reg )
#define virt_to_le32bus (   x)    ( cpu_to_le32 ( virt_to_bus ( x ) ) )

Definition at line 37 of file velocity.c.

Referenced by velocity_refill_rx(), and velocity_transmit().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static int velocity_autopoll_stop ( struct velocity_nic vlc) [static]

Stop MII auto-polling.

Parameters:
vlcVelocity device
Return values:
rcReturn status code

Definition at line 58 of file velocity.c.

References DBGC, ETIMEDOUT, readb(), velocity_nic::regs, timeout(), udelay(), VELOCITY_MIICR, VELOCITY_MIISR, VELOCITY_MIISR_IDLE, VELOCITY_TIMEOUT_US, and writeb().

Referenced by velocity_mii_read(), and velocity_mii_write().

                                                               {
        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;
}
static int velocity_autopoll_start ( struct velocity_nic vlc) [static]

Start MII auto-polling.

Parameters:
vlcVelocity device
Return values:
rcReturn status code

Definition at line 82 of file velocity.c.

References DBGC, ETIMEDOUT, readb(), velocity_nic::regs, timeout(), udelay(), VELOCITY_MIICR, VELOCITY_MIICR_MAUTO, VELOCITY_MIISR, VELOCITY_MIISR_IDLE, VELOCITY_TIMEOUT_US, and writeb().

Referenced by velocity_check_link(), velocity_mii_read(), velocity_mii_write(), and velocity_open().

                                                                {
        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;
}
static int velocity_mii_read ( struct mii_interface mdio,
unsigned int phy  __unused,
unsigned int  reg 
) [static]

Read from MII register.

Parameters:
mdioMII interface
phyPHY address
regRegister address
Return values:
valueData read, or negative error

Definition at line 108 of file velocity.c.

References container_of, DBGC, DBGC2, ETIMEDOUT, readb(), readw(), velocity_nic::regs, timeout(), udelay(), velocity_autopoll_start(), velocity_autopoll_stop(), VELOCITY_MIIADDR, VELOCITY_MIICR, VELOCITY_MIICR_RCMD, VELOCITY_MIIDATA, velocity_setbit, VELOCITY_TIMEOUT_US, and writeb().

                                                                             {
        struct velocity_nic *vlc =
                container_of ( mdio, struct velocity_nic, mdio );
        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;
}
static int velocity_mii_write ( struct mii_interface mdio,
unsigned int phy  __unused,
unsigned int  reg,
unsigned int  data 
) [static]

Write to MII register.

Parameters:
mdioMII interface
phyPHY address
regRegister address
dataData to write
Return values:
rcReturn status code

Definition at line 151 of file velocity.c.

References container_of, DBGC, DBGC2, ETIMEDOUT, readb(), velocity_nic::regs, timeout(), udelay(), velocity_autopoll_start(), velocity_autopoll_stop(), VELOCITY_MIIADDR, VELOCITY_MIICR, VELOCITY_MIICR_WCMD, VELOCITY_MIIDATA, velocity_setbit, VELOCITY_TIMEOUT_US, writeb(), and writew().

                                                   {
        struct velocity_nic *vlc =
                container_of ( mdio, struct velocity_nic, mdio );
        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;
}
static void velocity_set_link ( struct velocity_nic vlc) [static]

Set Link speed.

Parameters:
vlcVelocity device

Definition at line 197 of file velocity.c.

References ADVERTISE_1000FULL, ADVERTISE_1000HALF, BMCR_SPEED1000, velocity_nic::mii, MII_BMCR, MII_CTRL1000, mii_read(), and mii_write().

Referenced by velocity_probe().

                                                           {
        int tmp;

        /* Advertise 1000MBit */
        tmp = mii_read ( &vlc->mii, MII_CTRL1000 );
        tmp |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
        mii_write ( &vlc->mii, MII_CTRL1000, tmp );

        /* Enable GBit operation in MII Control Register */
        tmp = mii_read ( &vlc->mii, MII_BMCR );
        tmp |= BMCR_SPEED1000;
        mii_write ( &vlc->mii, MII_BMCR, tmp );
}
static int velocity_reload_eeprom ( struct velocity_nic vlc) [static]

Reload eeprom contents.

Parameters:
vlcVelocity device

Definition at line 223 of file velocity.c.

References DBGC, ETIMEDOUT, readb(), velocity_nic::regs, timeout(), udelay(), VELOCITY_EECSR, VELOCITY_EECSR_RELOAD, velocity_setbit, and VELOCITY_TIMEOUT_US.

Referenced by velocity_probe().

                                                               {
        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;
}
static int velocity_reset ( struct velocity_nic vlc) [static]

Reset hardware.

Parameters:
vlcVelocity device
Return values:
rcReturn status code

Definition at line 247 of file velocity.c.

References DBGC, EINVAL, readb(), velocity_nic::regs, timeout(), udelay(), VELOCITY_CFGA, VELOCITY_CFGA_PACPI, VELOCITY_CR1_SFRST, VELOCITY_CRS1, velocity_setbit, VELOCITY_STICKY, VELOCITY_STICKY_DS0, VELOCITY_STICKY_DS1, VELOCITY_TIMEOUT_US, and writeb().

Referenced by velocity_probe(), and velocity_remove().

                                                       {
        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;
}
static void velocity_check_link ( struct net_device netdev) [static]

Check link state.

Parameters:
netdevNetwork device

Definition at line 288 of file velocity.c.

References DBGC, netdev_link_down(), netdev_link_up(), net_device::priv, readb(), velocity_nic::regs, velocity_autopoll_start(), VELOCITY_PHYSTS0, and VELOCITY_PHYSTS0_LINK.

Referenced by velocity_open(), and velocity_poll().

                                                              {
        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 );
}
static int velocity_alloc_rings ( struct velocity_nic vlc) [static]

Allocate descriptor rings.

Parameters:
vlcVelocity device
Return values:
rcReturn status code

Definition at line 316 of file velocity.c.

References DBGC2, ENOMEM, free_dma(), malloc_dma(), memset(), rc, velocity_nic::regs, velocity_nic::rx_commit, velocity_nic::rx_cons, velocity_nic::rx_prod, velocity_nic::rx_ring, velocity_nic::tx_cons, velocity_nic::tx_prod, velocity_nic::tx_ring, VELOCITY_RING_ALIGN, VELOCITY_RXDESC_ADDR_LO, VELOCITY_RXDESC_NUM, VELOCITY_RXDESC_SIZE, VELOCITY_RXDESCNUM, VELOCITY_TXDESC_ADDR_LO0, VELOCITY_TXDESC_NUM, VELOCITY_TXDESC_SIZE, VELOCITY_TXDESCNUM, virt_to_bus(), writel(), and writew().

Referenced by velocity_open().

                                                             {
        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;
}
static void velocity_refill_rx ( struct velocity_nic vlc) [static]

Refill receive descriptor ring.

Parameters:
vlcVelocity device

Definition at line 368 of file velocity.c.

References velocity_rx_descriptor::addr, alloc_iob(), cpu_to_le32, data, DBGC2, velocity_rx_descriptor::des0, velocity_rx_descriptor::des1, velocity_rx_descriptor::des2, velocity_nic::regs, velocity_nic::rx_buffs, velocity_nic::rx_commit, velocity_nic::rx_cons, velocity_nic::rx_prod, velocity_nic::rx_ring, VELOCITY_DES0_OWN, VELOCITY_DES2_IC, VELOCITY_DES2_SIZE, VELOCITY_RX_MAX_LEN, VELOCITY_RXDESC_NUM, VELOCITY_RXDESC_RESIDUECNT, virt_to_le32bus, wmb, and writew().

Referenced by velocity_open(), and velocity_poll().

                                                            {
        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 );
}
static int velocity_open ( struct net_device netdev) [static]

Open network device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 424 of file velocity.c.

References DBGC, DBGC2, net_device::priv, rc, readb(), velocity_nic::regs, velocity_alloc_rings(), velocity_autopoll_start(), velocity_check_link(), VELOCITY_CR0_RXON, VELOCITY_CR0_START, VELOCITY_CR0_STOP, VELOCITY_CR0_TXON, VELOCITY_CR1_DPOLL, VELOCITY_CRC0, VELOCITY_CRS0, VELOCITY_IMR0, VELOCITY_IMR1, VELOCITY_RCR, velocity_refill_rx(), VELOCITY_RXQCSR_RUN, VELOCITY_RXQCSR_WAK, VELOCITY_RXQCSRS, VELOCITY_TXQCSRS, VELOCITY_TXQCSRS_RUN0, writeb(), and writew().

                                                       {
        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;
}
static void velocity_close ( struct net_device netdev) [static]

Close network device.

Parameters:
netdevNetwork device

Definition at line 471 of file velocity.c.

References free_dma(), free_iob(), NULL, net_device::priv, velocity_nic::regs, velocity_nic::rx_buffs, velocity_nic::rx_cons, velocity_nic::rx_prod, velocity_nic::rx_ring, velocity_nic::tx_cons, velocity_nic::tx_prod, velocity_nic::tx_ring, VELOCITY_CR0_RXON, VELOCITY_CR0_STOP, VELOCITY_CR0_TXON, VELOCITY_CRC0, VELOCITY_CRS0, VELOCITY_RXDESC_ADDR_LO, VELOCITY_RXDESC_NUM, VELOCITY_RXDESC_SIZE, VELOCITY_RXDESCNUM, VELOCITY_TXDESC_ADDR_LO0, VELOCITY_TXDESC_SIZE, VELOCITY_TXDESCNUM, writeb(), writel(), and writew().

                                                         {
        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;
}
static int velocity_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Transmit packet.

Parameters:
netdevNetwork device
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 515 of file velocity.c.

References velocity_frag::addr, cpu_to_le32, io_buffer::data, DBGC2, velocity_tx_descriptor::des0, velocity_tx_descriptor::des1, velocity_frag::des2, ETH_ZLEN, velocity_tx_descriptor::frags, iob_len(), iob_pad(), net_device::priv, velocity_nic::regs, velocity_nic::tx_prod, velocity_nic::tx_ring, VELOCITY_DES0_OWN, VELOCITY_DES1_FRAG, VELOCITY_DES1_INTR, VELOCITY_DES1_TCPLS, VELOCITY_DES2_SIZE, velocity_setbit, VELOCITY_TXDESC_NUM, VELOCITY_TXQCSRS, VELOCITY_TXQCSRS_WAK0, virt_to_le32bus, and wmb.

                                                         {
        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;
}
static void velocity_poll_rx ( struct velocity_nic vlc) [static]

Poll for received packets.

Parameters:
vlcVelocity device

Definition at line 555 of file velocity.c.

References cpu_to_le32, io_buffer::data, DBGC, DBGC2, DBGC_HD, des0, velocity_rx_descriptor::des0, EINVAL, iob_put, len, velocity_nic::netdev, netdev_rx(), netdev_rx_err(), velocity_nic::rx_buffs, velocity_nic::rx_cons, velocity_nic::rx_prod, velocity_nic::rx_ring, VELOCITY_DES0_OWN, VELOCITY_DES0_RMBC, VELOCITY_DES0_RX_ERR, VELOCITY_DES0_RXOK, and VELOCITY_RXDESC_NUM.

Referenced by velocity_poll().

                                                          {
        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++;
        }
}
static void velocity_poll_tx ( struct velocity_nic vlc) [static]

Poll for completed packets.

Parameters:
vlcVelocity device

Definition at line 612 of file velocity.c.

References DBGC2, velocity_tx_descriptor::des0, EINVAL, le32_to_cpu, velocity_nic::netdev, netdev_tx_complete_next(), netdev_tx_complete_next_err(), velocity_nic::tx_cons, velocity_nic::tx_prod, velocity_nic::tx_ring, VELOCITY_DES0_OWN, VELOCITY_DES0_TERR, and VELOCITY_TXDESC_NUM.

Referenced by velocity_poll().

                                                          {
        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++;
        }
}
static void velocity_poll ( struct net_device netdev) [static]

Poll for completed and received packets.

Parameters:
netdevNetwork device

Definition at line 645 of file velocity.c.

References DBGC2, net_device::priv, readb(), velocity_nic::regs, velocity_check_link(), VELOCITY_ISR0, VELOCITY_ISR1, VELOCITY_ISR1_SRCI, velocity_poll_rx(), velocity_poll_tx(), velocity_refill_rx(), VELOCITY_RXQCSR_RUN, VELOCITY_RXQCSR_WAK, VELOCITY_RXQCSRS, and writew().

                                                        {
        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 );
}
static void velocity_irq ( struct net_device netdev,
int  enable 
) [static]

Enable or disable interrupts.

Parameters:
netdevNetwork device
enableInterrupts should be enabled

Definition at line 677 of file velocity.c.

References DBGC, net_device::priv, velocity_nic::regs, VELOCITY_CR3_GINTMSK1, VELOCITY_CRC3, VELOCITY_CRS3, and writeb().

                                                                   {
        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 );
        }
}
static int velocity_probe ( struct pci_device pci) [static]

Probe PCI device.

Parameters:
pciPCI device
Return values:
rcReturn status code

Definition at line 714 of file velocity.c.

References adjust_pci_device(), alloc_etherdev(), DBGC, pci_device::dev, net_device::dev, ENOMEM, net_device::hw_addr, ioremap(), velocity_nic::mdio, mdio_init(), pci_device::membase, velocity_nic::mii, mii_init(), mii_reset(), netdev, velocity_nic::netdev, netdev_init(), netdev_nullify(), netdev_put(), pci_set_drvdata(), net_device::priv, rc, readb(), register_netdev(), velocity_nic::regs, strerror(), VELOCITY_BAR_SIZE, VELOCITY_MAC0, VELOCITY_MAC1, VELOCITY_MAC2, VELOCITY_MAC3, VELOCITY_MAC4, VELOCITY_MAC5, velocity_reload_eeprom(), velocity_reset(), and velocity_set_link().

                                                     {
        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 */
        mdio_init ( &vlc->mdio, &velocity_mii_operations );
        mii_init ( &vlc->mii, &vlc->mdio, 0 );
        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;
}
static void velocity_remove ( struct pci_device pci) [static]

Remove PCI device.

Parameters:
pciPCI device

Definition at line 786 of file velocity.c.

References netdev, netdev_nullify(), netdev_put(), pci_get_drvdata(), net_device::priv, unregister_netdev(), and velocity_reset().

                                                       {
        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 );
}

Variable Documentation

Initial value:
 {
        .read = velocity_mii_read,
        .write = velocity_mii_write,
}

Velocity MII operations.

Definition at line 187 of file velocity.c.

Initial value:
 {
        .open           = velocity_open,
        .close          = velocity_close,
        .transmit       = velocity_transmit,
        .poll           = velocity_poll,
        .irq            = velocity_irq,
}

Velocity network device operations.

Definition at line 693 of file velocity.c.

struct pci_device_id velocity_nics[] [static]
Initial value:
 {
        PCI_ROM ( 0x1106, 0x3119, "vt6122",     "VIA Velocity", 0 ),
}

Velocity PCI device IDs.

Definition at line 802 of file velocity.c.

struct pci_driver velocity_driver __pci_driver
Initial value:
 {
        .ids = velocity_nics,
        .id_count = ( sizeof ( velocity_nics ) / sizeof ( velocity_nics[0] ) ),
        .probe = velocity_probe,
        .remove = velocity_remove,
}

Velocity PCI driver.

Definition at line 807 of file velocity.c.