iPXE
Defines | Functions | Variables
eepro100.c File Reference
#include <stdint.h>
#include <byteswap.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <ipxe/ethernet.h>
#include <ipxe/if_ether.h>
#include <ipxe/iobuf.h>
#include <ipxe/malloc.h>
#include <ipxe/pci.h>
#include <ipxe/spi_bit.h>
#include <ipxe/timer.h>
#include <ipxe/nvs.h>
#include <ipxe/threewire.h>
#include <ipxe/netdevice.h>
#include "eepro100.h"

Go to the source code of this file.

Defines

#define INTERRUPT_MASK   ( SCBMaskEarlyRx | SCBMaskFlowCtl )
#define RFD_STATUS

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static int ifec_pci_probe (struct pci_device *pci)
static void ifec_pci_remove (struct pci_device *pci)
static void ifec_net_close (struct net_device *netdev)
static void ifec_net_irq (struct net_device *netdev, int enable)
static int ifec_net_open (struct net_device *netdev)
static void ifec_net_poll (struct net_device *netdev)
static int ifec_net_transmit (struct net_device *netdev, struct io_buffer *iobuf)
static int ifec_spi_read_bit (struct bit_basher *basher, unsigned int bit_id)
static void ifec_spi_write_bit (struct bit_basher *basher, unsigned int bit_id, unsigned long data)
static void ifec_init_eeprom (struct net_device *netdev)
static int ifec_mdio_read (struct net_device *netdev, int phy_id, int location)
static void ifec_mdio_setup (struct net_device *netdev, int options)
static int ifec_mdio_write (struct net_device *netdev, int phy_id, int location, int value)
static void ifec_reset (struct net_device *netdev)
static void ifec_free (struct net_device *netdev)
static void ifec_rfd_init (struct ifec_rfd *rfd, s16 command, u32 link)
static void ifec_reprime_ru (struct net_device *netdev)
static void ifec_check_ru_status (struct net_device *netdev, unsigned short intr_status)
static void ifec_rx_process (struct net_device *netdev)
static int ifec_get_rx_desc (struct net_device *netdev, int cur, int cmd, int link)
static void ifec_refill_rx_ring (struct net_device *netdev)
static int ifec_rx_setup (struct net_device *netdev)
static int ifec_scb_cmd (struct net_device *netdev, u32 ptr, u8 cmd)
static int ifec_scb_cmd_wait (struct net_device *netdev)
static void ifec_tx_process (struct net_device *netdev)
static int ifec_tx_setup (struct net_device *netdev)
void ifec_tx_wake (struct net_device *netdev)

Variables

static struct ifec_cfg ifec_cfg
static struct net_device_operations ifec_operations
static const uint16_t ifec_ee_bits []
static struct bit_basher_operations ifec_basher_ops
static struct pci_device_id ifec_nics []
struct pci_driver ifec_driver __pci_driver

Define Documentation

Definition at line 280 of file eepro100.c.

Referenced by ifec_net_irq(), and ifec_net_poll().

#define RFD_STATUS
Value:
( RFD_OK | RFDRxCol | RFDRxErr | RFDShort | \
                     RFDDMAOverrun | RFDNoBufs | RFDCRCError )

Definition at line 785 of file eepro100.c.

Referenced by ifec_rx_process().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static int ifec_pci_probe ( struct pci_device pci) [static]

Definition at line 171 of file eepro100.c.

References adjust_pci_device(), alloc_etherdev(), DBGP, pci_device::dev, net_device::dev, ifec_private::eeprom, EEPROM_ADDR_MAC_0, EEPROM_ADDR_MDIO_REGISTER, EINVAL, ENOMEM, error, ETH_ALEN, net_device::hw_addr, ifec_init_eeprom(), ifec_reset(), ifec_private::ioaddr, pci_device::ioaddr, ifec_private::mdio_register, memset(), netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), spi_device::nvs, nvs_read(), pci_set_drvdata(), priv, net_device::priv, rc, and register_netdev().

{
        struct net_device *netdev;
        struct ifec_private *priv;
        int rc;

        DBGP ( "ifec_pci_probe: " );

        if ( pci->ioaddr == 0 )
                return -EINVAL;

        netdev = alloc_etherdev ( sizeof(*priv) );
        if ( !netdev )
                return -ENOMEM;

        netdev_init ( netdev, &ifec_operations );
        priv = netdev->priv;

        pci_set_drvdata ( pci, netdev );
        netdev->dev = &pci->dev;

        /* enable bus master, etc */
        adjust_pci_device( pci );

        DBGP ( "pci " );

        memset ( priv, 0, sizeof(*priv) );
        priv->ioaddr = pci->ioaddr;

        ifec_reset ( netdev );
        DBGP ( "reset " );

        ifec_init_eeprom ( netdev );

        /* read MAC address */
        nvs_read ( &priv->eeprom.nvs, EEPROM_ADDR_MAC_0, netdev->hw_addr,
                   ETH_ALEN );
        /* read mdio_register */
        nvs_read ( &priv->eeprom.nvs, EEPROM_ADDR_MDIO_REGISTER,
                   &priv->mdio_register, 2 );

        if ( ( rc = register_netdev ( netdev ) ) != 0 )
                goto error;

        netdev_link_up ( netdev );

        DBGP ( "ints\n" );

        return 0;

error:
        ifec_reset     ( netdev );
        netdev_nullify ( netdev );
        netdev_put     ( netdev );

        return rc;
}
static void ifec_pci_remove ( struct pci_device pci) [static]

Definition at line 236 of file eepro100.c.

References DBGP, ifec_reset(), netdev, netdev_nullify(), netdev_put(), pci_get_drvdata(), and unregister_netdev().

{
        struct net_device *netdev = pci_get_drvdata ( pci );

        DBGP ( "ifec_pci_remove\n" );

        unregister_netdev ( netdev );
        ifec_reset        ( netdev );
        netdev_nullify    ( netdev );
        netdev_put        ( netdev );
}
static void ifec_net_close ( struct net_device netdev) [static]

Definition at line 257 of file eepro100.c.

References DBGP, ifec_free(), ifec_net_irq(), ifec_reset(), inw(), ioaddr, ifec_private::ioaddr, outw(), priv, net_device::priv, and SCBStatus.

{
        struct ifec_private *priv = netdev->priv;
        unsigned long ioaddr = priv->ioaddr;
        unsigned short intr_status;

        DBGP ( "ifec_net_close\n" );

        /* disable interrupts */
        ifec_net_irq ( netdev, 0 );

        /* Ack & clear ints */
        intr_status = inw ( ioaddr + SCBStatus );
        outw ( intr_status, ioaddr + SCBStatus );
        inw ( ioaddr + SCBStatus );

        ifec_reset ( netdev );

        /* Free any resources */
        ifec_free ( netdev );
}
static void ifec_net_irq ( struct net_device netdev,
int  enable 
) [static]

Definition at line 290 of file eepro100.c.

References DBGP, INTERRUPT_MASK, ioaddr, ifec_private::ioaddr, outw(), priv, net_device::priv, SCBCmd, and SCBMaskAll.

Referenced by ifec_net_close(), ifec_net_open(), and ifec_reset().

{
        struct ifec_private *priv = netdev->priv;
        unsigned long ioaddr = priv->ioaddr;

        DBGP ( "ifec_net_irq\n" );

        outw ( enable ? INTERRUPT_MASK : SCBMaskAll, ioaddr + SCBCmd );
}
static int ifec_net_open ( struct net_device netdev) [static]

Definition at line 309 of file eepro100.c.

References ifec_cfg::byte, CB_ALIGN, cfg, CmdIASetup, ifec_ias::command, ifec_private::configured, CUCmdBase, CUStart, CUStatsAddr, DBG, DBG2, DBGP, ENOMEM, error, ETH_ALEN, free_dma(), ifec_ias::ia, ifec_free(), ifec_mdio_setup(), ifec_net_irq(), ifec_reset(), ifec_rx_setup(), ifec_scb_cmd(), ifec_scb_cmd_wait(), ifec_tx_setup(), ifec_ias::link, ifec_cfg::link, net_device::ll_addr, malloc_dma(), mdelay(), memcpy(), NULL, options, priv, net_device::priv, rc, ifec_private::rfds, RUAddrLoad, RUStart, ifec_private::stats, ifec_ias::status, ifec_cfg::status, ifec_private::tcbs, and virt_to_bus().

{
        struct ifec_private *priv = netdev->priv;
        struct ifec_ias *ias = NULL;
        struct ifec_cfg *cfg = NULL;
        int i, options;
        int rc = -ENOMEM;

        DBGP ( "ifec_net_open: " );

        /* Ensure interrupts are disabled. */
        ifec_net_irq ( netdev, 0 );

        /* Initialize Command Unit and Receive Unit base addresses. */
        ifec_scb_cmd ( netdev, 0, RUAddrLoad );
        ifec_scb_cmd ( netdev, virt_to_bus ( &priv->stats ), CUStatsAddr );
        ifec_scb_cmd ( netdev, 0, CUCmdBase );

        /* Initialize both rings */
        if ( ( rc = ifec_rx_setup ( netdev ) ) != 0 )
                goto error;
        if ( ( rc = ifec_tx_setup ( netdev ) ) != 0 )
                goto error;

        /* Initialize MDIO */
        options = 0x00; /* 0x40 = 10mbps half duplex, 0x00 = Autosense */
        ifec_mdio_setup ( netdev, options );

        /* Prepare MAC address w/ Individual Address Setup (ias) command.*/
        ias = malloc_dma ( sizeof ( *ias ), CB_ALIGN );
        if ( !ias ) {
                rc = -ENOMEM;
                goto error;
        }
        ias->command      = CmdIASetup;
        ias->status       = 0;
        memcpy ( ias->ia, netdev->ll_addr, ETH_ALEN );

        /* Prepare operating parameters w/ a configure command. */
        cfg = malloc_dma ( sizeof ( *cfg ), CB_ALIGN );
        if ( !cfg ) {
                rc = -ENOMEM;
                goto error;
        }
        memcpy ( cfg, &ifec_cfg, sizeof ( *cfg ) );
        cfg->link     = virt_to_bus ( priv->tcbs );
        cfg->byte[19] = ( options & 0x10 ) ? 0xC0 : 0x80;
        ias->link     = virt_to_bus ( cfg );

        /* Issue the ias and configure commands. */
        ifec_scb_cmd ( netdev, virt_to_bus ( ias ), CUStart );
        ifec_scb_cmd_wait ( netdev );
        priv->configured = 1;

        /* Wait up to 10 ms for configuration to initiate */
        for ( i = 10; i && !cfg->status; i-- )
                mdelay ( 1 );
        if ( ! cfg->status ) {
                DBG ( "Failed to initiate!\n" );
                goto error;
        }
        free_dma ( ias, sizeof ( *ias ) );
        free_dma ( cfg, sizeof ( *cfg ) );
        DBG2 ( "cfg " );

        /* Enable rx by sending ring address to card */
        if ( priv->rfds[0] != NULL ) {
                ifec_scb_cmd ( netdev, virt_to_bus( priv->rfds[0] ), RUStart );
                ifec_scb_cmd_wait ( netdev );
        }
        DBG2 ( "rx_start\n" );

        return 0;

error:
        free_dma ( cfg, sizeof ( *cfg ) );
        free_dma ( ias, sizeof ( *ias ) );
        ifec_free ( netdev );
        ifec_reset ( netdev );
        return rc;
}
static void ifec_net_poll ( struct net_device netdev) [static]

Definition at line 400 of file eepro100.c.

References DBG2, DBGP, ifec_check_ru_status(), ifec_rx_process(), ifec_tx_process(), INTERRUPT_MASK, inw(), ifec_private::ioaddr, outw(), priv, net_device::priv, and SCBStatus.

{
        struct ifec_private *priv = netdev->priv;
        unsigned short intr_status;

        DBGP ( "ifec_net_poll\n" );

        /* acknowledge interrupts ASAP */
        intr_status = inw ( priv->ioaddr + SCBStatus );
        outw ( intr_status, priv->ioaddr + SCBStatus );
        inw ( priv->ioaddr + SCBStatus );

        DBG2 ( "poll - status: 0x%04X\n", intr_status );

        /* anything to do here? */
        if ( ( intr_status & ( ~INTERRUPT_MASK ) ) == 0 )
                return;

        /* process received and transmitted packets */
        ifec_tx_process ( netdev );
        ifec_rx_process ( netdev );

        ifec_check_ru_status ( netdev, intr_status );

        return;
}
static int ifec_net_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Definition at line 436 of file eepro100.c.

References CmdSuspend, CmdTx, CmdTxFlex, ifec_tcb::command, ifec_tcb::count, io_buffer::data, DBG, DBG2, DBGP, ENOBUFS, ifec_tx_wake(), inw(), ioaddr, ifec_private::ioaddr, ifec_tcb::iob, iob_len(), ifec_tcb::next, priv, net_device::priv, SCBCmd, ifec_tcb::status, ifec_tcb::tbd_addr0, ifec_tcb::tbd_size0, ifec_private::tcb_head, and virt_to_bus().

{
        struct ifec_private *priv = netdev->priv;
        struct ifec_tcb *tcb = priv->tcb_head->next;
        unsigned long ioaddr = priv->ioaddr;

        DBGP ( "ifec_net_transmit\n" );

        /* Wait for TCB to become available. */
        if ( tcb->status || tcb->iob ) {
                DBG ( "TX overflow\n" );
                return -ENOBUFS;
        }

        DBG2 ( "transmitting packet (%zd bytes). status = %hX, cmd=%hX\n",
                iob_len ( iobuf ), tcb->status, inw ( ioaddr + SCBCmd ) );

        tcb->command   = CmdSuspend | CmdTx | CmdTxFlex;
        tcb->count     = 0x01208000;
        tcb->tbd_addr0 = virt_to_bus ( iobuf->data );
        tcb->tbd_size0 = 0x3FFF & iob_len ( iobuf );
        tcb->iob = iobuf;

        ifec_tx_wake ( netdev );

        /* Append to end of ring. */
        priv->tcb_head = tcb;

        return 0;
}
static int ifec_spi_read_bit ( struct bit_basher basher,
unsigned int  bit_id 
) [static]

Definition at line 485 of file eepro100.c.

References spi_bit_basher::basher, container_of, CSREeprom, DBGP, inw(), ifec_private::ioaddr, priv, and ifec_private::spi.

{
        struct ifec_private *priv =
                container_of ( basher, struct ifec_private, spi.basher );
        unsigned long ee_addr = priv->ioaddr + CSREeprom;
        unsigned int ret = 0;
        uint16_t mask;

        DBGP ( "ifec_spi_read_bit\n" );

        mask = ifec_ee_bits[bit_id];
        ret = inw (ee_addr);

        return ( ret & mask ) ? 1 : 0;
}
static void ifec_spi_write_bit ( struct bit_basher basher,
unsigned int  bit_id,
unsigned long  data 
) [static]

Definition at line 510 of file eepro100.c.

References spi_bit_basher::basher, container_of, CSREeprom, DBGP, inw(), ifec_private::ioaddr, outw(), priv, ifec_private::spi, and val.

{
        struct ifec_private *priv =
                container_of ( basher, struct ifec_private, spi.basher );
        unsigned long ee_addr = priv->ioaddr + CSREeprom;
        short val;
        uint16_t mask = ifec_ee_bits[bit_id];

        DBGP ( "ifec_spi_write_bit\n" );

        val = inw ( ee_addr );
        val &= ~mask;
        val |= data & mask;

        outw ( val, ee_addr );
}
static void ifec_init_eeprom ( struct net_device netdev) [static]

Definition at line 540 of file eepro100.c.

References spi_device::address_len, spi_bit_basher::basher, spi_bit_basher::bus, spi_device::bus, DBGP, ifec_private::eeprom, ifec_basher_ops, init_spi_bit_basher(), spi_bus::mode, bit_basher::op, priv, net_device::priv, ifec_private::spi, SPI_MODE_THREEWIRE, and threewire_detect_address_len().

Referenced by ifec_pci_probe().

{
        struct ifec_private *priv = netdev->priv;

        DBGP ( "ifec_init_eeprom\n" );

        priv->spi.basher.op = &ifec_basher_ops;
        priv->spi.bus.mode = SPI_MODE_THREEWIRE;
        init_spi_bit_basher ( &priv->spi );

        priv->eeprom.bus = &priv->spi.bus;

        /* init as 93c46(93c14 compatible) first, to set the command len,
         * block size and word len. Needs to be set for address len detection.
         */
        init_at93c46 ( &priv->eeprom, 16 );

        /* detect address length, */
        threewire_detect_address_len ( &priv->eeprom );

        /* address len == 8 means 93c66 instead of 93c46 */
        if ( priv->eeprom.address_len == 8 )
                init_at93c66 ( &priv->eeprom, 16 );
}
static int ifec_mdio_read ( struct net_device netdev,
int  phy_id,
int  location 
) [static]

Definition at line 571 of file eepro100.c.

References CSRCtrlMDI, DBG, DBGP, inl(), ioaddr, ifec_private::ioaddr, outl(), priv, net_device::priv, udelay(), and val.

Referenced by ifec_mdio_setup().

{
        struct ifec_private *priv = netdev->priv;
        unsigned long ioaddr = priv->ioaddr;
        int val;
        int boguscnt = 64*4;     /* <64 usec. to complete, typ 27 ticks */

        DBGP ( "ifec_mdio_read\n" );

        outl ( 0x08000000 | ( location << 16 ) | ( phy_id << 21 ),
               ioaddr + CSRCtrlMDI );
        do {
                udelay ( 16 );

                val = inl ( ioaddr + CSRCtrlMDI );

                if ( --boguscnt < 0 ) {
                        DBG ( " ifec_mdio_read() time out with val = %X.\n",
                                 val );
                        break;
                }
        } while (! ( val & 0x10000000 ) );
        return val & 0xffff;
}
static void ifec_mdio_setup ( struct net_device netdev,
int  options 
) [static]

Definition at line 603 of file eepro100.c.

References CONGENB, DBG2, DBGP, DP83840, DP83840A, ifec_mdio_read(), ifec_mdio_write(), ifec_private::mdio_register, priv, and net_device::priv.

Referenced by ifec_net_open().

{
        struct ifec_private *priv = netdev->priv;
        unsigned short mdio_register = priv->mdio_register;

        DBGP ( "ifec_mdio_setup\n" );

        if (   ( (mdio_register>>8) & 0x3f ) == DP83840
            || ( (mdio_register>>8) & 0x3f ) == DP83840A ) {
                int mdi_reg23 = ifec_mdio_read ( netdev, mdio_register
                                                  & 0x1f, 23 ) | 0x0422;
                if (CONGENB)
                        mdi_reg23 |= 0x0100;
                DBG2 ( "DP83840 specific setup, setting register 23 to "
                                                         "%hX.\n", mdi_reg23 );
                ifec_mdio_write ( netdev, mdio_register & 0x1f, 23, mdi_reg23 );
        }
        DBG2 ( "dp83840 " );
        if ( options != 0 ) {
                ifec_mdio_write ( netdev, mdio_register & 0x1f, 0,
                                           ( (options & 0x20) ? 0x2000 : 0 ) |
                                           ( (options & 0x10) ? 0x0100 : 0 ) );
                DBG2 ( "set mdio_register. " );
        }
}
static int ifec_mdio_write ( struct net_device netdev,
int  phy_id,
int  location,
int  value 
) [static]

Definition at line 635 of file eepro100.c.

References CSRCtrlMDI, DBG, DBGP, inl(), ioaddr, ifec_private::ioaddr, outl(), priv, net_device::priv, udelay(), and val.

Referenced by ifec_mdio_setup().

{
        struct ifec_private *priv = netdev->priv;
        unsigned long ioaddr = priv->ioaddr;
        int val;
        int boguscnt = 64*4;     /* <64 usec. to complete, typ 27 ticks */

        DBGP ( "ifec_mdio_write\n" );

        outl ( 0x04000000 | ( location << 16 ) | ( phy_id << 21 ) | value,
               ioaddr + CSRCtrlMDI );
        do {
                udelay ( 16 );

                val = inl ( ioaddr + CSRCtrlMDI );
                if ( --boguscnt < 0 ) {
                        DBG ( " ifec_mdio_write() time out with val = %X.\n",
                              val );
                        break;
                }
        } while (! ( val & 0x10000000 ) );
        return val & 0xffff;
}
static void ifec_reset ( struct net_device netdev) [static]

Definition at line 665 of file eepro100.c.

References CSRPort, DBGP, ifec_net_irq(), inw(), ioaddr, ifec_private::ioaddr, outl(), PortPartialReset, PortReset, priv, net_device::priv, SCBStatus, and udelay().

Referenced by ifec_net_close(), ifec_net_open(), ifec_pci_probe(), and ifec_pci_remove().

{
        struct ifec_private *priv = netdev->priv;
        unsigned long ioaddr = priv->ioaddr;

        DBGP ( "ifec_reset\n" );

        /* do partial reset first */
        outl ( PortPartialReset, ioaddr + CSRPort );
        inw ( ioaddr + SCBStatus );
        udelay ( 20 );

        /* full reset */
        outl ( PortReset, ioaddr + CSRPort );
        inw ( ioaddr + SCBStatus );
        udelay ( 20 );

        /* disable interrupts again */
        ifec_net_irq ( netdev, 0 );
}
static void ifec_free ( struct net_device netdev) [static]

Definition at line 691 of file eepro100.c.

References DBGP, free_dma(), free_iob(), netdev_priv(), NULL, priv, RFD_COUNT, ifec_private::rfds, ifec_private::rx_iobs, ifec_private::tcbs, and TX_RING_BYTES.

Referenced by ifec_net_close(), and ifec_net_open().

{
        struct ifec_private *priv = netdev_priv ( netdev );
        int i;

        DBGP ( "ifec_free\n" );

        /* free all allocated receive io_buffers */
        for ( i = 0; i < RFD_COUNT; i++ ) {
                free_iob ( priv->rx_iobs[i] );
                priv->rx_iobs[i] = NULL;
                priv->rfds[i] = NULL;
        }

        /* free TX ring buffer */
        free_dma ( priv->tcbs, TX_RING_BYTES );

        priv->tcbs = NULL;
}
static void ifec_rfd_init ( struct ifec_rfd rfd,
s16  command,
u32  link 
) [static]

Definition at line 718 of file eepro100.c.

References command, ifec_rfd::command, ifec_rfd::count, DBGP, link, ifec_rfd::link, RFD_PACKET_LEN, ifec_rfd::rx_buf_addr, ifec_rfd::size, and ifec_rfd::status.

Referenced by ifec_get_rx_desc().

{
        DBGP ( "ifec_rfd_init\n" );

        rfd->status      = 0;
        rfd->command     = command;
        rfd->rx_buf_addr = 0xFFFFFFFF;
        rfd->count       = 0;
        rfd->size        = RFD_PACKET_LEN;
        rfd->link        = link;
}
static void ifec_reprime_ru ( struct net_device netdev) [static]

Definition at line 735 of file eepro100.c.

References cur_rx, ifec_private::cur_rx, DBGP, ifec_scb_cmd(), ifec_scb_cmd_wait(), NULL, priv, net_device::priv, ifec_private::rfds, RUStart, and virt_to_bus().

Referenced by ifec_check_ru_status().

{
        struct ifec_private *priv = netdev->priv;
        int cur_rx = priv->cur_rx;
        
        DBGP ( "ifec_reprime_ru\n" );
        
        if ( priv->rfds[cur_rx] != NULL ) {
                ifec_scb_cmd ( netdev, virt_to_bus ( priv->rfds[cur_rx] ),
                               RUStart );
                ifec_scb_cmd_wait ( netdev );
        }
}
static void ifec_check_ru_status ( struct net_device netdev,
unsigned short  intr_status 
) [static]

Definition at line 754 of file eepro100.c.

References DBG, DBGP, ifec_reprime_ru(), inw(), ifec_private::ioaddr, priv, net_device::priv, and SCBStatus.

Referenced by ifec_net_poll(), and ifec_refill_rx_ring().

{
        struct ifec_private *priv = netdev->priv;

        DBGP ( "ifec_check_ru_status\n" );

        /*
        * The chip may have suspended reception for various reasons.
        * Check for that, and re-prime it should this be the case.
        */
        switch ( ( intr_status >> 2 ) & 0xf ) {
                case 0:  /* Idle */
                case 4:  /* Ready */
                        break;
                case 1:  /* Suspended */
                case 2:  /* No resources (RFDs) */
                case 9:  /* Suspended with no more RBDs */
                case 10: /* No resources due to no RBDs */
                case 12: /* Ready with no RBDs */
                        DBG ( "ifec_net_poll: RU reprimed.\n" );
                        ifec_reprime_ru ( netdev );
                        break;
                default:
                        /* reserved values */
                        DBG ( "ifec_net_poll: RU state anomaly: %i\n",
                              ( inw ( priv->ioaddr + SCBStatus ) >> 2 ) & 0xf );
                        break;
        }
}
static void ifec_rx_process ( struct net_device netdev) [static]

Definition at line 793 of file eepro100.c.

References ifec_rfd::count, cur_rx, ifec_private::cur_rx, DBG, DBG2, DBGIO_HD, DBGP, EINVAL, ifec_refill_rx_ring(), iob_put, netdev_rx(), netdev_rx_err(), NULL, ifec_rfd::packet, priv, net_device::priv, RFD_COUNT, RFD_OK, RFD_STATUS, RFDMaskCount, ifec_private::rfds, RFDShort, ifec_private::rx_iobs, status, and ifec_rfd::status.

Referenced by ifec_net_poll().

{
        struct ifec_private *priv   = netdev->priv;
        int cur_rx = priv->cur_rx;
        struct io_buffer *iob = priv->rx_iobs[cur_rx];
        struct ifec_rfd *rfd = priv->rfds[cur_rx];
        unsigned int rx_len;
        s16 status;

        DBGP ( "ifec_rx_process\n" );

        /* Process any received packets */
        while ( iob && rfd && ( status = rfd->status ) ) {
                rx_len = rfd->count & RFDMaskCount;

                DBG2 ( "Got a packet: Len = %d, cur_rx = %d.\n", rx_len,
                       cur_rx );
                DBGIO_HD ( (void*)rfd->packet, 0x30 );

                if ( ( status & ( RFD_STATUS & ~RFDShort ) ) != RFD_OK ) {
                        DBG ( "Corrupted packet received. "
                              "Status = %#08hx\n", status );
                        netdev_rx_err ( netdev, iob, -EINVAL );
                } else {
                        /* Hand off the packet to the network subsystem */
                        iob_put ( iob, rx_len );
                        DBG2 ( "Received packet: %p, len: %d\n", iob, rx_len );
                        netdev_rx ( netdev, iob );
                }

                /* make sure we don't reuse this RFD */
                priv->rx_iobs[cur_rx] = NULL;
                priv->rfds[cur_rx] = NULL;

                /* Next RFD */
                priv->cur_rx = ( cur_rx + 1 ) % RFD_COUNT;
                cur_rx = priv->cur_rx;
                iob = priv->rx_iobs[cur_rx];
                rfd = priv->rfds[cur_rx];
        }

        ifec_refill_rx_ring ( netdev );
}
static int ifec_get_rx_desc ( struct net_device netdev,
int  cur,
int  cmd,
int  link 
) [static]

Definition at line 847 of file eepro100.c.

References alloc_iob(), io_buffer::data, DBG, DBGP, ENOMEM, ifec_rfd_init(), iob_reserve, NULL, priv, net_device::priv, RFD_HEADER_LEN, ifec_private::rfds, and ifec_private::rx_iobs.

Referenced by ifec_refill_rx_ring().

{
        struct ifec_private *priv = netdev->priv;
        struct ifec_rfd *rfd  = priv->rfds[cur];

        DBGP ( "ifec_get_rx_desc\n" );

        priv->rx_iobs[cur] = alloc_iob ( sizeof ( *rfd ) );
        if ( ! priv->rx_iobs[cur] ) {
                DBG ( "alloc_iob failed. desc. nr: %d\n", cur );
                priv->rfds[cur] = NULL;
                return -ENOMEM;
        }

        /* Initialize new tail. */
        priv->rfds[cur] = priv->rx_iobs[cur]->data;
        ifec_rfd_init ( priv->rfds[cur], cmd, link );
        iob_reserve ( priv->rx_iobs[cur], RFD_HEADER_LEN );

        return 0;
}
static void ifec_refill_rx_ring ( struct net_device netdev) [static]

Definition at line 875 of file eepro100.c.

References CmdEndOfList, CmdSuspend, ifec_rfd::command, cur_rx, ifec_private::cur_rx, DBG2, DBGP, ifec_check_ru_status(), ifec_get_rx_desc(), inw(), ifec_private::ioaddr, ifec_rfd::link, NULL, priv, net_device::priv, RFD_COUNT, ifec_private::rfds, ifec_private::rx_iobs, SCBStatus, and virt_to_bus().

Referenced by ifec_rx_process(), and ifec_rx_setup().

{
        struct ifec_private *priv = netdev->priv;
        int i, cur_rx;
        unsigned short intr_status;

        DBGP ( "ifec_refill_rx_ring\n" );

        for ( i = 0; i < RFD_COUNT; i++ ) {
                cur_rx = ( priv->cur_rx + i ) % RFD_COUNT;
                /* only refill if empty */
                if ( priv->rfds[cur_rx] != NULL ||
                     priv->rx_iobs[cur_rx] != NULL )
                        continue;

                DBG2 ( "refilling RFD %d\n", cur_rx );

                if ( ifec_get_rx_desc ( netdev, cur_rx,
                     CmdSuspend | CmdEndOfList, 0 ) == 0 ) {
                        if ( i > 0 ) {
                                int prev_rx = ( ( ( cur_rx + RFD_COUNT ) - 1 )
                                                % RFD_COUNT );
                                struct ifec_rfd *rfd = priv->rfds[prev_rx];

                                rfd->command = 0;
                                rfd->link = virt_to_bus ( priv->rfds[cur_rx] );
                        }
                }
        }

        intr_status = inw ( priv->ioaddr + SCBStatus );
        ifec_check_ru_status ( netdev, intr_status );
}
static int ifec_rx_setup ( struct net_device netdev) [static]

Definition at line 915 of file eepro100.c.

References ifec_private::cur_rx, DBGP, ifec_refill_rx_ring(), NULL, priv, net_device::priv, RFD_COUNT, ifec_private::rfds, and ifec_private::rx_iobs.

Referenced by ifec_net_open().

{
        struct ifec_private *priv = netdev->priv;
        int i;

        DBGP ( "ifec_rx_setup\n" );

        priv->cur_rx = 0;

        /* init values for ifec_refill_rx_ring() */
        for ( i = 0; i < RFD_COUNT; i++ ) {
                priv->rfds[i] = NULL;
                priv->rx_iobs[i] = NULL;
        }
        ifec_refill_rx_ring ( netdev );

        return 0;
}
static int ifec_scb_cmd ( struct net_device netdev,
u32  ptr,
u8  cmd 
) [static]

Definition at line 942 of file eepro100.c.

References DBGP, ifec_scb_cmd_wait(), ioaddr, ifec_private::ioaddr, outb(), outl(), priv, net_device::priv, rc, SCBCmd, and SCBPointer.

Referenced by ifec_net_open(), ifec_reprime_ru(), and ifec_tx_wake().

{
        struct ifec_private *priv = netdev->priv;
        unsigned long ioaddr = priv->ioaddr;
        int rc;

        DBGP ( "ifec_scb_cmd\n" );

        rc = ifec_scb_cmd_wait ( netdev );      /* Wait until ready */
        if ( !rc ) {
                outl ( ptr, ioaddr + SCBPointer );
                outb ( cmd, ioaddr + SCBCmd );          /* Issue command */
        }
        return rc;
}
static int ifec_scb_cmd_wait ( struct net_device netdev) [static]

Definition at line 964 of file eepro100.c.

References CU_CMD_TIMEOUT, DBG, DBGP, inb(), ifec_private::ioaddr, priv, net_device::priv, rc, SCBCmd, and udelay().

Referenced by ifec_net_open(), ifec_reprime_ru(), ifec_scb_cmd(), and ifec_tx_wake().

{
        struct ifec_private *priv = netdev->priv;
        unsigned long cmd_ioaddr = priv->ioaddr + SCBCmd;
        int rc, wait = CU_CMD_TIMEOUT;

        DBGP ( "ifec_scb_cmd_wait\n" );

        for ( ; wait && ( rc = inb ( cmd_ioaddr ) ); wait-- )
                udelay ( 1 );

        if ( !wait )
                DBG ( "ifec_scb_cmd_wait timeout!\n" );
        return rc;
}
static void ifec_tx_process ( struct net_device netdev) [static]

Definition at line 985 of file eepro100.c.

References DBG, DBG2, DBGP, EINVAL, ifec_tcb::iob, netdev_tx_complete(), netdev_tx_complete_err(), ifec_tcb::next, NULL, priv, net_device::priv, status, ifec_tcb::status, ifec_private::tcb_tail, and TCB_U.

Referenced by ifec_net_poll().

{
        struct ifec_private *priv = netdev->priv;
        struct ifec_tcb *tcb = priv->tcb_tail;
        s16 status;

        DBGP ( "ifec_tx_process\n" );

        /* Check status of transmitted packets */
        while ( ( status = tcb->status ) && tcb->iob ) {
                if ( status & TCB_U ) {
                        /* report error to iPXE */
                        DBG ( "ifec_tx_process : tx error!\n " );
                        netdev_tx_complete_err ( netdev, tcb->iob, -EINVAL );
                } else {
                        /* report successful transmit */
                        netdev_tx_complete ( netdev, tcb->iob );
                }
                DBG2 ( "tx completion\n" );

                tcb->iob = NULL;
                tcb->status = 0;

                priv->tcb_tail = tcb->next;     /* Next TCB */
                tcb = tcb->next;
        }
}
static int ifec_tx_setup ( struct net_device netdev) [static]

Definition at line 1019 of file eepro100.c.

References CB_ALIGN, ifec_tcb::count, DBG, DBGP, ENOMEM, ifec_tcb::iob, ifec_tcb::link, malloc_dma(), ifec_tcb::next, NULL, priv, net_device::priv, ifec_tcb::status, ifec_tcb::tbd_addr0, ifec_tcb::tbda_addr, TCB_COUNT, ifec_private::tcb_head, ifec_private::tcb_tail, ifec_private::tcbs, ifec_private::tx_cnt, ifec_private::tx_curr, TX_RING_BYTES, ifec_private::tx_tail, and virt_to_bus().

Referenced by ifec_net_open().

{
        struct ifec_private *priv = netdev->priv;
        struct ifec_tcb *tcb;
        int i;

        DBGP ( "ifec_tx_setup\n" );

        /* allocate tx ring */
        priv->tcbs = malloc_dma ( TX_RING_BYTES, CB_ALIGN );
        if ( !priv->tcbs ) {
                DBG ( "TX-ring allocation failed\n" );
                return -ENOMEM;
        }

        tcb = priv->tcb_tail = priv->tcbs;
        priv->tx_curr = priv->tx_tail = 0;
        priv->tx_cnt = 0;

        for ( i = 0; i < TCB_COUNT; i++, tcb++ ) {
                tcb->status    = 0;
                tcb->count     = 0x01208000;
                tcb->iob       = NULL;
                tcb->tbda_addr = virt_to_bus ( &tcb->tbd_addr0 );
                tcb->link      = virt_to_bus ( tcb + 1 );
                tcb->next      = tcb + 1;
        }
        /* We point tcb_head at the last TCB, so the first ifec_net_transmit()
         * will use the first (head->next) TCB to transmit. */
        priv->tcb_head = --tcb;
        tcb->link = virt_to_bus ( priv->tcbs );
        tcb->next = priv->tcbs;
        
        return 0;
}
void ifec_tx_wake ( struct net_device netdev)

Definition at line 1072 of file eepro100.c.

References CmdSuspend, ifec_tcb::command, ifec_private::configured, CUResume, CUStart, DBG2, DBGP, ifec_scb_cmd(), ifec_scb_cmd_wait(), inw(), ioaddr, ifec_private::ioaddr, ifec_tcb::next, outb(), outl(), priv, net_device::priv, SCBCmd, SCBPointer, SCBStatus, ifec_private::tcb_head, and virt_to_bus().

Referenced by ifec_net_transmit().

{
        struct ifec_private *priv = netdev->priv;
        unsigned long ioaddr = priv->ioaddr;
        struct ifec_tcb *tcb = priv->tcb_head->next;

        DBGP ( "ifec_tx_wake\n" );

        /* For the special case of the first transmit, we issue a START. The
         * card won't RESUME after the configure command. */
        if ( priv->configured ) {
                priv->configured = 0;
                ifec_scb_cmd ( netdev, virt_to_bus ( tcb ), CUStart );
                ifec_scb_cmd_wait ( netdev );
                return;
        }

        /* Resume if suspended. */
        switch ( ( inw ( ioaddr + SCBStatus ) >> 6 ) & 0x3 ) {
        case 0:  /* Idle - We should not reach this state. */
                DBG2 ( "ifec_tx_wake: tx idle!\n" );
                ifec_scb_cmd ( netdev, virt_to_bus ( tcb ), CUStart );
                ifec_scb_cmd_wait ( netdev );
                return;
        case 1:  /* Suspended */
                DBG2 ( "s" );
                break;
        default: /* Active */
                DBG2 ( "a" );
        }
        ifec_scb_cmd_wait ( netdev );
        outl ( 0, ioaddr + SCBPointer );
        priv->tcb_head->command &= ~CmdSuspend;
        /* Immediately issue Resume command */
        outb ( CUResume, ioaddr + SCBCmd );
        ifec_scb_cmd_wait ( netdev );
}

Variable Documentation

struct ifec_cfg ifec_cfg [static]
Initial value:
 {
        .status  = 0,
        .command = CmdConfigure | CmdSuspend,
        .link    = 0,        
        .byte = { 22,        
                  ( TX_FIFO << 4 ) | RX_FIFO,  
                  0, 0,                        
                  RX_DMA_COUNT,                
                  TX_DMA_COUNT + 0x80,         
                  0x32,      
                  0x03,      
                  1,         
                  0,
                  0x2E,      
                  0,         
                  0x60,      
                  0, 0xf2,
                  0x48,      
                  0, 0x40,
                  0xf2,      
                  0x80,      
                  0x3f,      
                  0x0D }     
}

Definition at line 126 of file eepro100.c.

Initial value:
 {
        .open     = ifec_net_open,
        .close    = ifec_net_close,
        .transmit = ifec_net_transmit,
        .poll     = ifec_net_poll,
        .irq      = ifec_net_irq
}

Definition at line 151 of file eepro100.c.

const uint16_t ifec_ee_bits[] [static]
Initial value:

Definition at line 471 of file eepro100.c.

Initial value:
 {
        .read = ifec_spi_read_bit,
        .write = ifec_spi_write_bit,
}

Definition at line 530 of file eepro100.c.

Referenced by ifec_init_eeprom().

struct pci_device_id ifec_nics[] [static]

Definition at line 1112 of file eepro100.c.

struct pci_driver ifec_driver __pci_driver
Initial value:
 {
        .ids      = ifec_nics,
        .id_count = ( sizeof (ifec_nics) / sizeof (ifec_nics[0]) ),
        .probe    = ifec_pci_probe,
        .remove   = ifec_pci_remove
}

Definition at line 1151 of file eepro100.c.