Annotation of qemu/roms/ipxe/src/drivers/net/b44.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2008 Stefan Hajnoczi <[email protected]>
                      3:  * Copyright (c) 2008 Pantelis Koukousoulas <[email protected]>
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or
                      6:  * modify it under the terms of the GNU General Public License as
                      7:  * published by the Free Software Foundation; either version 2 of the
                      8:  * License, or any later version.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     13:  * General Public License for more details.
                     14:  *
                     15:  * You should have received a copy of the GNU General Public License
                     16:  * along with this program; if not, write to the Free Software
                     17:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     18:  *
                     19:  * This driver is a port of the b44 linux driver version 1.01
                     20:  *
                     21:  * Copyright (c) 2002 David S. Miller <[email protected]>
                     22:  * Copyright (c) Pekka Pietikainen <[email protected]>
                     23:  * Copyright (C) 2006 Broadcom Corporation.
                     24:  *
                     25:  * Some ssb bits copied from version 2.0 of the b44 driver
                     26:  * Copyright (c) Michael Buesch
                     27:  *
                     28:  * Copyright (c) a lot of people too. Please respect their work.
                     29:  */
                     30: 
                     31: FILE_LICENCE ( GPL2_OR_LATER );
                     32: 
                     33: #include <errno.h>
                     34: #include <assert.h>
                     35: #include <stdio.h>
                     36: #include <unistd.h>
                     37: #include <byteswap.h>
                     38: #include <ipxe/io.h>
                     39: #include <mii.h>
                     40: #include <ipxe/iobuf.h>
                     41: #include <ipxe/malloc.h>
                     42: #include <ipxe/pci.h>
                     43: #include <ipxe/netdevice.h>
                     44: #include <ipxe/ethernet.h>
                     45: #include <ipxe/if_ether.h>
                     46: #include "b44.h"
                     47: 
                     48: 
                     49: static inline int ring_next(int index)
                     50: {
                     51:        /* B44_RING_SIZE is a power of 2 :) */
                     52:        return (index + 1) & (B44_RING_SIZE - 1);
                     53: }
                     54: 
                     55: 
                     56: /* Memory-mapped I/O wrappers */
                     57: 
                     58: static inline u32 br32(const struct b44_private *bp, u32 reg)
                     59: {
                     60:        return readl(bp->regs + reg);
                     61: }
                     62: 
                     63: 
                     64: static inline void bw32(const struct b44_private *bp, u32 reg, u32 val)
                     65: {
                     66:        writel(val, bp->regs + reg);
                     67: }
                     68: 
                     69: 
                     70: static inline void bflush(const struct b44_private *bp, u32 reg, u32 timeout)
                     71: {
                     72:        readl(bp->regs + reg);
                     73:        udelay(timeout);
                     74: }
                     75: 
                     76: 
                     77: #define VIRT_TO_B44(addr)      ( virt_to_bus(addr) + SB_PCI_DMA )
                     78: 
                     79: 
                     80: /**
                     81:  * Return non-zero if the installed RAM is within
                     82:  * the limit given and zero if it is outside.
                     83:  * Hopefully will be removed soon.
                     84:  */
                     85: int phys_ram_within_limit(u64 limit)
                     86: {
                     87:        struct memory_map memmap;
                     88:        struct memory_region *highest = NULL;
                     89:        get_memmap(&memmap);
                     90: 
                     91:        if (memmap.count == 0)
                     92:                return 0;
                     93:        highest = &memmap.regions[memmap.count - 1];
                     94: 
                     95:        return (highest->end < limit);
                     96: }
                     97: 
                     98: 
                     99: /**
                    100:  * Ring cells waiting to be processed are between 'tx_cur' and 'pending'
                    101:  * indexes in the ring.
                    102:  */
                    103: static u32 pending_tx_index(struct b44_private *bp)
                    104: {
                    105:        u32 pending = br32(bp, B44_DMATX_STAT);
                    106:        pending &= DMATX_STAT_CDMASK;
                    107: 
                    108:        pending /= sizeof(struct dma_desc);
                    109:        return pending & (B44_RING_SIZE - 1);
                    110: }
                    111: 
                    112: 
                    113: /**
                    114:  * Ring cells waiting to be processed are between 'rx_cur' and 'pending'
                    115:  * indexes in the ring.
                    116:  */
                    117: static u32 pending_rx_index(struct b44_private *bp)
                    118: {
                    119:        u32 pending = br32(bp, B44_DMARX_STAT);
                    120:        pending &= DMARX_STAT_CDMASK;
                    121: 
                    122:        pending /= sizeof(struct dma_desc);
                    123:        return pending & (B44_RING_SIZE - 1);
                    124: }
                    125: 
                    126: 
                    127: /**
                    128:  * Wait until the given bit is set/cleared.
                    129:  */
                    130: static int b44_wait_bit(struct b44_private *bp, unsigned long reg, u32 bit,
                    131:                                    unsigned long timeout, const int clear)
                    132: {
                    133:        unsigned long i;
                    134: 
                    135:        for (i = 0; i < timeout; i++) {
                    136:                u32 val = br32(bp, reg);
                    137: 
                    138:                if (clear && !(val & bit))
                    139:                        break;
                    140: 
                    141:                if (!clear && (val & bit))
                    142:                        break;
                    143: 
                    144:                udelay(10);
                    145:        }
                    146:        if (i == timeout) {
                    147:                return -ENODEV;
                    148:        }
                    149:        return 0;
                    150: }
                    151: 
                    152: 
                    153: /*
                    154:  * Sonics Silicon Backplane support. SSB is a mini-bus interconnecting
                    155:  * so-called IP Cores. One of those cores implements the Fast Ethernet
                    156:  * functionality and another one the PCI engine.
                    157:  *
                    158:  * You need to switch to the core you want to talk to before actually
                    159:  * sending commands.
                    160:  *
                    161:  * See: http://bcm-v4.sipsolutions.net/Backplane for (reverse-engineered)
                    162:  * specs.
                    163:  */
                    164: 
                    165: static inline u32 ssb_get_core_rev(struct b44_private *bp)
                    166: {
                    167:        return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
                    168: }
                    169: 
                    170: 
                    171: static inline int ssb_is_core_up(struct b44_private *bp)
                    172: {
                    173:        return ((br32(bp, B44_SBTMSLOW) & (SSB_CORE_DOWN | SBTMSLOW_CLOCK))
                    174:                                                        == SBTMSLOW_CLOCK);
                    175: }
                    176: 
                    177: 
                    178: static u32 ssb_pci_setup(struct b44_private *bp, u32 cores)
                    179: {
                    180:        u32 bar_orig, pci_rev, val;
                    181: 
                    182:        pci_read_config_dword(bp->pci, SSB_BAR0_WIN, &bar_orig);
                    183:        pci_write_config_dword(bp->pci, SSB_BAR0_WIN,
                    184:                               BCM4400_PCI_CORE_ADDR);
                    185:        pci_rev = ssb_get_core_rev(bp);
                    186: 
                    187:        val = br32(bp, B44_SBINTVEC);
                    188:        val |= cores;
                    189:        bw32(bp, B44_SBINTVEC, val);
                    190: 
                    191:        val = br32(bp, SSB_PCI_TRANS_2);
                    192:        val |= SSB_PCI_PREF | SSB_PCI_BURST;
                    193:        bw32(bp, SSB_PCI_TRANS_2, val);
                    194: 
                    195:        pci_write_config_dword(bp->pci, SSB_BAR0_WIN, bar_orig);
                    196: 
                    197:        return pci_rev;
                    198: }
                    199: 
                    200: 
                    201: static void ssb_core_disable(struct b44_private *bp)
                    202: {
                    203:        if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
                    204:                return;
                    205: 
                    206:        bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
                    207:        b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
                    208:        b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);
                    209: 
                    210:        bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
                    211:                                                SSB_CORE_DOWN));
                    212:        bflush(bp, B44_SBTMSLOW, 1);
                    213: 
                    214:        bw32(bp, B44_SBTMSLOW, SSB_CORE_DOWN);
                    215:        bflush(bp, B44_SBTMSLOW, 1);
                    216: }
                    217: 
                    218: 
                    219: static void ssb_core_reset(struct b44_private *bp)
                    220: {
                    221:        u32 val;
                    222:        const u32 mask = (SBTMSLOW_CLOCK | SBTMSLOW_FGC | SBTMSLOW_RESET);
                    223: 
                    224:        ssb_core_disable(bp);
                    225: 
                    226:        bw32(bp, B44_SBTMSLOW, mask);
                    227:        bflush(bp, B44_SBTMSLOW, 1);
                    228: 
                    229:        /* Clear SERR if set, this is a hw bug workaround.  */
                    230:        if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
                    231:                bw32(bp, B44_SBTMSHIGH, 0);
                    232: 
                    233:        val = br32(bp, B44_SBIMSTATE);
                    234:        if (val & (SBIMSTATE_BAD)) {
                    235:                bw32(bp, B44_SBIMSTATE, val & ~SBIMSTATE_BAD);
                    236:        }
                    237: 
                    238:        bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
                    239:        bflush(bp, B44_SBTMSLOW, 1);
                    240: 
                    241:        bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
                    242:        bflush(bp, B44_SBTMSLOW, 1);
                    243: }
                    244: 
                    245: 
                    246: /*
                    247:  * Driver helper functions
                    248:  */
                    249: 
                    250: /*
                    251:  * Chip reset provides power to the b44 MAC & PCI cores, which
                    252:  * is necessary for MAC register access. We only do a partial
                    253:  * reset in case of transmit/receive errors (ISTAT_ERRORS) to
                    254:  * avoid the chip being hung for an unnecessary long time in
                    255:  * this case.
                    256:  *
                    257:  * Called-by: b44_close, b44_halt, b44_inithw(b44_open), b44_probe
                    258:  */
                    259: static void b44_chip_reset(struct b44_private *bp, int reset_kind)
                    260: {
                    261:        if (ssb_is_core_up(bp)) {
                    262:                bw32(bp, B44_RCV_LAZY, 0);
                    263: 
                    264:                bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
                    265: 
                    266:                b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
                    267: 
                    268:                bw32(bp, B44_DMATX_CTRL, 0);
                    269: 
                    270:                bp->tx_dirty = bp->tx_cur = 0;
                    271: 
                    272:                if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK)
                    273:                        b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
                    274:                                                                  100, 0);
                    275: 
                    276:                bw32(bp, B44_DMARX_CTRL, 0);
                    277: 
                    278:                bp->rx_cur = 0;
                    279:        } else {
                    280:                ssb_pci_setup(bp, SBINTVEC_ENET0);
                    281:        }
                    282: 
                    283:        ssb_core_reset(bp);
                    284: 
                    285:        /* Don't enable PHY if we are only doing a partial reset. */
                    286:        if (reset_kind == B44_CHIP_RESET_PARTIAL)
                    287:                return;
                    288: 
                    289:        /* Make PHY accessible. */
                    290:        bw32(bp, B44_MDIO_CTRL,
                    291:             (MDIO_CTRL_PREAMBLE | (0x0d & MDIO_CTRL_MAXF_MASK)));
                    292:        bflush(bp, B44_MDIO_CTRL, 1);
                    293: 
                    294:        /* Enable internal or external PHY */
                    295:        if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
                    296:                bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
                    297:                bflush(bp, B44_ENET_CTRL, 1);
                    298:        } else {
                    299:                u32 val = br32(bp, B44_DEVCTRL);
                    300:                if (val & DEVCTRL_EPR) {
                    301:                        bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
                    302:                        bflush(bp, B44_DEVCTRL, 100);
                    303:                }
                    304:        }
                    305: }
                    306: 
                    307: 
                    308: /**
                    309:  * called by b44_poll in the error path
                    310:  */
                    311: static void b44_halt(struct b44_private *bp)
                    312: {
                    313:        /* disable ints */
                    314:        bw32(bp, B44_IMASK, 0);
                    315:        bflush(bp, B44_IMASK, 1);
                    316: 
                    317:        DBG("b44: powering down PHY\n");
                    318:        bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
                    319: 
                    320:        /*
                    321:         * Now reset the chip, but without enabling
                    322:         * the MAC&PHY part of it.
                    323:         * This has to be done _after_ we shut down the PHY
                    324:         */
                    325:        b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
                    326: }
                    327: 
                    328: 
                    329: 
                    330: /*
                    331:  * Called at device open time to get the chip ready for
                    332:  * packet processing.
                    333:  *
                    334:  * Called-by: b44_open
                    335:  */
                    336: static void b44_init_hw(struct b44_private *bp, int reset_kind)
                    337: {
                    338:        u32 val;
                    339: #define CTRL_MASK (DMARX_CTRL_ENABLE | (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))
                    340: 
                    341:        b44_chip_reset(bp, B44_CHIP_RESET_FULL);
                    342:        if (reset_kind == B44_FULL_RESET) {
                    343:                b44_phy_reset(bp);
                    344:        }
                    345: 
                    346:        /* Enable CRC32, set proper LED modes and power on PHY */
                    347:        bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
                    348:        bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
                    349: 
                    350:        /* This sets the MAC address too.  */
                    351:        b44_set_rx_mode(bp->netdev);
                    352: 
                    353:        /* MTU + eth header + possible VLAN tag + struct rx_header */
                    354:        bw32(bp, B44_RXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
                    355:        bw32(bp, B44_TXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
                    356: 
                    357:        bw32(bp, B44_TX_HIWMARK, TX_HIWMARK_DEFLT);
                    358:        if (reset_kind == B44_PARTIAL_RESET) {
                    359:                bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
                    360:        } else {
                    361:                bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
                    362:                bw32(bp, B44_DMATX_ADDR, VIRT_TO_B44(bp->tx));
                    363: 
                    364:                bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
                    365:                bw32(bp, B44_DMARX_ADDR, VIRT_TO_B44(bp->rx));
                    366:                bw32(bp, B44_DMARX_PTR, B44_RX_RING_LEN_BYTES);
                    367: 
                    368:                bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
                    369:        }
                    370: 
                    371:        val = br32(bp, B44_ENET_CTRL);
                    372:        bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
                    373: #undef CTRL_MASK
                    374: }
                    375: 
                    376: 
                    377: /***  Management of ring descriptors  ***/
                    378: 
                    379: 
                    380: static void b44_populate_rx_descriptor(struct b44_private *bp, u32 idx)
                    381: {
                    382:        struct rx_header *rh;
                    383:        u32 ctrl, addr;
                    384: 
                    385:        rh = bp->rx_iobuf[idx]->data;
                    386:        rh->len = 0;
                    387:        rh->flags = 0;
                    388:        ctrl = DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET);
                    389:        if (idx == B44_RING_LAST) {
                    390:                ctrl |= DESC_CTRL_EOT;
                    391:        }
                    392:        addr = VIRT_TO_B44(bp->rx_iobuf[idx]->data);
                    393: 
                    394:        bp->rx[idx].ctrl = cpu_to_le32(ctrl);
                    395:        bp->rx[idx].addr = cpu_to_le32(addr);
                    396:        bw32(bp, B44_DMARX_PTR, idx * sizeof(struct dma_desc));
                    397: }
                    398: 
                    399: 
                    400: /*
                    401:  * Refill RX ring descriptors with buffers. This is needed
                    402:  * because during rx we are passing ownership of descriptor
                    403:  * buffers to the network stack.
                    404:  */
                    405: static void b44_rx_refill(struct b44_private *bp, u32 pending)
                    406: {
                    407:        u32 i;
                    408: 
                    409:        // skip pending
                    410:        for (i = pending + 1; i != bp->rx_cur; i = ring_next(i)) {
                    411:                if (bp->rx_iobuf[i] != NULL)
                    412:                        continue;
                    413: 
                    414:                bp->rx_iobuf[i] = alloc_iob(RX_PKT_BUF_SZ);
                    415:                if (!bp->rx_iobuf[i]) {
                    416:                        DBG("Refill rx ring failed!!\n");
                    417:                        break;
                    418:                }
                    419: 
                    420:                b44_populate_rx_descriptor(bp, i);
                    421:        }
                    422: }
                    423: 
                    424: 
                    425: static void b44_free_rx_ring(struct b44_private *bp)
                    426: {
                    427:        u32 i;
                    428: 
                    429:        if (bp->rx) {
                    430:                for (i = 0; i < B44_RING_SIZE; i++) {
                    431:                        free_iob(bp->rx_iobuf[i]);
                    432:                        bp->rx_iobuf[i] = NULL;
                    433:                }
                    434:                free_dma(bp->rx, B44_RX_RING_LEN_BYTES);
                    435:                bp->rx = NULL;
                    436:        }
                    437: }
                    438: 
                    439: 
                    440: static int b44_init_rx_ring(struct b44_private *bp)
                    441: {
                    442:        b44_free_rx_ring(bp);
                    443: 
                    444:        bp->rx = malloc_dma(B44_RX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
                    445:        if (!bp->rx)
                    446:                return -ENOMEM;
                    447: 
                    448:        memset(bp->rx_iobuf, 0, sizeof(bp->rx_iobuf));
                    449: 
                    450:        bp->rx_iobuf[0] = alloc_iob(RX_PKT_BUF_SZ);
                    451:        b44_populate_rx_descriptor(bp, 0);
                    452:        b44_rx_refill(bp, 0);
                    453: 
                    454:        DBG("Init RX rings: rx=0x%08lx\n", VIRT_TO_B44(bp->rx));
                    455:        return 0;
                    456: }
                    457: 
                    458: 
                    459: static void b44_free_tx_ring(struct b44_private *bp)
                    460: {
                    461:        if (bp->tx) {
                    462:                free_dma(bp->tx, B44_TX_RING_LEN_BYTES);
                    463:                bp->tx = NULL;
                    464:        }
                    465: }
                    466: 
                    467: 
                    468: static int b44_init_tx_ring(struct b44_private *bp)
                    469: {
                    470:        b44_free_tx_ring(bp);
                    471: 
                    472:        bp->tx = malloc_dma(B44_TX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
                    473:        if (!bp->tx)
                    474:                return -ENOMEM;
                    475: 
                    476:        memset(bp->tx, 0, B44_TX_RING_LEN_BYTES);
                    477:        memset(bp->tx_iobuf, 0, sizeof(bp->tx_iobuf));
                    478: 
                    479:        DBG("Init TX rings: tx=0x%08lx\n", VIRT_TO_B44(bp->tx));
                    480:        return 0;
                    481: }
                    482: 
                    483: 
                    484: /*** Interaction with the PHY ***/
                    485: 
                    486: 
                    487: static int b44_phy_read(struct b44_private *bp, int reg, u32 * val)
                    488: {
                    489:        int err;
                    490: 
                    491:        u32 arg1 = (MDIO_OP_READ << MDIO_DATA_OP_SHIFT);
                    492:        u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
                    493:        u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
                    494:        u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
                    495:        u32 argv = arg1 | arg2 | arg3 | arg4;
                    496: 
                    497:        bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
                    498:        bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
                    499:        err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
                    500:        *val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
                    501: 
                    502:        return err;
                    503: }
                    504: 
                    505: 
                    506: static int b44_phy_write(struct b44_private *bp, int reg, u32 val)
                    507: {
                    508:        u32 arg1 = (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT);
                    509:        u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
                    510:        u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
                    511:        u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
                    512:        u32 arg5 = (val & MDIO_DATA_DATA);
                    513:        u32 argv = arg1 | arg2 | arg3 | arg4 | arg5;
                    514: 
                    515: 
                    516:        bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
                    517:        bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
                    518:        return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
                    519: }
                    520: 
                    521: 
                    522: static int b44_phy_reset(struct b44_private *bp)
                    523: {
                    524:        u32 val;
                    525:        int err;
                    526: 
                    527:        err = b44_phy_write(bp, MII_BMCR, BMCR_RESET);
                    528:        if (err)
                    529:                return err;
                    530: 
                    531:        udelay(100);
                    532:        err = b44_phy_read(bp, MII_BMCR, &val);
                    533:        if (!err) {
                    534:                if (val & BMCR_RESET) {
                    535:                        return -ENODEV;
                    536:                }
                    537:        }
                    538: 
                    539:        return 0;
                    540: }
                    541: 
                    542: 
                    543: /*
                    544:  * The BCM44xx CAM (Content Addressable Memory) stores the MAC
                    545:  * and PHY address.
                    546:  */
                    547: static void b44_cam_write(struct b44_private *bp, unsigned char *data,
                    548:                                                            int index)
                    549: {
                    550:        u32 val;
                    551: 
                    552:        val  = ((u32) data[2]) << 24;
                    553:        val |= ((u32) data[3]) << 16;
                    554:        val |= ((u32) data[4]) << 8;
                    555:        val |= ((u32) data[5]) << 0;
                    556:        bw32(bp, B44_CAM_DATA_LO, val);
                    557: 
                    558: 
                    559:        val = (CAM_DATA_HI_VALID |
                    560:               (((u32) data[0]) << 8) | (((u32) data[1]) << 0));
                    561: 
                    562:        bw32(bp, B44_CAM_DATA_HI, val);
                    563: 
                    564:        val = CAM_CTRL_WRITE | (index << CAM_CTRL_INDEX_SHIFT);
                    565:        bw32(bp, B44_CAM_CTRL, val);
                    566: 
                    567:        b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
                    568: }
                    569: 
                    570: 
                    571: static void b44_set_mac_addr(struct b44_private *bp)
                    572: {
                    573:        u32 val;
                    574:        bw32(bp, B44_CAM_CTRL, 0);
                    575:        b44_cam_write(bp, bp->netdev->ll_addr, 0);
                    576:        val = br32(bp, B44_CAM_CTRL);
                    577:        bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
                    578: }
                    579: 
                    580: 
                    581: /* Read 128-bytes of EEPROM. */
                    582: static void b44_read_eeprom(struct b44_private *bp, u8 * data)
                    583: {
                    584:        long i;
                    585:        u16 *ptr = (u16 *) data;
                    586: 
                    587:        for (i = 0; i < 128; i += 2)
                    588:                ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i));
                    589: }
                    590: 
                    591: 
                    592: static void b44_load_mac_and_phy_addr(struct b44_private *bp)
                    593: {
                    594:        u8 eeprom[128];
                    595: 
                    596:        /* Load MAC address, note byteswapping */
                    597:        b44_read_eeprom(bp, &eeprom[0]);
                    598:        bp->netdev->hw_addr[0] = eeprom[79];
                    599:        bp->netdev->hw_addr[1] = eeprom[78];
                    600:        bp->netdev->hw_addr[2] = eeprom[81];
                    601:        bp->netdev->hw_addr[3] = eeprom[80];
                    602:        bp->netdev->hw_addr[4] = eeprom[83];
                    603:        bp->netdev->hw_addr[5] = eeprom[82];
                    604: 
                    605:        /* Load PHY address */
                    606:        bp->phy_addr = eeprom[90] & 0x1f;
                    607: }
                    608: 
                    609: 
                    610: static void b44_set_rx_mode(struct net_device *netdev)
                    611: {
                    612:        struct b44_private *bp = netdev_priv(netdev);
                    613:        unsigned char zero[6] = { 0, 0, 0, 0, 0, 0 };
                    614:        u32 val;
                    615:        int i;
                    616: 
                    617:        val = br32(bp, B44_RXCONFIG);
                    618:        val &= ~RXCONFIG_PROMISC;
                    619:        val |= RXCONFIG_ALLMULTI;
                    620: 
                    621:        b44_set_mac_addr(bp);
                    622: 
                    623:        for (i = 1; i < 64; i++)
                    624:                b44_cam_write(bp, zero, i);
                    625: 
                    626:        bw32(bp, B44_RXCONFIG, val);
                    627:        val = br32(bp, B44_CAM_CTRL);
                    628:        bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
                    629: }
                    630: 
                    631: 
                    632: /*** Implementation of iPXE driver callbacks ***/
                    633: 
                    634: /**
                    635:  * Probe device
                    636:  *
                    637:  * @v pci      PCI device
                    638:  * @v id       Matching entry in ID table
                    639:  * @ret rc     Return status code
                    640:  */
                    641: static int b44_probe(struct pci_device *pci)
                    642: {
                    643:        struct net_device *netdev;
                    644:        struct b44_private *bp;
                    645:        int rc;
                    646: 
                    647:        /*
                    648:         * Bail out if more than 1GB of physical RAM is installed.
                    649:         * This limitation will be removed later when dma mapping
                    650:         * is merged into mainline.
                    651:         */
                    652:        if (!phys_ram_within_limit(B44_30BIT_DMA_MASK)) {
                    653:                DBG("Sorry, this version of the driver does not\n"
                    654:                    "support systems with more than 1GB of RAM.\n");
                    655:                return -ENOMEM;
                    656:        }
                    657: 
                    658:        /* Set up netdev */
                    659:        netdev = alloc_etherdev(sizeof(*bp));
                    660:        if (!netdev)
                    661:                return -ENOMEM;
                    662: 
                    663:        netdev_init(netdev, &b44_operations);
                    664:        pci_set_drvdata(pci, netdev);
                    665:        netdev->dev = &pci->dev;
                    666: 
                    667:        /* Set up private data */
                    668:        bp = netdev_priv(netdev);
                    669:        memset(bp, 0, sizeof(*bp));
                    670:        bp->netdev = netdev;
                    671:        bp->pci = pci;
                    672: 
                    673:        /* Map device registers */
                    674:        bp->regs = ioremap(pci->membase, B44_REGS_SIZE);
                    675:        if (!bp->regs) {
                    676:                netdev_put(netdev);
                    677:                return -ENOMEM;
                    678:        }
                    679: 
                    680:        /* Enable PCI bus mastering */
                    681:        adjust_pci_device(pci);
                    682: 
                    683:        b44_load_mac_and_phy_addr(bp);
                    684: 
                    685:        rc = register_netdev(netdev);
                    686:        if (rc != 0) {
                    687:                iounmap(bp->regs);
                    688:                netdev_put(netdev);
                    689:                return rc;
                    690:        }
                    691: 
                    692:        /* Link management currently not implemented */
                    693:        netdev_link_up(netdev);
                    694: 
                    695:        b44_chip_reset(bp, B44_CHIP_RESET_FULL);
                    696: 
                    697:        DBG("b44 %s (%04x:%04x) regs=%p MAC=%s\n", pci->id->name,
                    698:            pci->id->vendor, pci->id->device, bp->regs,
                    699:            eth_ntoa(netdev->ll_addr));
                    700: 
                    701:        return 0;
                    702: }
                    703: 
                    704: 
                    705: /**
                    706:  * Remove device
                    707:  *
                    708:  * @v pci      PCI device
                    709:  */
                    710: static void b44_remove(struct pci_device *pci)
                    711: {
                    712:        struct net_device *netdev = pci_get_drvdata(pci);
                    713:        struct b44_private *bp = netdev_priv(netdev);
                    714: 
                    715:        ssb_core_disable(bp);
                    716:        unregister_netdev(netdev);
                    717:        iounmap(bp->regs);
                    718:        netdev_nullify(netdev);
                    719:        netdev_put(netdev);
                    720: }
                    721: 
                    722: 
                    723: /** Enable or disable interrupts
                    724:  *
                    725:  * @v netdev   Network device
                    726:  * @v enable   Interrupts should be enabled
                    727:  */
                    728: static void b44_irq(struct net_device *netdev, int enable)
                    729: {
                    730:        struct b44_private *bp = netdev_priv(netdev);
                    731: 
                    732:        /* Interrupt mask specifies which events generate interrupts */
                    733:        bw32(bp, B44_IMASK, enable ? IMASK_DEF : IMASK_DISABLE);
                    734: }
                    735: 
                    736: 
                    737: /** Open network device
                    738:  *
                    739:  * @v netdev   Network device
                    740:  * @ret rc     Return status code
                    741:  */
                    742: static int b44_open(struct net_device *netdev)
                    743: {
                    744:        struct b44_private *bp = netdev_priv(netdev);
                    745:        int rc;
                    746: 
                    747:        rc = b44_init_tx_ring(bp);
                    748:        if (rc != 0)
                    749:                return rc;
                    750: 
                    751:        rc = b44_init_rx_ring(bp);
                    752:        if (rc != 0)
                    753:                return rc;
                    754: 
                    755:        b44_init_hw(bp, B44_FULL_RESET);
                    756: 
                    757:        /* Disable interrupts */
                    758:        b44_irq(netdev, 0);
                    759: 
                    760:        return 0;
                    761: }
                    762: 
                    763: 
                    764: /** Close network device
                    765:  *
                    766:  * @v netdev   Network device
                    767:  */
                    768: static void b44_close(struct net_device *netdev)
                    769: {
                    770:        struct b44_private *bp = netdev_priv(netdev);
                    771: 
                    772:        b44_chip_reset(bp, B44_FULL_RESET);
                    773:        b44_free_tx_ring(bp);
                    774:        b44_free_rx_ring(bp);
                    775: }
                    776: 
                    777: 
                    778: /** Transmit packet
                    779:  *
                    780:  * @v netdev   Network device
                    781:  * @v iobuf    I/O buffer
                    782:  * @ret rc     Return status code
                    783:  */
                    784: static int b44_transmit(struct net_device *netdev, struct io_buffer *iobuf)
                    785: {
                    786:        struct b44_private *bp = netdev_priv(netdev);
                    787:        u32 cur = bp->tx_cur;
                    788:        u32 ctrl;
                    789: 
                    790:        /* Check for TX ring overflow */
                    791:        if (bp->tx[cur].ctrl) {
                    792:                DBG("tx overflow\n");
                    793:                return -ENOBUFS;
                    794:        }
                    795: 
                    796:        /* Will call netdev_tx_complete() on the iobuf later */
                    797:        bp->tx_iobuf[cur] = iobuf;
                    798: 
                    799:        /* Set up TX descriptor */
                    800:        ctrl = (iob_len(iobuf) & DESC_CTRL_LEN) |
                    801:            DESC_CTRL_IOC | DESC_CTRL_SOF | DESC_CTRL_EOF;
                    802: 
                    803:        if (cur == B44_RING_LAST)
                    804:                ctrl |= DESC_CTRL_EOT;
                    805: 
                    806:        bp->tx[cur].ctrl = cpu_to_le32(ctrl);
                    807:        bp->tx[cur].addr = cpu_to_le32(VIRT_TO_B44(iobuf->data));
                    808: 
                    809:        /* Update next available descriptor index */
                    810:        cur = ring_next(cur);
                    811:        bp->tx_cur = cur;
                    812:        wmb();
                    813: 
                    814:        /* Tell card that a new TX descriptor is ready */
                    815:        bw32(bp, B44_DMATX_PTR, cur * sizeof(struct dma_desc));
                    816:        return 0;
                    817: }
                    818: 
                    819: 
                    820: /** Recycles sent TX descriptors and notifies network stack
                    821:  *
                    822:  * @v bp Driver state
                    823:  */
                    824: static void b44_tx_complete(struct b44_private *bp)
                    825: {
                    826:        u32 cur, i;
                    827: 
                    828:        cur = pending_tx_index(bp);
                    829: 
                    830:        for (i = bp->tx_dirty; i != cur; i = ring_next(i)) {
                    831:                /* Free finished frame */
                    832:                netdev_tx_complete(bp->netdev, bp->tx_iobuf[i]);
                    833:                bp->tx_iobuf[i] = NULL;
                    834: 
                    835:                /* Clear TX descriptor */
                    836:                bp->tx[i].ctrl = 0;
                    837:                bp->tx[i].addr = 0;
                    838:        }
                    839:        bp->tx_dirty = cur;
                    840: }
                    841: 
                    842: 
                    843: static void b44_process_rx_packets(struct b44_private *bp)
                    844: {
                    845:        struct io_buffer *iob;  /* received data */
                    846:        struct rx_header *rh;
                    847:        u32 pending, i;
                    848:        u16 len;
                    849: 
                    850:        pending = pending_rx_index(bp);
                    851: 
                    852:        for (i = bp->rx_cur; i != pending; i = ring_next(i)) {
                    853:                iob = bp->rx_iobuf[i];
                    854:                if (iob == NULL)
                    855:                        break;
                    856: 
                    857:                rh = iob->data;
                    858:                len = le16_to_cpu(rh->len);
                    859: 
                    860:                /*
                    861:                 * Guard against incompletely written RX descriptors.
                    862:                 * Without this, things can get really slow!
                    863:                 */
                    864:                if (len == 0)
                    865:                        break;
                    866: 
                    867:                /* Discard CRC that is generated by the card */
                    868:                len -= 4;
                    869: 
                    870:                /* Check for invalid packets and errors */
                    871:                if (len > RX_PKT_BUF_SZ - RX_PKT_OFFSET ||
                    872:                    (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
                    873:                        DBG("rx error len=%d flags=%04x\n", len,
                    874:                                         cpu_to_le16(rh->flags));
                    875:                        rh->len = 0;
                    876:                        rh->flags = 0;
                    877:                        netdev_rx_err(bp->netdev, iob, -EINVAL);
                    878:                        continue;
                    879:                }
                    880: 
                    881:                /* Clear RX descriptor */
                    882:                rh->len = 0;
                    883:                rh->flags = 0;
                    884:                bp->rx_iobuf[i] = NULL;
                    885: 
                    886:                /* Hand off the IO buffer to the network stack */
                    887:                iob_reserve(iob, RX_PKT_OFFSET);
                    888:                iob_put(iob, len);
                    889:                netdev_rx(bp->netdev, iob);
                    890:        }
                    891:        bp->rx_cur = i;
                    892:        b44_rx_refill(bp, pending_rx_index(bp));
                    893: }
                    894: 
                    895: 
                    896: /** Poll for completed and received packets
                    897:  *
                    898:  * @v netdev   Network device
                    899:  */
                    900: static void b44_poll(struct net_device *netdev)
                    901: {
                    902:        struct b44_private *bp = netdev_priv(netdev);
                    903:        u32 istat;
                    904: 
                    905:        /* Interrupt status */
                    906:        istat = br32(bp, B44_ISTAT);
                    907:        istat &= IMASK_DEF;     /* only the events we care about */
                    908: 
                    909:        if (!istat)
                    910:                return;
                    911:        if (istat & ISTAT_TX)
                    912:                b44_tx_complete(bp);
                    913:        if (istat & ISTAT_RX)
                    914:                b44_process_rx_packets(bp);
                    915:        if (istat & ISTAT_ERRORS) {
                    916:                DBG("b44 error istat=0x%08x\n", istat);
                    917: 
                    918:                /* Reset B44 core partially to avoid long waits */
                    919:                b44_irq(bp->netdev, 0);
                    920:                b44_halt(bp);
                    921:                b44_init_tx_ring(bp);
                    922:                b44_init_rx_ring(bp);
                    923:                b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
                    924:        }
                    925: 
                    926:        /* Acknowledge interrupt */
                    927:        bw32(bp, B44_ISTAT, 0);
                    928:        bflush(bp, B44_ISTAT, 1);
                    929: }
                    930: 
                    931: 
                    932: static struct net_device_operations b44_operations = {
                    933:        .open = b44_open,
                    934:        .close = b44_close,
                    935:        .transmit = b44_transmit,
                    936:        .poll = b44_poll,
                    937:        .irq = b44_irq,
                    938: };
                    939: 
                    940: 
                    941: static struct pci_device_id b44_nics[] = {
                    942:        PCI_ROM(0x14e4, 0x4401, "BCM4401", "BCM4401", 0),
                    943:        PCI_ROM(0x14e4, 0x170c, "BCM4401-B0", "BCM4401-B0", 0),
                    944:        PCI_ROM(0x14e4, 0x4402, "BCM4401-B1", "BCM4401-B1", 0),
                    945: };
                    946: 
                    947: 
                    948: struct pci_driver b44_driver __pci_driver = {
                    949:        .ids = b44_nics,
                    950:        .id_count = sizeof b44_nics / sizeof b44_nics[0],
                    951:        .probe = b44_probe,
                    952:        .remove = b44_remove,
                    953: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.