00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 FILE_LICENCE ( GPL2_OR_LATER );
00032
00033 #include <errno.h>
00034 #include <assert.h>
00035 #include <stdio.h>
00036 #include <unistd.h>
00037 #include <byteswap.h>
00038 #include <gpxe/io.h>
00039 #include <mii.h>
00040 #include <gpxe/iobuf.h>
00041 #include <gpxe/malloc.h>
00042 #include <gpxe/pci.h>
00043 #include <gpxe/netdevice.h>
00044 #include <gpxe/ethernet.h>
00045 #include <gpxe/if_ether.h>
00046 #include <gpxe/memmap.h>
00047 #include "b44.h"
00048
00049
00050 static inline int ring_next(int index)
00051 {
00052
00053 return (index + 1) & (B44_RING_SIZE - 1);
00054 }
00055
00056
00057
00058
00059 static inline u32 br32(const struct b44_private *bp, u32 reg)
00060 {
00061 return readl(bp->regs + reg);
00062 }
00063
00064
00065 static inline void bw32(const struct b44_private *bp, u32 reg, u32 val)
00066 {
00067 writel(val, bp->regs + reg);
00068 }
00069
00070
00071 static inline void bflush(const struct b44_private *bp, u32 reg, u32 timeout)
00072 {
00073 readl(bp->regs + reg);
00074 udelay(timeout);
00075 }
00076
00077
00078 #define VIRT_TO_B44(addr) ( virt_to_bus(addr) + SB_PCI_DMA )
00079
00080
00081
00082
00083
00084
00085
00086 int phys_ram_within_limit(u64 limit)
00087 {
00088 struct memory_map memmap;
00089 struct memory_region *highest = NULL;
00090 get_memmap(&memmap);
00091
00092 highest = &memmap.regions[memmap.count - 1];
00093
00094 return (highest->end < limit);
00095 }
00096
00097
00098
00099
00100
00101
00102 static u32 pending_tx_index(struct b44_private *bp)
00103 {
00104 u32 pending = br32(bp, B44_DMATX_STAT);
00105 pending &= DMATX_STAT_CDMASK;
00106
00107 pending /= sizeof(struct dma_desc);
00108 return pending & (B44_RING_SIZE - 1);
00109 }
00110
00111
00112
00113
00114
00115
00116 static u32 pending_rx_index(struct b44_private *bp)
00117 {
00118 u32 pending = br32(bp, B44_DMARX_STAT);
00119 pending &= DMARX_STAT_CDMASK;
00120
00121 pending /= sizeof(struct dma_desc);
00122 return pending & (B44_RING_SIZE - 1);
00123 }
00124
00125
00126
00127
00128
00129 static int b44_wait_bit(struct b44_private *bp, unsigned long reg, u32 bit,
00130 unsigned long timeout, const int clear)
00131 {
00132 unsigned long i;
00133
00134 for (i = 0; i < timeout; i++) {
00135 u32 val = br32(bp, reg);
00136
00137 if (clear && !(val & bit))
00138 break;
00139
00140 if (!clear && (val & bit))
00141 break;
00142
00143 udelay(10);
00144 }
00145 if (i == timeout) {
00146 return -ENODEV;
00147 }
00148 return 0;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 static inline u32 ssb_get_core_rev(struct b44_private *bp)
00165 {
00166 return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
00167 }
00168
00169
00170 static inline int ssb_is_core_up(struct b44_private *bp)
00171 {
00172 return ((br32(bp, B44_SBTMSLOW) & (SSB_CORE_DOWN | SBTMSLOW_CLOCK))
00173 == SBTMSLOW_CLOCK);
00174 }
00175
00176
00177 static u32 ssb_pci_setup(struct b44_private *bp, u32 cores)
00178 {
00179 u32 bar_orig, pci_rev, val;
00180
00181 pci_read_config_dword(bp->pci, SSB_BAR0_WIN, &bar_orig);
00182 pci_write_config_dword(bp->pci, SSB_BAR0_WIN,
00183 BCM4400_PCI_CORE_ADDR);
00184 pci_rev = ssb_get_core_rev(bp);
00185
00186 val = br32(bp, B44_SBINTVEC);
00187 val |= cores;
00188 bw32(bp, B44_SBINTVEC, val);
00189
00190 val = br32(bp, SSB_PCI_TRANS_2);
00191 val |= SSB_PCI_PREF | SSB_PCI_BURST;
00192 bw32(bp, SSB_PCI_TRANS_2, val);
00193
00194 pci_write_config_dword(bp->pci, SSB_BAR0_WIN, bar_orig);
00195
00196 return pci_rev;
00197 }
00198
00199
00200 static void ssb_core_disable(struct b44_private *bp)
00201 {
00202 if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
00203 return;
00204
00205 bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
00206 b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
00207 b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);
00208
00209 bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
00210 SSB_CORE_DOWN));
00211 bflush(bp, B44_SBTMSLOW, 1);
00212
00213 bw32(bp, B44_SBTMSLOW, SSB_CORE_DOWN);
00214 bflush(bp, B44_SBTMSLOW, 1);
00215 }
00216
00217
00218 static void ssb_core_reset(struct b44_private *bp)
00219 {
00220 u32 val;
00221 const u32 mask = (SBTMSLOW_CLOCK | SBTMSLOW_FGC | SBTMSLOW_RESET);
00222
00223 ssb_core_disable(bp);
00224
00225 bw32(bp, B44_SBTMSLOW, mask);
00226 bflush(bp, B44_SBTMSLOW, 1);
00227
00228
00229 if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
00230 bw32(bp, B44_SBTMSHIGH, 0);
00231
00232 val = br32(bp, B44_SBIMSTATE);
00233 if (val & (SBIMSTATE_BAD)) {
00234 bw32(bp, B44_SBIMSTATE, val & ~SBIMSTATE_BAD);
00235 }
00236
00237 bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
00238 bflush(bp, B44_SBTMSLOW, 1);
00239
00240 bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
00241 bflush(bp, B44_SBTMSLOW, 1);
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 static void b44_chip_reset(struct b44_private *bp, int reset_kind)
00259 {
00260 if (ssb_is_core_up(bp)) {
00261 bw32(bp, B44_RCV_LAZY, 0);
00262
00263 bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
00264
00265 b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
00266
00267 bw32(bp, B44_DMATX_CTRL, 0);
00268
00269 bp->tx_dirty = bp->tx_cur = 0;
00270
00271 if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK)
00272 b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
00273 100, 0);
00274
00275 bw32(bp, B44_DMARX_CTRL, 0);
00276
00277 bp->rx_cur = 0;
00278 } else {
00279 ssb_pci_setup(bp, SBINTVEC_ENET0);
00280 }
00281
00282 ssb_core_reset(bp);
00283
00284
00285 if (reset_kind == B44_CHIP_RESET_PARTIAL)
00286 return;
00287
00288
00289 bw32(bp, B44_MDIO_CTRL,
00290 (MDIO_CTRL_PREAMBLE | (0x0d & MDIO_CTRL_MAXF_MASK)));
00291 bflush(bp, B44_MDIO_CTRL, 1);
00292
00293
00294 if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
00295 bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
00296 bflush(bp, B44_ENET_CTRL, 1);
00297 } else {
00298 u32 val = br32(bp, B44_DEVCTRL);
00299 if (val & DEVCTRL_EPR) {
00300 bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
00301 bflush(bp, B44_DEVCTRL, 100);
00302 }
00303 }
00304 }
00305
00306
00307
00308
00309
00310 static void b44_halt(struct b44_private *bp)
00311 {
00312
00313 bw32(bp, B44_IMASK, 0);
00314 bflush(bp, B44_IMASK, 1);
00315
00316 DBG("b44: powering down PHY\n");
00317 bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN);
00318
00319
00320
00321
00322
00323
00324 b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 static void b44_init_hw(struct b44_private *bp, int reset_kind)
00336 {
00337 u32 val;
00338 #define CTRL_MASK (DMARX_CTRL_ENABLE | (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))
00339
00340 b44_chip_reset(bp, B44_CHIP_RESET_FULL);
00341 if (reset_kind == B44_FULL_RESET) {
00342 b44_phy_reset(bp);
00343 }
00344
00345
00346 bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
00347 bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
00348
00349
00350 b44_set_rx_mode(bp->netdev);
00351
00352
00353 bw32(bp, B44_RXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
00354 bw32(bp, B44_TXMAXLEN, B44_MAX_MTU + ETH_HLEN + 8 + RX_HEADER_LEN);
00355
00356 bw32(bp, B44_TX_HIWMARK, TX_HIWMARK_DEFLT);
00357 if (reset_kind == B44_PARTIAL_RESET) {
00358 bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
00359 } else {
00360 bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
00361 bw32(bp, B44_DMATX_ADDR, VIRT_TO_B44(bp->tx));
00362
00363 bw32(bp, B44_DMARX_CTRL, CTRL_MASK);
00364 bw32(bp, B44_DMARX_ADDR, VIRT_TO_B44(bp->rx));
00365 bw32(bp, B44_DMARX_PTR, B44_RX_RING_LEN_BYTES);
00366
00367 bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
00368 }
00369
00370 val = br32(bp, B44_ENET_CTRL);
00371 bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
00372 #undef CTRL_MASK
00373 }
00374
00375
00376
00377
00378
00379 static void b44_populate_rx_descriptor(struct b44_private *bp, u32 idx)
00380 {
00381 struct rx_header *rh;
00382 u32 ctrl, addr;
00383
00384 rh = bp->rx_iobuf[idx]->data;
00385 rh->len = 0;
00386 rh->flags = 0;
00387 ctrl = DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET);
00388 if (idx == B44_RING_LAST) {
00389 ctrl |= DESC_CTRL_EOT;
00390 }
00391 addr = VIRT_TO_B44(bp->rx_iobuf[idx]->data);
00392
00393 bp->rx[idx].ctrl = cpu_to_le32(ctrl);
00394 bp->rx[idx].addr = cpu_to_le32(addr);
00395 bw32(bp, B44_DMARX_PTR, idx * sizeof(struct dma_desc));
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 static void b44_rx_refill(struct b44_private *bp, u32 pending)
00405 {
00406 u32 i;
00407
00408
00409 for (i = pending + 1; i != bp->rx_cur; i = ring_next(i)) {
00410 if (bp->rx_iobuf[i] != NULL)
00411 continue;
00412
00413 bp->rx_iobuf[i] = alloc_iob(RX_PKT_BUF_SZ);
00414 if (!bp->rx_iobuf[i]) {
00415 DBG("Refill rx ring failed!!\n");
00416 break;
00417 }
00418
00419 b44_populate_rx_descriptor(bp, i);
00420 }
00421 }
00422
00423
00424 static void b44_free_rx_ring(struct b44_private *bp)
00425 {
00426 u32 i;
00427
00428 if (bp->rx) {
00429 for (i = 0; i < B44_RING_SIZE; i++) {
00430 free_iob(bp->rx_iobuf[i]);
00431 bp->rx_iobuf[i] = NULL;
00432 }
00433 free_dma(bp->rx, B44_RX_RING_LEN_BYTES);
00434 bp->rx = NULL;
00435 }
00436 }
00437
00438
00439 static int b44_init_rx_ring(struct b44_private *bp)
00440 {
00441 b44_free_rx_ring(bp);
00442
00443 bp->rx = malloc_dma(B44_RX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
00444 if (!bp->rx)
00445 return -ENOMEM;
00446
00447 memset(bp->rx_iobuf, 0, sizeof(bp->rx_iobuf));
00448
00449 bp->rx_iobuf[0] = alloc_iob(RX_PKT_BUF_SZ);
00450 b44_populate_rx_descriptor(bp, 0);
00451 b44_rx_refill(bp, 0);
00452
00453 DBG("Init RX rings: rx=0x%08lx\n", VIRT_TO_B44(bp->rx));
00454 return 0;
00455 }
00456
00457
00458 static void b44_free_tx_ring(struct b44_private *bp)
00459 {
00460 if (bp->tx) {
00461 free_dma(bp->tx, B44_TX_RING_LEN_BYTES);
00462 bp->tx = NULL;
00463 }
00464 }
00465
00466
00467 static int b44_init_tx_ring(struct b44_private *bp)
00468 {
00469 b44_free_tx_ring(bp);
00470
00471 bp->tx = malloc_dma(B44_TX_RING_LEN_BYTES, B44_DMA_ALIGNMENT);
00472 if (!bp->tx)
00473 return -ENOMEM;
00474
00475 memset(bp->tx, 0, B44_TX_RING_LEN_BYTES);
00476 memset(bp->tx_iobuf, 0, sizeof(bp->tx_iobuf));
00477
00478 DBG("Init TX rings: tx=0x%08lx\n", VIRT_TO_B44(bp->tx));
00479 return 0;
00480 }
00481
00482
00483
00484
00485
00486 static int b44_phy_read(struct b44_private *bp, int reg, u32 * val)
00487 {
00488 int err;
00489
00490 u32 arg1 = (MDIO_OP_READ << MDIO_DATA_OP_SHIFT);
00491 u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
00492 u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
00493 u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
00494 u32 argv = arg1 | arg2 | arg3 | arg4;
00495
00496 bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
00497 bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
00498 err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
00499 *val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
00500
00501 return err;
00502 }
00503
00504
00505 static int b44_phy_write(struct b44_private *bp, int reg, u32 val)
00506 {
00507 u32 arg1 = (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT);
00508 u32 arg2 = (bp->phy_addr << MDIO_DATA_PMD_SHIFT);
00509 u32 arg3 = (reg << MDIO_DATA_RA_SHIFT);
00510 u32 arg4 = (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT);
00511 u32 arg5 = (val & MDIO_DATA_DATA);
00512 u32 argv = arg1 | arg2 | arg3 | arg4 | arg5;
00513
00514
00515 bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
00516 bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | argv));
00517 return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
00518 }
00519
00520
00521 static int b44_phy_reset(struct b44_private *bp)
00522 {
00523 u32 val;
00524 int err;
00525
00526 err = b44_phy_write(bp, MII_BMCR, BMCR_RESET);
00527 if (err)
00528 return err;
00529
00530 udelay(100);
00531 err = b44_phy_read(bp, MII_BMCR, &val);
00532 if (!err) {
00533 if (val & BMCR_RESET) {
00534 return -ENODEV;
00535 }
00536 }
00537
00538 return 0;
00539 }
00540
00541
00542
00543
00544
00545
00546 static void b44_cam_write(struct b44_private *bp, unsigned char *data,
00547 int index)
00548 {
00549 u32 val;
00550
00551 val = ((u32) data[2]) << 24;
00552 val |= ((u32) data[3]) << 16;
00553 val |= ((u32) data[4]) << 8;
00554 val |= ((u32) data[5]) << 0;
00555 bw32(bp, B44_CAM_DATA_LO, val);
00556
00557
00558 val = (CAM_DATA_HI_VALID |
00559 (((u32) data[0]) << 8) | (((u32) data[1]) << 0));
00560
00561 bw32(bp, B44_CAM_DATA_HI, val);
00562
00563 val = CAM_CTRL_WRITE | (index << CAM_CTRL_INDEX_SHIFT);
00564 bw32(bp, B44_CAM_CTRL, val);
00565
00566 b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
00567 }
00568
00569
00570 static void b44_set_mac_addr(struct b44_private *bp)
00571 {
00572 u32 val;
00573 bw32(bp, B44_CAM_CTRL, 0);
00574 b44_cam_write(bp, bp->netdev->ll_addr, 0);
00575 val = br32(bp, B44_CAM_CTRL);
00576 bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
00577 }
00578
00579
00580
00581 static void b44_read_eeprom(struct b44_private *bp, u8 * data)
00582 {
00583 long i;
00584 u16 *ptr = (u16 *) data;
00585
00586 for (i = 0; i < 128; i += 2)
00587 ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i));
00588 }
00589
00590
00591 static void b44_load_mac_and_phy_addr(struct b44_private *bp)
00592 {
00593 u8 eeprom[128];
00594
00595
00596 b44_read_eeprom(bp, &eeprom[0]);
00597 bp->netdev->hw_addr[0] = eeprom[79];
00598 bp->netdev->hw_addr[1] = eeprom[78];
00599 bp->netdev->hw_addr[2] = eeprom[81];
00600 bp->netdev->hw_addr[3] = eeprom[80];
00601 bp->netdev->hw_addr[4] = eeprom[83];
00602 bp->netdev->hw_addr[5] = eeprom[82];
00603
00604
00605 bp->phy_addr = eeprom[90] & 0x1f;
00606 }
00607
00608
00609 static void b44_set_rx_mode(struct net_device *netdev)
00610 {
00611 struct b44_private *bp = netdev_priv(netdev);
00612 unsigned char zero[6] = { 0, 0, 0, 0, 0, 0 };
00613 u32 val;
00614 int i;
00615
00616 val = br32(bp, B44_RXCONFIG);
00617 val &= ~RXCONFIG_PROMISC;
00618 val |= RXCONFIG_ALLMULTI;
00619
00620 b44_set_mac_addr(bp);
00621
00622 for (i = 1; i < 64; i++)
00623 b44_cam_write(bp, zero, i);
00624
00625 bw32(bp, B44_RXCONFIG, val);
00626 val = br32(bp, B44_CAM_CTRL);
00627 bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 static int b44_probe(struct pci_device *pci, const struct pci_device_id *id)
00641 {
00642 struct net_device *netdev;
00643 struct b44_private *bp;
00644 int rc;
00645
00646
00647
00648
00649
00650
00651 if (!phys_ram_within_limit(B44_30BIT_DMA_MASK)) {
00652 DBG("Sorry, this version of the driver does not\n"
00653 "support systems with more than 1GB of RAM.\n");
00654 return -ENOMEM;
00655 }
00656
00657
00658 netdev = alloc_etherdev(sizeof(*bp));
00659 if (!netdev)
00660 return -ENOMEM;
00661
00662 netdev_init(netdev, &b44_operations);
00663 pci_set_drvdata(pci, netdev);
00664 netdev->dev = &pci->dev;
00665
00666
00667 bp = netdev_priv(netdev);
00668 memset(bp, 0, sizeof(*bp));
00669 bp->netdev = netdev;
00670 bp->pci = pci;
00671
00672
00673 bp->regs = ioremap(pci->membase, B44_REGS_SIZE);
00674 if (!bp->regs) {
00675 netdev_put(netdev);
00676 return -ENOMEM;
00677 }
00678
00679
00680 adjust_pci_device(pci);
00681
00682 b44_load_mac_and_phy_addr(bp);
00683
00684
00685 netdev_link_up(netdev);
00686
00687 rc = register_netdev(netdev);
00688 if (rc != 0) {
00689 iounmap(bp->regs);
00690 netdev_put(netdev);
00691 return rc;
00692 }
00693
00694 b44_chip_reset(bp, B44_CHIP_RESET_FULL);
00695
00696 DBG("b44 %s (%04x:%04x) regs=%p MAC=%s\n", id->name, id->vendor,
00697 id->device, bp->regs, eth_ntoa(netdev->ll_addr));
00698
00699 return 0;
00700 }
00701
00702
00703
00704
00705
00706
00707
00708 static void b44_remove(struct pci_device *pci)
00709 {
00710 struct net_device *netdev = pci_get_drvdata(pci);
00711 struct b44_private *bp = netdev_priv(netdev);
00712
00713 ssb_core_disable(bp);
00714 unregister_netdev(netdev);
00715 iounmap(bp->regs);
00716 netdev_nullify(netdev);
00717 netdev_put(netdev);
00718 }
00719
00720
00721
00722
00723
00724
00725
00726 static void b44_irq(struct net_device *netdev, int enable)
00727 {
00728 struct b44_private *bp = netdev_priv(netdev);
00729
00730
00731 bw32(bp, B44_IMASK, enable ? IMASK_DEF : IMASK_DISABLE);
00732 }
00733
00734
00735
00736
00737
00738
00739
00740 static int b44_open(struct net_device *netdev)
00741 {
00742 struct b44_private *bp = netdev_priv(netdev);
00743 int rc;
00744
00745 rc = b44_init_tx_ring(bp);
00746 if (rc != 0)
00747 return rc;
00748
00749 rc = b44_init_rx_ring(bp);
00750 if (rc != 0)
00751 return rc;
00752
00753 b44_init_hw(bp, B44_FULL_RESET);
00754
00755
00756 b44_irq(netdev, 0);
00757
00758 return 0;
00759 }
00760
00761
00762
00763
00764
00765
00766 static void b44_close(struct net_device *netdev)
00767 {
00768 struct b44_private *bp = netdev_priv(netdev);
00769
00770 b44_chip_reset(bp, B44_FULL_RESET);
00771 b44_free_tx_ring(bp);
00772 b44_free_rx_ring(bp);
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782 static int b44_transmit(struct net_device *netdev, struct io_buffer *iobuf)
00783 {
00784 struct b44_private *bp = netdev_priv(netdev);
00785 u32 cur = bp->tx_cur;
00786 u32 ctrl;
00787
00788
00789 if (bp->tx[cur].ctrl) {
00790 DBG("tx overflow\n");
00791 return -ENOBUFS;
00792 }
00793
00794
00795 bp->tx_iobuf[cur] = iobuf;
00796
00797
00798 ctrl = (iob_len(iobuf) & DESC_CTRL_LEN) |
00799 DESC_CTRL_IOC | DESC_CTRL_SOF | DESC_CTRL_EOF;
00800
00801 if (cur == B44_RING_LAST)
00802 ctrl |= DESC_CTRL_EOT;
00803
00804 bp->tx[cur].ctrl = cpu_to_le32(ctrl);
00805 bp->tx[cur].addr = cpu_to_le32(VIRT_TO_B44(iobuf->data));
00806
00807
00808 cur = ring_next(cur);
00809 bp->tx_cur = cur;
00810 wmb();
00811
00812
00813 bw32(bp, B44_DMATX_PTR, cur * sizeof(struct dma_desc));
00814 return 0;
00815 }
00816
00817
00818
00819
00820
00821
00822 static void b44_tx_complete(struct b44_private *bp)
00823 {
00824 u32 cur, i;
00825
00826 cur = pending_tx_index(bp);
00827
00828 for (i = bp->tx_dirty; i != cur; i = ring_next(i)) {
00829
00830 netdev_tx_complete(bp->netdev, bp->tx_iobuf[i]);
00831 bp->tx_iobuf[i] = NULL;
00832
00833
00834 bp->tx[i].ctrl = 0;
00835 bp->tx[i].addr = 0;
00836 }
00837 bp->tx_dirty = cur;
00838 }
00839
00840
00841 static void b44_process_rx_packets(struct b44_private *bp)
00842 {
00843 struct io_buffer *iob;
00844 struct rx_header *rh;
00845 u32 pending, i;
00846 u16 len;
00847
00848 pending = pending_rx_index(bp);
00849
00850 for (i = bp->rx_cur; i != pending; i = ring_next(i)) {
00851 iob = bp->rx_iobuf[i];
00852 if (iob == NULL)
00853 break;
00854
00855 rh = iob->data;
00856 len = le16_to_cpu(rh->len);
00857
00858
00859
00860
00861
00862 if (len == 0)
00863 break;
00864
00865
00866 len -= 4;
00867
00868
00869 if (len > RX_PKT_BUF_SZ - RX_PKT_OFFSET ||
00870 (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
00871 DBG("rx error len=%d flags=%04x\n", len,
00872 cpu_to_le16(rh->flags));
00873 rh->len = 0;
00874 rh->flags = 0;
00875 netdev_rx_err(bp->netdev, iob, -EINVAL);
00876 continue;
00877 }
00878
00879
00880 rh->len = 0;
00881 rh->flags = 0;
00882 bp->rx_iobuf[i] = NULL;
00883
00884
00885 iob_reserve(iob, RX_PKT_OFFSET);
00886 iob_put(iob, len);
00887 netdev_rx(bp->netdev, iob);
00888 }
00889 bp->rx_cur = i;
00890 b44_rx_refill(bp, pending_rx_index(bp));
00891 }
00892
00893
00894
00895
00896
00897
00898 static void b44_poll(struct net_device *netdev)
00899 {
00900 struct b44_private *bp = netdev_priv(netdev);
00901 u32 istat;
00902
00903
00904 istat = br32(bp, B44_ISTAT);
00905 istat &= IMASK_DEF;
00906
00907 if (!istat)
00908 return;
00909 if (istat & ISTAT_TX)
00910 b44_tx_complete(bp);
00911 if (istat & ISTAT_RX)
00912 b44_process_rx_packets(bp);
00913 if (istat & ISTAT_ERRORS) {
00914 DBG("b44 error istat=0x%08x\n", istat);
00915
00916
00917 b44_irq(bp->netdev, 0);
00918 b44_halt(bp);
00919 b44_init_tx_ring(bp);
00920 b44_init_rx_ring(bp);
00921 b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
00922 }
00923
00924
00925 bw32(bp, B44_ISTAT, 0);
00926 bflush(bp, B44_ISTAT, 1);
00927 }
00928
00929
00930 static struct net_device_operations b44_operations = {
00931 .open = b44_open,
00932 .close = b44_close,
00933 .transmit = b44_transmit,
00934 .poll = b44_poll,
00935 .irq = b44_irq,
00936 };
00937
00938
00939 static struct pci_device_id b44_nics[] = {
00940 PCI_ROM(0x14e4, 0x4401, "BCM4401", "BCM4401", 0),
00941 PCI_ROM(0x14e4, 0x170c, "BCM4401-B0", "BCM4401-B0", 0),
00942 PCI_ROM(0x14e4, 0x4402, "BCM4401-B1", "BCM4401-B1", 0),
00943 };
00944
00945
00946 struct pci_driver b44_driver __pci_driver = {
00947 .ids = b44_nics,
00948 .id_count = sizeof b44_nics / sizeof b44_nics[0],
00949 .probe = b44_probe,
00950 .remove = b44_remove,
00951 };