iPXE
Defines | Functions | Variables
b44.c File Reference
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <byteswap.h>
#include <ipxe/io.h>
#include <mii.h>
#include <ipxe/iobuf.h>
#include <ipxe/malloc.h>
#include <ipxe/pci.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/if_ether.h>
#include "b44.h"

Go to the source code of this file.

Defines

#define VIRT_TO_B44(addr)   ( virt_to_bus(addr) + SB_PCI_DMA )
#define CTRL_MASK   (DMARX_CTRL_ENABLE | (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static int ring_next (int index)
static u32 br32 (const struct b44_private *bp, u32 reg)
static void bw32 (const struct b44_private *bp, u32 reg, u32 val)
static void bflush (const struct b44_private *bp, u32 reg, u32 timeout)
static int b44_address_ok (void *address)
 Check if card can access address.
static u32 pending_tx_index (struct b44_private *bp)
 Ring cells waiting to be processed are between 'tx_cur' and 'pending' indexes in the ring.
static u32 pending_rx_index (struct b44_private *bp)
 Ring cells waiting to be processed are between 'rx_cur' and 'pending' indexes in the ring.
static int b44_wait_bit (struct b44_private *bp, unsigned long reg, u32 bit, unsigned long timeout, const int clear)
 Wait until the given bit is set/cleared.
static u32 ssb_get_core_rev (struct b44_private *bp)
static int ssb_is_core_up (struct b44_private *bp)
static u32 ssb_pci_setup (struct b44_private *bp, u32 cores)
static void ssb_core_disable (struct b44_private *bp)
static void ssb_core_reset (struct b44_private *bp)
static void b44_chip_reset (struct b44_private *bp, int reset_kind)
static void b44_halt (struct b44_private *bp)
 called by b44_poll in the error path
static void b44_init_hw (struct b44_private *bp, int reset_kind)
static void b44_populate_rx_descriptor (struct b44_private *bp, u32 idx)
static void b44_rx_refill (struct b44_private *bp, u32 pending)
static void b44_free_rx_ring (struct b44_private *bp)
static int b44_init_rx_ring (struct b44_private *bp)
static void b44_free_tx_ring (struct b44_private *bp)
static int b44_init_tx_ring (struct b44_private *bp)
static int b44_phy_read (struct b44_private *bp, int reg, u32 *val)
static int b44_phy_write (struct b44_private *bp, int reg, u32 val)
static int b44_phy_reset (struct b44_private *bp)
static void b44_cam_write (struct b44_private *bp, unsigned char *data, int index)
static void b44_set_mac_addr (struct b44_private *bp)
static void b44_read_eeprom (struct b44_private *bp, u8 *data)
static void b44_load_mac_and_phy_addr (struct b44_private *bp)
static void b44_set_rx_mode (struct net_device *netdev)
static int b44_probe (struct pci_device *pci)
 Probe device.
static void b44_remove (struct pci_device *pci)
 Remove device.
static void b44_irq (struct net_device *netdev, int enable)
 Enable or disable interrupts.
static int b44_open (struct net_device *netdev)
 Open network device.
static void b44_close (struct net_device *netdev)
 Close network device.
static int b44_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet.
static void b44_tx_complete (struct b44_private *bp)
 Recycles sent TX descriptors and notifies network stack.
static void b44_process_rx_packets (struct b44_private *bp)
static void b44_poll (struct net_device *netdev)
 Poll for completed and received packets.

Variables

static struct net_device_operations b44_operations
static struct pci_device_id b44_nics []
struct pci_driver b44_driver __pci_driver

Define Documentation

#define VIRT_TO_B44 (   addr)    ( virt_to_bus(addr) + SB_PCI_DMA )
#define CTRL_MASK   (DMARX_CTRL_ENABLE | (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))

Referenced by b44_init_hw().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static int ring_next ( int  index) [inline, static]

Definition at line 50 of file b44.c.

Referenced by b44_process_rx_packets(), b44_rx_refill(), b44_transmit(), and b44_tx_complete().

{
        /* B44_RING_SIZE is a power of 2 :) */
        return (index + 1) & (B44_RING_SIZE - 1);
}
static u32 br32 ( const struct b44_private *  bp,
u32  reg 
) [inline, static]
static void bw32 ( const struct b44_private *  bp,
u32  reg,
u32  val 
) [inline, static]
static void bflush ( const struct b44_private *  bp,
u32  reg,
u32  timeout 
) [inline, static]

Definition at line 71 of file b44.c.

References readl(), and udelay().

Referenced by b44_chip_reset(), b44_halt(), b44_poll(), ssb_core_disable(), and ssb_core_reset().

{
        readl(bp->regs + reg);
        udelay(timeout);
}
static int b44_address_ok ( void *  address) [inline, static]

Check if card can access address.

Parameters:
addressVirtual address
address_okCard can access address

Definition at line 88 of file b44.c.

References virt_to_bus().

Referenced by b44_init_rx_ring(), b44_init_tx_ring(), b44_rx_refill(), and b44_transmit().

                                 {

        /* Card can address anything with a 30-bit address */
        if ( ( virt_to_bus ( address ) & ~B44_30BIT_DMA_MASK ) == 0 )
                return 1;

        return 0;
}
static u32 pending_tx_index ( struct b44_private *  bp) [static]

Ring cells waiting to be processed are between 'tx_cur' and 'pending' indexes in the ring.

Definition at line 101 of file b44.c.

References br32(), and pending.

Referenced by b44_tx_complete().

{
        u32 pending = br32(bp, B44_DMATX_STAT);
        pending &= DMATX_STAT_CDMASK;

        pending /= sizeof(struct dma_desc);
        return pending & (B44_RING_SIZE - 1);
}
static u32 pending_rx_index ( struct b44_private *  bp) [static]

Ring cells waiting to be processed are between 'rx_cur' and 'pending' indexes in the ring.

Definition at line 115 of file b44.c.

References br32(), and pending.

Referenced by b44_process_rx_packets().

{
        u32 pending = br32(bp, B44_DMARX_STAT);
        pending &= DMARX_STAT_CDMASK;

        pending /= sizeof(struct dma_desc);
        return pending & (B44_RING_SIZE - 1);
}
static int b44_wait_bit ( struct b44_private *  bp,
unsigned long  reg,
u32  bit,
unsigned long  timeout,
const int  clear 
) [static]

Wait until the given bit is set/cleared.

Definition at line 128 of file b44.c.

References br32(), ENODEV, timeout(), udelay(), and val.

Referenced by b44_cam_write(), b44_chip_reset(), b44_phy_read(), b44_phy_write(), and ssb_core_disable().

{
        unsigned long i;

        for (i = 0; i < timeout; i++) {
                u32 val = br32(bp, reg);

                if (clear && !(val & bit))
                        break;

                if (!clear && (val & bit))
                        break;

                udelay(10);
        }
        if (i == timeout) {
                return -ENODEV;
        }
        return 0;
}
static u32 ssb_get_core_rev ( struct b44_private *  bp) [inline, static]

Definition at line 163 of file b44.c.

References br32().

Referenced by ssb_pci_setup().

{
        return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
}
static int ssb_is_core_up ( struct b44_private *  bp) [inline, static]

Definition at line 169 of file b44.c.

References br32().

Referenced by b44_chip_reset().

{
        return ((br32(bp, B44_SBTMSLOW) & (SSB_CORE_DOWN | SBTMSLOW_CLOCK))
                                                        == SBTMSLOW_CLOCK);
}
static u32 ssb_pci_setup ( struct b44_private *  bp,
u32  cores 
) [static]

Definition at line 176 of file b44.c.

References br32(), bw32(), pci_read_config_dword(), pci_write_config_dword(), ssb_get_core_rev(), and val.

Referenced by b44_chip_reset().

{
        u32 bar_orig, pci_rev, val;

        pci_read_config_dword(bp->pci, SSB_BAR0_WIN, &bar_orig);
        pci_write_config_dword(bp->pci, SSB_BAR0_WIN,
                               BCM4400_PCI_CORE_ADDR);
        pci_rev = ssb_get_core_rev(bp);

        val = br32(bp, B44_SBINTVEC);
        val |= cores;
        bw32(bp, B44_SBINTVEC, val);

        val = br32(bp, SSB_PCI_TRANS_2);
        val |= SSB_PCI_PREF | SSB_PCI_BURST;
        bw32(bp, SSB_PCI_TRANS_2, val);

        pci_write_config_dword(bp->pci, SSB_BAR0_WIN, bar_orig);

        return pci_rev;
}
static void ssb_core_disable ( struct b44_private *  bp) [static]

Definition at line 199 of file b44.c.

References b44_wait_bit(), bflush(), br32(), and bw32().

Referenced by b44_remove(), and ssb_core_reset().

{
        if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
                return;

        bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
        b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
        b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);

        bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
                                                SSB_CORE_DOWN));
        bflush(bp, B44_SBTMSLOW, 1);

        bw32(bp, B44_SBTMSLOW, SSB_CORE_DOWN);
        bflush(bp, B44_SBTMSLOW, 1);
}
static void ssb_core_reset ( struct b44_private *  bp) [static]

Definition at line 217 of file b44.c.

References bflush(), br32(), bw32(), ssb_core_disable(), and val.

Referenced by b44_chip_reset().

{
        u32 val;
        const u32 mask = (SBTMSLOW_CLOCK | SBTMSLOW_FGC | SBTMSLOW_RESET);

        ssb_core_disable(bp);

        bw32(bp, B44_SBTMSLOW, mask);
        bflush(bp, B44_SBTMSLOW, 1);

        /* Clear SERR if set, this is a hw bug workaround.  */
        if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
                bw32(bp, B44_SBTMSHIGH, 0);

        val = br32(bp, B44_SBIMSTATE);
        if (val & (SBIMSTATE_BAD)) {
                bw32(bp, B44_SBIMSTATE, val & ~SBIMSTATE_BAD);
        }

        bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
        bflush(bp, B44_SBTMSLOW, 1);

        bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
        bflush(bp, B44_SBTMSLOW, 1);
}
static void b44_chip_reset ( struct b44_private *  bp,
int  reset_kind 
) [static]

Definition at line 257 of file b44.c.

References b44_wait_bit(), bflush(), br32(), bw32(), ssb_core_reset(), ssb_is_core_up(), ssb_pci_setup(), and val.

Referenced by b44_close(), b44_halt(), b44_init_hw(), and b44_probe().

{
        if (ssb_is_core_up(bp)) {
                bw32(bp, B44_RCV_LAZY, 0);

                bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);

                b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);

                bw32(bp, B44_DMATX_CTRL, 0);

                bp->tx_dirty = bp->tx_cur = 0;

                if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK)
                        b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
                                                                  100, 0);

                bw32(bp, B44_DMARX_CTRL, 0);

                bp->rx_cur = 0;
        } else {
                ssb_pci_setup(bp, SBINTVEC_ENET0);
        }

        ssb_core_reset(bp);

        /* Don't enable PHY if we are only doing a partial reset. */
        if (reset_kind == B44_CHIP_RESET_PARTIAL)
                return;

        /* Make PHY accessible. */
        bw32(bp, B44_MDIO_CTRL,
             (MDIO_CTRL_PREAMBLE | (0x0d & MDIO_CTRL_MAXF_MASK)));
        bflush(bp, B44_MDIO_CTRL, 1);

        /* Enable internal or external PHY */
        if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
                bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
                bflush(bp, B44_ENET_CTRL, 1);
        } else {
                u32 val = br32(bp, B44_DEVCTRL);
                if (val & DEVCTRL_EPR) {
                        bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
                        bflush(bp, B44_DEVCTRL, 100);
                }
        }
}
static void b44_halt ( struct b44_private *  bp) [static]

called by b44_poll in the error path

Definition at line 309 of file b44.c.

References b44_chip_reset(), bflush(), bw32(), and DBG.

Referenced by b44_poll().

{
        /* disable ints */
        bw32(bp, B44_IMASK, 0);
        bflush(bp, B44_IMASK, 1);

        DBG("b44: powering down PHY\n");
        bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);

        /*
         * Now reset the chip, but without enabling
         * the MAC&PHY part of it.
         * This has to be done _after_ we shut down the PHY
         */
        b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
}
static void b44_init_hw ( struct b44_private *  bp,
int  reset_kind 
) [static]

Definition at line 334 of file b44.c.

References b44_chip_reset(), b44_phy_reset(), b44_set_rx_mode(), br32(), bw32(), CTRL_MASK, ETH_HLEN, val, and VIRT_TO_B44.

Referenced by b44_open(), and b44_poll().

{
        u32 val;
#define CTRL_MASK (DMARX_CTRL_ENABLE | (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))

        b44_chip_reset(bp, B44_CHIP_RESET_FULL);
        if (reset_kind == B44_FULL_RESET) {
                b44_phy_reset(bp);
        }

        /* Enable CRC32, set proper LED modes and power on PHY */
        bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
        bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));

        /* This sets the MAC address too.  */
        b44_set_rx_mode(bp->netdev);

        /* MTU + eth header + possible VLAN tag + struct rx_header */
        bw32(bp, B44_RXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
        bw32(bp, B44_TXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);

        bw32(bp, B44_TX_HIWMARK, TX_HIWMARK_DEFLT);
        if (reset_kind == B44_PARTIAL_RESET) {
                bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
        } else {
                bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
                bw32(bp, B44_DMATX_ADDR, VIRT_TO_B44(bp->tx));

                bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
                bw32(bp, B44_DMARX_ADDR, VIRT_TO_B44(bp->rx));
                bw32(bp, B44_DMARX_PTR, B44_RX_RING_LEN_BYTES);

                bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
        }

        val = br32(bp, B44_ENET_CTRL);
        bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
#undef CTRL_MASK
}
static void b44_populate_rx_descriptor ( struct b44_private *  bp,
u32  idx 
) [static]

Definition at line 378 of file b44.c.

References addr, bw32(), cpu_to_le32, ctrl, and VIRT_TO_B44.

Referenced by b44_init_rx_ring(), and b44_rx_refill().

{
        struct rx_header *rh;
        u32 ctrl, addr;

        rh = bp->rx_iobuf[idx]->data;
        rh->len = 0;
        rh->flags = 0;
        ctrl = DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET);
        if (idx == B44_RING_LAST) {
                ctrl |= DESC_CTRL_EOT;
        }
        addr = VIRT_TO_B44(bp->rx_iobuf[idx]->data);

        bp->rx[idx].ctrl = cpu_to_le32(ctrl);
        bp->rx[idx].addr = cpu_to_le32(addr);
        bw32(bp, B44_DMARX_PTR, idx * sizeof(struct dma_desc));
}
static void b44_rx_refill ( struct b44_private *  bp,
u32  pending 
) [static]

Definition at line 403 of file b44.c.

References alloc_iob(), b44_address_ok(), b44_populate_rx_descriptor(), io_buffer::data, DBG, free_iob(), NULL, and ring_next().

Referenced by b44_init_rx_ring(), and b44_process_rx_packets().

{
        struct io_buffer *iobuf;
        u32 i;

        // skip pending
        for (i = pending + 1; i != bp->rx_cur; i = ring_next(i)) {
                if (bp->rx_iobuf[i] != NULL)
                        continue;

                iobuf = alloc_iob(RX_PKT_BUF_SZ);
                if (!iobuf) {
                        DBG("Refill rx ring failed!!\n");
                        break;
                }
                if (!b44_address_ok(iobuf->data)) {
                        DBG("Refill rx ring bad address!!\n");
                        free_iob(iobuf);
                        break;
                }
                bp->rx_iobuf[i] = iobuf;

                b44_populate_rx_descriptor(bp, i);
        }
}
static void b44_free_rx_ring ( struct b44_private *  bp) [static]

Definition at line 430 of file b44.c.

References free_dma(), free_iob(), and NULL.

Referenced by b44_close(), and b44_init_rx_ring().

{
        u32 i;

        if (bp->rx) {
                for (i = 0; i < B44_RING_SIZE; i++) {
                        free_iob(bp->rx_iobuf[i]);
                        bp->rx_iobuf[i] = NULL;
                }
                free_dma(bp->rx, B44_RX_RING_LEN_BYTES);
                bp->rx = NULL;
        }
}
static int b44_init_rx_ring ( struct b44_private *  bp) [static]

Definition at line 445 of file b44.c.

References alloc_iob(), b44_address_ok(), b44_free_rx_ring(), b44_populate_rx_descriptor(), b44_rx_refill(), DBG, ENOMEM, ENOTSUP, free_dma(), malloc_dma(), memset(), and VIRT_TO_B44.

Referenced by b44_open(), and b44_poll().

{
        b44_free_rx_ring(bp);

        bp->rx = malloc_dma(B44_RX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
        if (!bp->rx)
                return -ENOMEM;
        if (!b44_address_ok(bp->rx)) {
                free_dma(bp->rx, B44_RX_RING_LEN_BYTES);
                return -ENOTSUP;
        }

        memset(bp->rx_iobuf, 0, sizeof(bp->rx_iobuf));

        bp->rx_iobuf[0] = alloc_iob(RX_PKT_BUF_SZ);
        b44_populate_rx_descriptor(bp, 0);
        b44_rx_refill(bp, 0);

        DBG("Init RX rings: rx=0x%08lx\n", VIRT_TO_B44(bp->rx));
        return 0;
}
static void b44_free_tx_ring ( struct b44_private *  bp) [static]

Definition at line 468 of file b44.c.

References free_dma(), and NULL.

Referenced by b44_close(), and b44_init_tx_ring().

{
        if (bp->tx) {
                free_dma(bp->tx, B44_TX_RING_LEN_BYTES);
                bp->tx = NULL;
        }
}
static int b44_init_tx_ring ( struct b44_private *  bp) [static]

Definition at line 477 of file b44.c.

References b44_address_ok(), b44_free_tx_ring(), DBG, ENOMEM, ENOTSUP, free_dma(), malloc_dma(), memset(), and VIRT_TO_B44.

Referenced by b44_open(), and b44_poll().

{
        b44_free_tx_ring(bp);

        bp->tx = malloc_dma(B44_TX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
        if (!bp->tx)
                return -ENOMEM;
        if (!b44_address_ok(bp->tx)) {
                free_dma(bp->tx, B44_TX_RING_LEN_BYTES);
                return -ENOTSUP;
        }

        memset(bp->tx, 0, B44_TX_RING_LEN_BYTES);
        memset(bp->tx_iobuf, 0, sizeof(bp->tx_iobuf));

        DBG("Init TX rings: tx=0x%08lx\n", VIRT_TO_B44(bp->tx));
        return 0;
}
static int b44_phy_read ( struct b44_private *  bp,
int  reg,
u32 val 
) [static]

Definition at line 500 of file b44.c.

References b44_wait_bit(), br32(), and bw32().

Referenced by b44_phy_reset().

{
        int err;

        u32 arg1 = (MDIO_OP_READ << MDIO_DATA_OP_SHIFT);
        u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
        u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
        u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
        u32 argv = arg1 | arg2 | arg3 | arg4;

        bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
        bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
        err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
        *val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;

        return err;
}
static int b44_phy_write ( struct b44_private *  bp,
int  reg,
u32  val 
) [static]

Definition at line 519 of file b44.c.

References b44_wait_bit(), and bw32().

Referenced by b44_phy_reset().

{
        u32 arg1 = (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT);
        u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
        u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
        u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
        u32 arg5 = (val & MDIO_DATA_DATA);
        u32 argv = arg1 | arg2 | arg3 | arg4 | arg5;


        bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
        bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
        return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
}
static int b44_phy_reset ( struct b44_private *  bp) [static]

Definition at line 535 of file b44.c.

References b44_phy_read(), b44_phy_write(), BMCR_RESET, ENODEV, MII_BMCR, udelay(), and val.

Referenced by b44_init_hw().

{
        u32 val;
        int err;

        err = b44_phy_write(bp, MII_BMCR, BMCR_RESET);
        if (err)
                return err;

        udelay(100);
        err = b44_phy_read(bp, MII_BMCR, &val);
        if (!err) {
                if (val & BMCR_RESET) {
                        return -ENODEV;
                }
        }

        return 0;
}
static void b44_cam_write ( struct b44_private *  bp,
unsigned char *  data,
int  index 
) [static]

Definition at line 560 of file b44.c.

References b44_wait_bit(), bw32(), and val.

Referenced by b44_set_mac_addr(), and b44_set_rx_mode().

{
        u32 val;

        val  = ((u32) data[2]) << 24;
        val |= ((u32) data[3]) << 16;
        val |= ((u32) data[4]) << 8;
        val |= ((u32) data[5]) << 0;
        bw32(bp, B44_CAM_DATA_LO, val);


        val = (CAM_DATA_HI_VALID |
               (((u32) data[0]) << 8) | (((u32) data[1]) << 0));

        bw32(bp, B44_CAM_DATA_HI, val);

        val = CAM_CTRL_WRITE | (index << CAM_CTRL_INDEX_SHIFT);
        bw32(bp, B44_CAM_CTRL, val);

        b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
}
static void b44_set_mac_addr ( struct b44_private *  bp) [static]

Definition at line 584 of file b44.c.

References b44_cam_write(), br32(), bw32(), and val.

Referenced by b44_set_rx_mode().

{
        u32 val;
        bw32(bp, B44_CAM_CTRL, 0);
        b44_cam_write(bp, bp->netdev->ll_addr, 0);
        val = br32(bp, B44_CAM_CTRL);
        bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
}
static void b44_read_eeprom ( struct b44_private *  bp,
u8 data 
) [static]

Definition at line 595 of file b44.c.

References cpu_to_le16, and readw().

Referenced by b44_load_mac_and_phy_addr().

{
        long i;
        u16 *ptr = (u16 *) data;

        for (i = 0; i < 128; i += 2)
                ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i));
}
static void b44_load_mac_and_phy_addr ( struct b44_private *  bp) [static]

Definition at line 605 of file b44.c.

References b44_read_eeprom(), and eeprom.

Referenced by b44_probe().

{
        u8 eeprom[128];

        /* Load MAC address, note byteswapping */
        b44_read_eeprom(bp, &eeprom[0]);
        bp->netdev->hw_addr[0] = eeprom[79];
        bp->netdev->hw_addr[1] = eeprom[78];
        bp->netdev->hw_addr[2] = eeprom[81];
        bp->netdev->hw_addr[3] = eeprom[80];
        bp->netdev->hw_addr[4] = eeprom[83];
        bp->netdev->hw_addr[5] = eeprom[82];

        /* Load PHY address */
        bp->phy_addr = eeprom[90] & 0x1f;
}
static void b44_set_rx_mode ( struct net_device netdev) [static]

Definition at line 623 of file b44.c.

References b44_cam_write(), b44_set_mac_addr(), bp, br32(), bw32(), netdev_priv(), val, and zero.

Referenced by b44_init_hw().

{
        struct b44_private *bp = netdev_priv(netdev);
        unsigned char zero[6] = { 0, 0, 0, 0, 0, 0 };
        u32 val;
        int i;

        val = br32(bp, B44_RXCONFIG);
        val &= ~RXCONFIG_PROMISC;
        val |= RXCONFIG_ALLMULTI;

        b44_set_mac_addr(bp);

        for (i = 1; i < 64; i++)
                b44_cam_write(bp, zero, i);

        bw32(bp, B44_RXCONFIG, val);
        val = br32(bp, B44_CAM_CTRL);
        bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
}
static int b44_probe ( struct pci_device pci) [static]

Probe device.

Parameters:
pciPCI device
idMatching entry in ID table
Return values:
rcReturn status code

Definition at line 654 of file b44.c.

References adjust_pci_device(), alloc_etherdev(), b44_chip_reset(), b44_load_mac_and_phy_addr(), b44_operations, bp, DBG, pci_device::dev, net_device::dev, pci_device_id::device, ENOMEM, eth_ntoa(), pci_device::id, ioremap(), iounmap(), net_device::ll_addr, pci_device::membase, memset(), pci_device_id::name, netdev, netdev_init(), netdev_link_up(), netdev_priv(), netdev_put(), pci_set_drvdata(), rc, register_netdev(), and pci_device_id::vendor.

{
        struct net_device *netdev;
        struct b44_private *bp;
        int rc;

        /* Set up netdev */
        netdev = alloc_etherdev(sizeof(*bp));
        if (!netdev)
                return -ENOMEM;

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

        /* Set up private data */
        bp = netdev_priv(netdev);
        memset(bp, 0, sizeof(*bp));
        bp->netdev = netdev;
        bp->pci = pci;

        /* Map device registers */
        bp->regs = ioremap(pci->membase, B44_REGS_SIZE);
        if (!bp->regs) {
                netdev_put(netdev);
                return -ENOMEM;
        }

        /* Enable PCI bus mastering */
        adjust_pci_device(pci);

        b44_load_mac_and_phy_addr(bp);

        rc = register_netdev(netdev);
        if (rc != 0) {
                iounmap(bp->regs);
                netdev_put(netdev);
                return rc;
        }

        /* Link management currently not implemented */
        netdev_link_up(netdev);

        b44_chip_reset(bp, B44_CHIP_RESET_FULL);

        DBG("b44 %s (%04x:%04x) regs=%p MAC=%s\n", pci->id->name,
            pci->id->vendor, pci->id->device, bp->regs,
            eth_ntoa(netdev->ll_addr));

        return 0;
}
static void b44_remove ( struct pci_device pci) [static]

Remove device.

Parameters:
pciPCI device

Definition at line 712 of file b44.c.

References bp, iounmap(), netdev, netdev_nullify(), netdev_priv(), netdev_put(), pci_get_drvdata(), ssb_core_disable(), and unregister_netdev().

{
        struct net_device *netdev = pci_get_drvdata(pci);
        struct b44_private *bp = netdev_priv(netdev);

        ssb_core_disable(bp);
        unregister_netdev(netdev);
        iounmap(bp->regs);
        netdev_nullify(netdev);
        netdev_put(netdev);
}
static void b44_irq ( struct net_device netdev,
int  enable 
) [static]

Enable or disable interrupts.

Parameters:
netdevNetwork device
enableInterrupts should be enabled

Definition at line 730 of file b44.c.

References bp, bw32(), and netdev_priv().

Referenced by b44_open(), and b44_poll().

{
        struct b44_private *bp = netdev_priv(netdev);

        /* Interrupt mask specifies which events generate interrupts */
        bw32(bp, B44_IMASK, enable ? IMASK_DEF : IMASK_DISABLE);
}
static int b44_open ( struct net_device netdev) [static]

Open network device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 744 of file b44.c.

References b44_init_hw(), b44_init_rx_ring(), b44_init_tx_ring(), b44_irq(), bp, netdev_priv(), and rc.

{
        struct b44_private *bp = netdev_priv(netdev);
        int rc;

        rc = b44_init_tx_ring(bp);
        if (rc != 0)
                return rc;

        rc = b44_init_rx_ring(bp);
        if (rc != 0)
                return rc;

        b44_init_hw(bp, B44_FULL_RESET);

        /* Disable interrupts */
        b44_irq(netdev, 0);

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

Close network device.

Parameters:
netdevNetwork device

Definition at line 770 of file b44.c.

References b44_chip_reset(), b44_free_rx_ring(), b44_free_tx_ring(), bp, and netdev_priv().

{
        struct b44_private *bp = netdev_priv(netdev);

        b44_chip_reset(bp, B44_FULL_RESET);
        b44_free_tx_ring(bp);
        b44_free_rx_ring(bp);
}
static int b44_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 786 of file b44.c.

References b44_address_ok(), bp, bw32(), cpu_to_le32, ctrl, io_buffer::data, DBG, ENOBUFS, ENOTSUP, iob_len(), netdev_priv(), ring_next(), VIRT_TO_B44, and wmb.

{
        struct b44_private *bp = netdev_priv(netdev);
        u32 cur = bp->tx_cur;
        u32 ctrl;

        /* Check for TX ring overflow */
        if (bp->tx[cur].ctrl) {
                DBG("tx overflow\n");
                return -ENOBUFS;
        }

        /* Check for addressability */
        if (!b44_address_ok(iobuf->data))
                return -ENOTSUP;

        /* Will call netdev_tx_complete() on the iobuf later */
        bp->tx_iobuf[cur] = iobuf;

        /* Set up TX descriptor */
        ctrl = (iob_len(iobuf) & DESC_CTRL_LEN) |
            DESC_CTRL_IOC | DESC_CTRL_SOF | DESC_CTRL_EOF;

        if (cur == B44_RING_LAST)
                ctrl |= DESC_CTRL_EOT;

        bp->tx[cur].ctrl = cpu_to_le32(ctrl);
        bp->tx[cur].addr = cpu_to_le32(VIRT_TO_B44(iobuf->data));

        /* Update next available descriptor index */
        cur = ring_next(cur);
        bp->tx_cur = cur;
        wmb();

        /* Tell card that a new TX descriptor is ready */
        bw32(bp, B44_DMATX_PTR, cur * sizeof(struct dma_desc));
        return 0;
}
static void b44_tx_complete ( struct b44_private *  bp) [static]

Recycles sent TX descriptors and notifies network stack.

Parameters:
bpDriver state

Definition at line 830 of file b44.c.

References netdev_tx_complete(), NULL, pending_tx_index(), and ring_next().

Referenced by b44_poll().

{
        u32 cur, i;

        cur = pending_tx_index(bp);

        for (i = bp->tx_dirty; i != cur; i = ring_next(i)) {
                /* Free finished frame */
                netdev_tx_complete(bp->netdev, bp->tx_iobuf[i]);
                bp->tx_iobuf[i] = NULL;

                /* Clear TX descriptor */
                bp->tx[i].ctrl = 0;
                bp->tx[i].addr = 0;
        }
        bp->tx_dirty = cur;
}
static void b44_process_rx_packets ( struct b44_private *  bp) [static]

Definition at line 849 of file b44.c.

References b44_rx_refill(), cpu_to_le16, io_buffer::data, DBG, EINVAL, iob_put, iob_reserve, le16_to_cpu, len, netdev_rx(), netdev_rx_err(), NULL, pending, pending_rx_index(), and ring_next().

Referenced by b44_poll().

{
        struct io_buffer *iob;  /* received data */
        struct rx_header *rh;
        u32 pending, i;
        u16 len;

        pending = pending_rx_index(bp);

        for (i = bp->rx_cur; i != pending; i = ring_next(i)) {
                iob = bp->rx_iobuf[i];
                if (iob == NULL)
                        break;

                rh = iob->data;
                len = le16_to_cpu(rh->len);

                /*
                 * Guard against incompletely written RX descriptors.
                 * Without this, things can get really slow!
                 */
                if (len == 0)
                        break;

                /* Discard CRC that is generated by the card */
                len -= 4;

                /* Check for invalid packets and errors */
                if (len > RX_PKT_BUF_SZ - RX_PKT_OFFSET ||
                    (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
                        DBG("rx error len=%d flags=%04x\n", len,
                                         cpu_to_le16(rh->flags));
                        rh->len = 0;
                        rh->flags = 0;
                        netdev_rx_err(bp->netdev, iob, -EINVAL);
                        continue;
                }

                /* Clear RX descriptor */
                rh->len = 0;
                rh->flags = 0;
                bp->rx_iobuf[i] = NULL;

                /* Hand off the IO buffer to the network stack */
                iob_reserve(iob, RX_PKT_OFFSET);
                iob_put(iob, len);
                netdev_rx(bp->netdev, iob);
        }
        bp->rx_cur = i;
        b44_rx_refill(bp, pending_rx_index(bp));
}
static void b44_poll ( struct net_device netdev) [static]

Poll for completed and received packets.

Parameters:
netdevNetwork device

Definition at line 906 of file b44.c.

References b44_halt(), b44_init_hw(), b44_init_rx_ring(), b44_init_tx_ring(), b44_irq(), b44_process_rx_packets(), b44_tx_complete(), bflush(), bp, br32(), bw32(), DBG, and netdev_priv().

{
        struct b44_private *bp = netdev_priv(netdev);
        u32 istat;

        /* Interrupt status */
        istat = br32(bp, B44_ISTAT);
        istat &= IMASK_DEF;     /* only the events we care about */

        if (!istat)
                return;
        if (istat & ISTAT_TX)
                b44_tx_complete(bp);
        if (istat & ISTAT_RX)
                b44_process_rx_packets(bp);
        if (istat & ISTAT_ERRORS) {
                DBG("b44 error istat=0x%08x\n", istat);

                /* Reset B44 core partially to avoid long waits */
                b44_irq(bp->netdev, 0);
                b44_halt(bp);
                b44_init_tx_ring(bp);
                b44_init_rx_ring(bp);
                b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
        }

        /* Acknowledge interrupt */
        bw32(bp, B44_ISTAT, 0);
        bflush(bp, B44_ISTAT, 1);
}

Variable Documentation

Initial value:
 {
        .open = b44_open,
        .close = b44_close,
        .transmit = b44_transmit,
        .poll = b44_poll,
        .irq = b44_irq,
}

Definition at line 938 of file b44.c.

Referenced by b44_probe().

struct pci_device_id b44_nics[] [static]
Initial value:
 {
        PCI_ROM(0x14e4, 0x4401, "BCM4401", "BCM4401", 0),
        PCI_ROM(0x14e4, 0x170c, "BCM4401-B0", "BCM4401-B0", 0),
        PCI_ROM(0x14e4, 0x4402, "BCM4401-B1", "BCM4401-B1", 0),
}

Definition at line 947 of file b44.c.

struct pci_driver b44_driver __pci_driver
Initial value:
 {
        .ids = b44_nics,
        .id_count = sizeof b44_nics / sizeof b44_nics[0],
        .probe = b44_probe,
        .remove = b44_remove,
}

Definition at line 954 of file b44.c.