|
|
1.1 ! root 1: /* ! 2: * eepro100.c -- This is a driver for Intel Fast Ethernet Controllers ! 3: * (ifec). ! 4: * ! 5: * Originally written for Etherboot by: ! 6: * ! 7: * Copyright (C) AW Computer Systems. ! 8: * written by R.E.Wolff -- [email protected] ! 9: * ! 10: * AW Computer Systems is contributing to the free software community ! 11: * by paying for this driver and then putting the result under GPL. ! 12: * ! 13: * If you need a Linux device driver, please contact BitWizard for a ! 14: * quote. ! 15: * ! 16: * This program is free software; you can redistribute it and/or ! 17: * modify it under the terms of the GNU General Public License as ! 18: * published by the Free Software Foundation; either version 2, or (at ! 19: * your option) any later version. ! 20: * ! 21: * This program is distributed in the hope that it will be useful, but ! 22: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 23: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 24: * General Public License for more details. ! 25: * ! 26: * You should have received a copy of the GNU General Public License ! 27: * along with this program; if not, write to the Free Software ! 28: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 29: * ! 30: * ! 31: * date version by what ! 32: * Written: May 29 1997 V0.10 REW Initial revision. ! 33: * changes: May 31 1997 V0.90 REW Works! ! 34: * Jun 1 1997 V0.91 REW Cleanup ! 35: * Jun 2 1997 V0.92 REW Add some code documentation ! 36: * Jul 25 1997 V1.00 REW Tested by AW to work in a PROM ! 37: * Cleanup for publication ! 38: * Dez 11 2004 V1.10 Kiszka Add RX ring buffer support ! 39: * Jun 2008 v2.0 mdeck Updated to iPXE. Changed much. ! 40: * ! 41: * Cleanups and fixes by Thomas Miletich<[email protected]> ! 42: * ! 43: * This is the etherboot intel etherexpress Pro/100B driver. ! 44: * ! 45: * It was written from scratch, with Donald Beckers eepro100.c kernel ! 46: * driver as a guideline. Mostly the 82557 related definitions and the ! 47: * lower level routines have been cut-and-pasted into this source. ! 48: * ! 49: * The driver was finished before Intel got the NDA out of the closet. ! 50: * ! 51: * Datasheet is now published and available from ! 52: * ftp://download.intel.com/design/network/manuals/8255X_OpenSDM.pdf ! 53: * - Michael Brown ! 54: * */ ! 55: ! 56: FILE_LICENCE ( GPL2_OR_LATER ); ! 57: ! 58: /* ! 59: * General Theory of Operation ! 60: * ! 61: * Initialization ! 62: * ! 63: * ifec_pci_probe() is called by iPXE during initialization. Typical NIC ! 64: * initialization is performed. EEPROM data is read. ! 65: * ! 66: * Network Boot ! 67: * ! 68: * ifec_net_open() is called by iPXE before attempting to network boot from the ! 69: * card. Here, the Command Unit & Receive Unit are initialized. The tx & rx ! 70: * rings are setup. The MAC address is programmed and the card is configured. ! 71: * ! 72: * Transmit ! 73: * ! 74: * ifec_net_transmit() enqueues a packet in the tx ring - active::tcbs[] The tx ! 75: * ring is composed of TCBs linked to each other into a ring. A tx request ! 76: * fills out the next available TCB with a pointer to the packet data. ! 77: * The last enqueued tx is always at active::tcb_head. Thus, a tx request fills ! 78: * out the TCB following tcb_head. ! 79: * active::tcb_tail points to the TCB we're awaiting completion of. ! 80: * ifec_tx_process() checks tcb_tail, and once complete, ! 81: * blindly increments tcb_tail to the next ring TCB. ! 82: * ! 83: * Receive ! 84: * ! 85: * priv::rfds[] is an array of Receive Frame Descriptors. The RFDs are linked ! 86: * together to form a ring. ! 87: * ifec_net_poll() calls ifec_rx_process(), which checks the next RFD for ! 88: * data. If we received a packet, we allocate a new io_buffer and copy the ! 89: * packet data into it. If alloc_iob() fails, we don't touch the RFD and try ! 90: * again on the next poll. ! 91: */ ! 92: ! 93: /* ! 94: * Debugging levels: ! 95: * - DBG() is for any errors, i.e. failed alloc_iob(), malloc_dma(), ! 96: * TX overflow, corrupted packets, ... ! 97: * - DBG2() is for successful events, like packet received, ! 98: * packet transmitted, and other general notifications. ! 99: * - DBGP() prints the name of each called function on entry ! 100: */ ! 101: ! 102: #include <stdint.h> ! 103: #include <byteswap.h> ! 104: #include <errno.h> ! 105: #include <stdio.h> ! 106: #include <unistd.h> ! 107: #include <ipxe/ethernet.h> ! 108: #include <ipxe/if_ether.h> ! 109: #include <ipxe/iobuf.h> ! 110: #include <ipxe/malloc.h> ! 111: #include <ipxe/pci.h> ! 112: #include <ipxe/spi_bit.h> ! 113: #include <ipxe/timer.h> ! 114: #include <ipxe/nvs.h> ! 115: #include <ipxe/threewire.h> ! 116: #include <ipxe/netdevice.h> ! 117: #include "eepro100.h" ! 118: ! 119: /****************************** Global data **********************************/ ! 120: ! 121: /* ! 122: * This is the default configuration command data. The values were copied from ! 123: * the Linux kernel initialization for the eepro100. ! 124: */ ! 125: static struct ifec_cfg ifec_cfg = { ! 126: .status = 0, ! 127: .command = CmdConfigure | CmdSuspend, ! 128: .link = 0, /* Filled in later */ ! 129: .byte = { 22, /* How many bytes in this array */ ! 130: ( TX_FIFO << 4 ) | RX_FIFO, /* Rx & Tx FIFO limits */ ! 131: 0, 0, /* Adaptive Interframe Spacing */ ! 132: RX_DMA_COUNT, /* Rx DMA max byte count */ ! 133: TX_DMA_COUNT + 0x80, /* Tx DMA max byte count */ ! 134: 0x32, /* Many bits. */ ! 135: 0x03, /* Discard short receive & Underrun retries */ ! 136: 1, /* 1=Use MII 0=Use AUI */ ! 137: 0, ! 138: 0x2E, /* NSAI, Preamble length, & Loopback*/ ! 139: 0, /* Linear priority */ ! 140: 0x60, /* L PRI MODE & Interframe spacing */ ! 141: 0, 0xf2, ! 142: 0x48, /* Promiscuous, Broadcast disable, CRS & CDT */ ! 143: 0, 0x40, ! 144: 0xf2, /* Stripping, Padding, Receive CRC Transfer */ ! 145: 0x80, /* 0x40=Force full-duplex, 0x80=Allowfull-duplex*/ ! 146: 0x3f, /* Multiple IA */ ! 147: 0x0D } /* Multicast all */ ! 148: }; ! 149: ! 150: static struct net_device_operations ifec_operations = { ! 151: .open = ifec_net_open, ! 152: .close = ifec_net_close, ! 153: .transmit = ifec_net_transmit, ! 154: .poll = ifec_net_poll, ! 155: .irq = ifec_net_irq ! 156: }; ! 157: ! 158: /******************* iPXE PCI Device Driver API functions ********************/ ! 159: ! 160: /* ! 161: * Initialize the PCI device. ! 162: * ! 163: * @v pci The device's associated pci_device structure. ! 164: * @v id The PCI device + vendor id. ! 165: * @ret rc Returns zero if successfully initialized. ! 166: * ! 167: * This function is called very early on, while iPXE is initializing. ! 168: * This is a iPXE PCI Device Driver API function. ! 169: */ ! 170: static int ifec_pci_probe ( struct pci_device *pci ) ! 171: { ! 172: struct net_device *netdev; ! 173: struct ifec_private *priv; ! 174: int rc; ! 175: ! 176: DBGP ( "ifec_pci_probe: " ); ! 177: ! 178: if ( pci->ioaddr == 0 ) ! 179: return -EINVAL; ! 180: ! 181: netdev = alloc_etherdev ( sizeof(*priv) ); ! 182: if ( !netdev ) ! 183: return -ENOMEM; ! 184: ! 185: netdev_init ( netdev, &ifec_operations ); ! 186: priv = netdev->priv; ! 187: ! 188: pci_set_drvdata ( pci, netdev ); ! 189: netdev->dev = &pci->dev; ! 190: ! 191: /* enable bus master, etc */ ! 192: adjust_pci_device( pci ); ! 193: ! 194: DBGP ( "pci " ); ! 195: ! 196: memset ( priv, 0, sizeof(*priv) ); ! 197: priv->ioaddr = pci->ioaddr; ! 198: ! 199: ifec_reset ( netdev ); ! 200: DBGP ( "reset " ); ! 201: ! 202: ifec_init_eeprom ( netdev ); ! 203: ! 204: /* read MAC address */ ! 205: nvs_read ( &priv->eeprom.nvs, EEPROM_ADDR_MAC_0, netdev->hw_addr, ! 206: ETH_ALEN ); ! 207: /* read mdio_register */ ! 208: nvs_read ( &priv->eeprom.nvs, EEPROM_ADDR_MDIO_REGISTER, ! 209: &priv->mdio_register, 2 ); ! 210: ! 211: if ( ( rc = register_netdev ( netdev ) ) != 0 ) ! 212: goto error; ! 213: ! 214: netdev_link_up ( netdev ); ! 215: ! 216: DBGP ( "ints\n" ); ! 217: ! 218: return 0; ! 219: ! 220: error: ! 221: ifec_reset ( netdev ); ! 222: netdev_nullify ( netdev ); ! 223: netdev_put ( netdev ); ! 224: ! 225: return rc; ! 226: } ! 227: ! 228: /* ! 229: * Remove a device from the PCI device list. ! 230: * ! 231: * @v pci PCI device to remove. ! 232: * ! 233: * This is a PCI Device Driver API function. ! 234: */ ! 235: static void ifec_pci_remove ( struct pci_device *pci ) ! 236: { ! 237: struct net_device *netdev = pci_get_drvdata ( pci ); ! 238: ! 239: DBGP ( "ifec_pci_remove\n" ); ! 240: ! 241: unregister_netdev ( netdev ); ! 242: ifec_reset ( netdev ); ! 243: netdev_nullify ( netdev ); ! 244: netdev_put ( netdev ); ! 245: } ! 246: ! 247: /****************** iPXE Network Device Driver API functions *****************/ ! 248: ! 249: /* ! 250: * Close a network device. ! 251: * ! 252: * @v netdev Device to close. ! 253: * ! 254: * This is a iPXE Network Device Driver API function. ! 255: */ ! 256: static void ifec_net_close ( struct net_device *netdev ) ! 257: { ! 258: struct ifec_private *priv = netdev->priv; ! 259: unsigned long ioaddr = priv->ioaddr; ! 260: unsigned short intr_status; ! 261: ! 262: DBGP ( "ifec_net_close\n" ); ! 263: ! 264: /* disable interrupts */ ! 265: ifec_net_irq ( netdev, 0 ); ! 266: ! 267: /* Ack & clear ints */ ! 268: intr_status = inw ( ioaddr + SCBStatus ); ! 269: outw ( intr_status, ioaddr + SCBStatus ); ! 270: inw ( ioaddr + SCBStatus ); ! 271: ! 272: ifec_reset ( netdev ); ! 273: ! 274: /* Free any resources */ ! 275: ifec_free ( netdev ); ! 276: } ! 277: ! 278: /* Interrupts to be masked */ ! 279: #define INTERRUPT_MASK ( SCBMaskEarlyRx | SCBMaskFlowCtl ) ! 280: ! 281: /* ! 282: * Enable or disable IRQ masking. ! 283: * ! 284: * @v netdev Device to control. ! 285: * @v enable Zero to mask off IRQ, non-zero to enable IRQ. ! 286: * ! 287: * This is a iPXE Network Driver API function. ! 288: */ ! 289: static void ifec_net_irq ( struct net_device *netdev, int enable ) ! 290: { ! 291: struct ifec_private *priv = netdev->priv; ! 292: unsigned long ioaddr = priv->ioaddr; ! 293: ! 294: DBGP ( "ifec_net_irq\n" ); ! 295: ! 296: outw ( enable ? INTERRUPT_MASK : SCBMaskAll, ioaddr + SCBCmd ); ! 297: } ! 298: ! 299: /* ! 300: * Opens a network device. ! 301: * ! 302: * @v netdev Device to be opened. ! 303: * @ret rc Non-zero if failed to open. ! 304: * ! 305: * This enables tx and rx on the device. ! 306: * This is a iPXE Network Device Driver API function. ! 307: */ ! 308: static int ifec_net_open ( struct net_device *netdev ) ! 309: { ! 310: struct ifec_private *priv = netdev->priv; ! 311: struct ifec_ias *ias = NULL; ! 312: struct ifec_cfg *cfg = NULL; ! 313: int i, options; ! 314: int rc = -ENOMEM; ! 315: ! 316: DBGP ( "ifec_net_open: " ); ! 317: ! 318: /* Ensure interrupts are disabled. */ ! 319: ifec_net_irq ( netdev, 0 ); ! 320: ! 321: /* Initialize Command Unit and Receive Unit base addresses. */ ! 322: ifec_scb_cmd ( netdev, 0, RUAddrLoad ); ! 323: ifec_scb_cmd ( netdev, virt_to_bus ( &priv->stats ), CUStatsAddr ); ! 324: ifec_scb_cmd ( netdev, 0, CUCmdBase ); ! 325: ! 326: /* Initialize both rings */ ! 327: if ( ( rc = ifec_rx_setup ( netdev ) ) != 0 ) ! 328: goto error; ! 329: if ( ( rc = ifec_tx_setup ( netdev ) ) != 0 ) ! 330: goto error; ! 331: ! 332: /* Initialize MDIO */ ! 333: options = 0x00; /* 0x40 = 10mbps half duplex, 0x00 = Autosense */ ! 334: ifec_mdio_setup ( netdev, options ); ! 335: ! 336: /* Prepare MAC address w/ Individual Address Setup (ias) command.*/ ! 337: ias = malloc_dma ( sizeof ( *ias ), CB_ALIGN ); ! 338: if ( !ias ) { ! 339: rc = -ENOMEM; ! 340: goto error; ! 341: } ! 342: ias->command = CmdIASetup; ! 343: ias->status = 0; ! 344: memcpy ( ias->ia, netdev->ll_addr, ETH_ALEN ); ! 345: ! 346: /* Prepare operating parameters w/ a configure command. */ ! 347: cfg = malloc_dma ( sizeof ( *cfg ), CB_ALIGN ); ! 348: if ( !cfg ) { ! 349: rc = -ENOMEM; ! 350: goto error; ! 351: } ! 352: memcpy ( cfg, &ifec_cfg, sizeof ( *cfg ) ); ! 353: cfg->link = virt_to_bus ( priv->tcbs ); ! 354: cfg->byte[19] = ( options & 0x10 ) ? 0xC0 : 0x80; ! 355: ias->link = virt_to_bus ( cfg ); ! 356: ! 357: /* Issue the ias and configure commands. */ ! 358: ifec_scb_cmd ( netdev, virt_to_bus ( ias ), CUStart ); ! 359: ifec_scb_cmd_wait ( netdev ); ! 360: priv->configured = 1; ! 361: ! 362: /* Wait up to 10 ms for configuration to initiate */ ! 363: for ( i = 10; i && !cfg->status; i-- ) ! 364: mdelay ( 1 ); ! 365: if ( ! cfg->status ) { ! 366: DBG ( "Failed to initiate!\n" ); ! 367: goto error; ! 368: } ! 369: free_dma ( ias, sizeof ( *ias ) ); ! 370: free_dma ( cfg, sizeof ( *cfg ) ); ! 371: DBG2 ( "cfg " ); ! 372: ! 373: /* Enable rx by sending ring address to card */ ! 374: if ( priv->rfds[0] != NULL ) { ! 375: ifec_scb_cmd ( netdev, virt_to_bus( priv->rfds[0] ), RUStart ); ! 376: ifec_scb_cmd_wait ( netdev ); ! 377: } ! 378: DBG2 ( "rx_start\n" ); ! 379: ! 380: return 0; ! 381: ! 382: error: ! 383: free_dma ( cfg, sizeof ( *cfg ) ); ! 384: free_dma ( ias, sizeof ( *ias ) ); ! 385: ifec_free ( netdev ); ! 386: ifec_reset ( netdev ); ! 387: return rc; ! 388: } ! 389: ! 390: /* ! 391: * This function allows a driver to process events during operation. ! 392: * ! 393: * @v netdev Device being polled. ! 394: * ! 395: * This is called periodically by iPXE to let the driver check the status of ! 396: * transmitted packets and to allow the driver to check for received packets. ! 397: * This is a iPXE Network Device Driver API function. ! 398: */ ! 399: static void ifec_net_poll ( struct net_device *netdev ) ! 400: { ! 401: struct ifec_private *priv = netdev->priv; ! 402: unsigned short intr_status; ! 403: ! 404: DBGP ( "ifec_net_poll\n" ); ! 405: ! 406: /* acknowledge interrupts ASAP */ ! 407: intr_status = inw ( priv->ioaddr + SCBStatus ); ! 408: outw ( intr_status, priv->ioaddr + SCBStatus ); ! 409: inw ( priv->ioaddr + SCBStatus ); ! 410: ! 411: DBG2 ( "poll - status: 0x%04X\n", intr_status ); ! 412: ! 413: /* anything to do here? */ ! 414: if ( ( intr_status & ( ~INTERRUPT_MASK ) ) == 0 ) ! 415: return; ! 416: ! 417: /* process received and transmitted packets */ ! 418: ifec_tx_process ( netdev ); ! 419: ifec_rx_process ( netdev ); ! 420: ! 421: ifec_check_ru_status ( netdev, intr_status ); ! 422: ! 423: return; ! 424: } ! 425: ! 426: /* ! 427: * This transmits a packet. ! 428: * ! 429: * @v netdev Device to transmit from. ! 430: * @v iobuf Data to transmit. ! 431: * @ret rc Non-zero if failed to transmit. ! 432: * ! 433: * This is a iPXE Network Driver API function. ! 434: */ ! 435: static int ifec_net_transmit ( struct net_device *netdev, ! 436: struct io_buffer *iobuf ) ! 437: { ! 438: struct ifec_private *priv = netdev->priv; ! 439: struct ifec_tcb *tcb = priv->tcb_head->next; ! 440: unsigned long ioaddr = priv->ioaddr; ! 441: ! 442: DBGP ( "ifec_net_transmit\n" ); ! 443: ! 444: /* Wait for TCB to become available. */ ! 445: if ( tcb->status || tcb->iob ) { ! 446: DBG ( "TX overflow\n" ); ! 447: return -ENOBUFS; ! 448: } ! 449: ! 450: DBG2 ( "transmitting packet (%zd bytes). status = %hX, cmd=%hX\n", ! 451: iob_len ( iobuf ), tcb->status, inw ( ioaddr + SCBCmd ) ); ! 452: ! 453: tcb->command = CmdSuspend | CmdTx | CmdTxFlex; ! 454: tcb->count = 0x01208000; ! 455: tcb->tbd_addr0 = virt_to_bus ( iobuf->data ); ! 456: tcb->tbd_size0 = 0x3FFF & iob_len ( iobuf ); ! 457: tcb->iob = iobuf; ! 458: ! 459: ifec_tx_wake ( netdev ); ! 460: ! 461: /* Append to end of ring. */ ! 462: priv->tcb_head = tcb; ! 463: ! 464: return 0; ! 465: } ! 466: ! 467: /*************************** Local support functions *************************/ ! 468: ! 469: /* Define what each GPIO Pin does */ ! 470: static const uint16_t ifec_ee_bits[] = { ! 471: [SPI_BIT_SCLK] = EE_SHIFT_CLK, ! 472: [SPI_BIT_MOSI] = EE_DATA_WRITE, ! 473: [SPI_BIT_MISO] = EE_DATA_READ, ! 474: [SPI_BIT_SS(0)] = EE_ENB, ! 475: }; ! 476: ! 477: /* ! 478: * Read a single bit from the GPIO pins used for SPI. ! 479: * should be called by SPI bitbash functions only ! 480: * ! 481: * @v basher Bitbash device ! 482: * @v bit_id Line to be read ! 483: */ ! 484: static int ifec_spi_read_bit ( struct bit_basher *basher, ! 485: unsigned int bit_id ) ! 486: { ! 487: struct ifec_private *priv = ! 488: container_of ( basher, struct ifec_private, spi.basher ); ! 489: unsigned long ee_addr = priv->ioaddr + CSREeprom; ! 490: unsigned int ret = 0; ! 491: uint16_t mask; ! 492: ! 493: DBGP ( "ifec_spi_read_bit\n" ); ! 494: ! 495: mask = ifec_ee_bits[bit_id]; ! 496: ret = inw (ee_addr); ! 497: ! 498: return ( ret & mask ) ? 1 : 0; ! 499: } ! 500: ! 501: /* ! 502: * Write a single bit to the GPIO pins used for SPI. ! 503: * should be called by SPI bitbash functions only ! 504: * ! 505: * @v basher Bitbash device ! 506: * @v bit_id Line to write to ! 507: * @v data Value to write ! 508: */ ! 509: static void ifec_spi_write_bit ( struct bit_basher *basher, ! 510: unsigned int bit_id, ! 511: unsigned long data ) ! 512: { ! 513: struct ifec_private *priv = ! 514: container_of ( basher, struct ifec_private, spi.basher ); ! 515: unsigned long ee_addr = priv->ioaddr + CSREeprom; ! 516: short val; ! 517: uint16_t mask = ifec_ee_bits[bit_id]; ! 518: ! 519: DBGP ( "ifec_spi_write_bit\n" ); ! 520: ! 521: val = inw ( ee_addr ); ! 522: val &= ~mask; ! 523: val |= data & mask; ! 524: ! 525: outw ( val, ee_addr ); ! 526: } ! 527: ! 528: /* set function pointer to SPI read- and write-bit functions */ ! 529: static struct bit_basher_operations ifec_basher_ops = { ! 530: .read = ifec_spi_read_bit, ! 531: .write = ifec_spi_write_bit, ! 532: }; ! 533: ! 534: /* ! 535: * Initialize the eeprom stuff ! 536: * ! 537: * @v netdev Network device ! 538: */ ! 539: static void ifec_init_eeprom ( struct net_device *netdev ) ! 540: { ! 541: struct ifec_private *priv = netdev->priv; ! 542: ! 543: DBGP ( "ifec_init_eeprom\n" ); ! 544: ! 545: priv->spi.basher.op = &ifec_basher_ops; ! 546: priv->spi.bus.mode = SPI_MODE_THREEWIRE; ! 547: init_spi_bit_basher ( &priv->spi ); ! 548: ! 549: priv->eeprom.bus = &priv->spi.bus; ! 550: ! 551: /* init as 93c46(93c14 compatible) first, to set the command len, ! 552: * block size and word len. Needs to be set for address len detection. ! 553: */ ! 554: init_at93c46 ( &priv->eeprom, 16 ); ! 555: ! 556: /* detect address length, */ ! 557: threewire_detect_address_len ( &priv->eeprom ); ! 558: ! 559: /* address len == 8 means 93c66 instead of 93c46 */ ! 560: if ( priv->eeprom.address_len == 8 ) ! 561: init_at93c66 ( &priv->eeprom, 16 ); ! 562: } ! 563: ! 564: /* ! 565: * Support function: ifec_mdio_read ! 566: * ! 567: * This probably reads a register in the "physical media interface chip". ! 568: * -- REW ! 569: */ ! 570: static int ifec_mdio_read ( struct net_device *netdev, int phy_id, ! 571: int location ) ! 572: { ! 573: struct ifec_private *priv = netdev->priv; ! 574: unsigned long ioaddr = priv->ioaddr; ! 575: int val; ! 576: int boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */ ! 577: ! 578: DBGP ( "ifec_mdio_read\n" ); ! 579: ! 580: outl ( 0x08000000 | ( location << 16 ) | ( phy_id << 21 ), ! 581: ioaddr + CSRCtrlMDI ); ! 582: do { ! 583: udelay ( 16 ); ! 584: ! 585: val = inl ( ioaddr + CSRCtrlMDI ); ! 586: ! 587: if ( --boguscnt < 0 ) { ! 588: DBG ( " ifec_mdio_read() time out with val = %X.\n", ! 589: val ); ! 590: break; ! 591: } ! 592: } while (! ( val & 0x10000000 ) ); ! 593: return val & 0xffff; ! 594: } ! 595: ! 596: /* ! 597: * Initializes MDIO. ! 598: * ! 599: * @v netdev Network device ! 600: * @v options MDIO options ! 601: */ ! 602: static void ifec_mdio_setup ( struct net_device *netdev, int options ) ! 603: { ! 604: struct ifec_private *priv = netdev->priv; ! 605: unsigned short mdio_register = priv->mdio_register; ! 606: ! 607: DBGP ( "ifec_mdio_setup\n" ); ! 608: ! 609: if ( ( (mdio_register>>8) & 0x3f ) == DP83840 ! 610: || ( (mdio_register>>8) & 0x3f ) == DP83840A ) { ! 611: int mdi_reg23 = ifec_mdio_read ( netdev, mdio_register ! 612: & 0x1f, 23 ) | 0x0422; ! 613: if (CONGENB) ! 614: mdi_reg23 |= 0x0100; ! 615: DBG2 ( "DP83840 specific setup, setting register 23 to " ! 616: "%hX.\n", mdi_reg23 ); ! 617: ifec_mdio_write ( netdev, mdio_register & 0x1f, 23, mdi_reg23 ); ! 618: } ! 619: DBG2 ( "dp83840 " ); ! 620: if ( options != 0 ) { ! 621: ifec_mdio_write ( netdev, mdio_register & 0x1f, 0, ! 622: ( (options & 0x20) ? 0x2000 : 0 ) | ! 623: ( (options & 0x10) ? 0x0100 : 0 ) ); ! 624: DBG2 ( "set mdio_register. " ); ! 625: } ! 626: } ! 627: ! 628: /* ! 629: * Support function: ifec_mdio_write ! 630: * ! 631: * This probably writes to the "physical media interface chip". ! 632: * -- REW ! 633: */ ! 634: static int ifec_mdio_write ( struct net_device *netdev, ! 635: int phy_id, int location, int value ) ! 636: { ! 637: struct ifec_private *priv = netdev->priv; ! 638: unsigned long ioaddr = priv->ioaddr; ! 639: int val; ! 640: int boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */ ! 641: ! 642: DBGP ( "ifec_mdio_write\n" ); ! 643: ! 644: outl ( 0x04000000 | ( location << 16 ) | ( phy_id << 21 ) | value, ! 645: ioaddr + CSRCtrlMDI ); ! 646: do { ! 647: udelay ( 16 ); ! 648: ! 649: val = inl ( ioaddr + CSRCtrlMDI ); ! 650: if ( --boguscnt < 0 ) { ! 651: DBG ( " ifec_mdio_write() time out with val = %X.\n", ! 652: val ); ! 653: break; ! 654: } ! 655: } while (! ( val & 0x10000000 ) ); ! 656: return val & 0xffff; ! 657: } ! 658: ! 659: /* ! 660: * Resets the hardware. ! 661: * ! 662: * @v netdev Network device ! 663: */ ! 664: static void ifec_reset ( struct net_device *netdev ) ! 665: { ! 666: struct ifec_private *priv = netdev->priv; ! 667: unsigned long ioaddr = priv->ioaddr; ! 668: ! 669: DBGP ( "ifec_reset\n" ); ! 670: ! 671: /* do partial reset first */ ! 672: outl ( PortPartialReset, ioaddr + CSRPort ); ! 673: inw ( ioaddr + SCBStatus ); ! 674: udelay ( 20 ); ! 675: ! 676: /* full reset */ ! 677: outl ( PortReset, ioaddr + CSRPort ); ! 678: inw ( ioaddr + SCBStatus ); ! 679: udelay ( 20 ); ! 680: ! 681: /* disable interrupts again */ ! 682: ifec_net_irq ( netdev, 0 ); ! 683: } ! 684: ! 685: /* ! 686: * free()s the tx/rx rings. ! 687: * ! 688: * @v netdev Network device ! 689: */ ! 690: static void ifec_free ( struct net_device *netdev ) ! 691: { ! 692: struct ifec_private *priv = netdev_priv ( netdev ); ! 693: int i; ! 694: ! 695: DBGP ( "ifec_free\n" ); ! 696: ! 697: /* free all allocated receive io_buffers */ ! 698: for ( i = 0; i < RFD_COUNT; i++ ) { ! 699: free_iob ( priv->rx_iobs[i] ); ! 700: priv->rx_iobs[i] = NULL; ! 701: priv->rfds[i] = NULL; ! 702: } ! 703: ! 704: /* free TX ring buffer */ ! 705: free_dma ( priv->tcbs, TX_RING_BYTES ); ! 706: ! 707: priv->tcbs = NULL; ! 708: } ! 709: ! 710: /* ! 711: * Initializes an RFD. ! 712: * ! 713: * @v rfd RFD struct to initialize ! 714: * @v command Command word ! 715: * @v link Link value ! 716: */ ! 717: static void ifec_rfd_init ( struct ifec_rfd *rfd, s16 command, u32 link ) ! 718: { ! 719: DBGP ( "ifec_rfd_init\n" ); ! 720: ! 721: rfd->status = 0; ! 722: rfd->command = command; ! 723: rfd->rx_buf_addr = 0xFFFFFFFF; ! 724: rfd->count = 0; ! 725: rfd->size = RFD_PACKET_LEN; ! 726: rfd->link = link; ! 727: } ! 728: ! 729: /* ! 730: * Send address of new RFD to card ! 731: * ! 732: * @v netdev Network device ! 733: */ ! 734: static void ifec_reprime_ru ( struct net_device *netdev ) ! 735: { ! 736: struct ifec_private *priv = netdev->priv; ! 737: int cur_rx = priv->cur_rx; ! 738: ! 739: DBGP ( "ifec_reprime_ru\n" ); ! 740: ! 741: if ( priv->rfds[cur_rx] != NULL ) { ! 742: ifec_scb_cmd ( netdev, virt_to_bus ( priv->rfds[cur_rx] ), ! 743: RUStart ); ! 744: ifec_scb_cmd_wait ( netdev ); ! 745: } ! 746: } ! 747: ! 748: /* ! 749: * Check if reprime of RU needed ! 750: * ! 751: * @v netdev Network device ! 752: */ ! 753: static void ifec_check_ru_status ( struct net_device *netdev, ! 754: unsigned short intr_status ) ! 755: { ! 756: struct ifec_private *priv = netdev->priv; ! 757: ! 758: DBGP ( "ifec_check_ru_status\n" ); ! 759: ! 760: /* ! 761: * The chip may have suspended reception for various reasons. ! 762: * Check for that, and re-prime it should this be the case. ! 763: */ ! 764: switch ( ( intr_status >> 2 ) & 0xf ) { ! 765: case 0: /* Idle */ ! 766: case 4: /* Ready */ ! 767: break; ! 768: case 1: /* Suspended */ ! 769: case 2: /* No resources (RFDs) */ ! 770: case 9: /* Suspended with no more RBDs */ ! 771: case 10: /* No resources due to no RBDs */ ! 772: case 12: /* Ready with no RBDs */ ! 773: DBG ( "ifec_net_poll: RU reprimed.\n" ); ! 774: ifec_reprime_ru ( netdev ); ! 775: break; ! 776: default: ! 777: /* reserved values */ ! 778: DBG ( "ifec_net_poll: RU state anomaly: %i\n", ! 779: ( inw ( priv->ioaddr + SCBStatus ) >> 2 ) & 0xf ); ! 780: break; ! 781: } ! 782: } ! 783: ! 784: #define RFD_STATUS ( RFD_OK | RFDRxCol | RFDRxErr | RFDShort | \ ! 785: RFDDMAOverrun | RFDNoBufs | RFDCRCError ) ! 786: /* ! 787: * Looks for received packets in the rx ring, reports success or error to ! 788: * the core accordingly. Starts reallocation of rx ring. ! 789: * ! 790: * @v netdev Network device ! 791: */ ! 792: static void ifec_rx_process ( struct net_device *netdev ) ! 793: { ! 794: struct ifec_private *priv = netdev->priv; ! 795: int cur_rx = priv->cur_rx; ! 796: struct io_buffer *iob = priv->rx_iobs[cur_rx]; ! 797: struct ifec_rfd *rfd = priv->rfds[cur_rx]; ! 798: unsigned int rx_len; ! 799: s16 status; ! 800: ! 801: DBGP ( "ifec_rx_process\n" ); ! 802: ! 803: /* Process any received packets */ ! 804: while ( iob && rfd && ( status = rfd->status ) ) { ! 805: rx_len = rfd->count & RFDMaskCount; ! 806: ! 807: DBG2 ( "Got a packet: Len = %d, cur_rx = %d.\n", rx_len, ! 808: cur_rx ); ! 809: DBGIO_HD ( (void*)rfd->packet, 0x30 ); ! 810: ! 811: if ( ( status & ( RFD_STATUS & ~RFDShort ) ) != RFD_OK ) { ! 812: DBG ( "Corrupted packet received. " ! 813: "Status = %#08hx\n", status ); ! 814: netdev_rx_err ( netdev, iob, -EINVAL ); ! 815: } else { ! 816: /* Hand off the packet to the network subsystem */ ! 817: iob_put ( iob, rx_len ); ! 818: DBG2 ( "Received packet: %p, len: %d\n", iob, rx_len ); ! 819: netdev_rx ( netdev, iob ); ! 820: } ! 821: ! 822: /* make sure we don't reuse this RFD */ ! 823: priv->rx_iobs[cur_rx] = NULL; ! 824: priv->rfds[cur_rx] = NULL; ! 825: ! 826: /* Next RFD */ ! 827: priv->cur_rx = ( cur_rx + 1 ) % RFD_COUNT; ! 828: cur_rx = priv->cur_rx; ! 829: iob = priv->rx_iobs[cur_rx]; ! 830: rfd = priv->rfds[cur_rx]; ! 831: } ! 832: ! 833: ifec_refill_rx_ring ( netdev ); ! 834: } ! 835: ! 836: /* ! 837: * Allocates io_buffer, set pointers in ifec_private structure accordingly, ! 838: * reserves space for RFD header in io_buffer. ! 839: * ! 840: * @v netdev Network device ! 841: * @v cur Descriptor number to work on ! 842: * @v cmd Value to set cmd field in RFD to ! 843: * @v link Pointer to ned RFD ! 844: * @ret rc 0 on success, negative on failure ! 845: */ ! 846: static int ifec_get_rx_desc ( struct net_device *netdev, int cur, int cmd, ! 847: int link ) ! 848: { ! 849: struct ifec_private *priv = netdev->priv; ! 850: struct ifec_rfd *rfd = priv->rfds[cur]; ! 851: ! 852: DBGP ( "ifec_get_rx_desc\n" ); ! 853: ! 854: priv->rx_iobs[cur] = alloc_iob ( sizeof ( *rfd ) ); ! 855: if ( ! priv->rx_iobs[cur] ) { ! 856: DBG ( "alloc_iob failed. desc. nr: %d\n", cur ); ! 857: priv->rfds[cur] = NULL; ! 858: return -ENOMEM; ! 859: } ! 860: ! 861: /* Initialize new tail. */ ! 862: priv->rfds[cur] = priv->rx_iobs[cur]->data; ! 863: ifec_rfd_init ( priv->rfds[cur], cmd, link ); ! 864: iob_reserve ( priv->rx_iobs[cur], RFD_HEADER_LEN ); ! 865: ! 866: return 0; ! 867: } ! 868: ! 869: /* ! 870: * Allocate new descriptor entries and initialize them if needed ! 871: * ! 872: * @v netdev Network device ! 873: */ ! 874: static void ifec_refill_rx_ring ( struct net_device *netdev ) ! 875: { ! 876: struct ifec_private *priv = netdev->priv; ! 877: int i, cur_rx; ! 878: unsigned short intr_status; ! 879: ! 880: DBGP ( "ifec_refill_rx_ring\n" ); ! 881: ! 882: for ( i = 0; i < RFD_COUNT; i++ ) { ! 883: cur_rx = ( priv->cur_rx + i ) % RFD_COUNT; ! 884: /* only refill if empty */ ! 885: if ( priv->rfds[cur_rx] != NULL || ! 886: priv->rx_iobs[cur_rx] != NULL ) ! 887: continue; ! 888: ! 889: DBG2 ( "refilling RFD %d\n", cur_rx ); ! 890: ! 891: if ( ifec_get_rx_desc ( netdev, cur_rx, ! 892: CmdSuspend | CmdEndOfList, 0 ) == 0 ) { ! 893: if ( i > 0 ) { ! 894: int prev_rx = ( ( ( cur_rx + RFD_COUNT ) - 1 ) ! 895: % RFD_COUNT ); ! 896: struct ifec_rfd *rfd = priv->rfds[prev_rx]; ! 897: ! 898: rfd->command = 0; ! 899: rfd->link = virt_to_bus ( priv->rfds[cur_rx] ); ! 900: } ! 901: } ! 902: } ! 903: ! 904: intr_status = inw ( priv->ioaddr + SCBStatus ); ! 905: ifec_check_ru_status ( netdev, intr_status ); ! 906: } ! 907: ! 908: /* ! 909: * Initial allocation & initialization of the rx ring. ! 910: * ! 911: * @v netdev Device of rx ring. ! 912: * @ret rc Non-zero if error occured ! 913: */ ! 914: static int ifec_rx_setup ( struct net_device *netdev ) ! 915: { ! 916: struct ifec_private *priv = netdev->priv; ! 917: int i; ! 918: ! 919: DBGP ( "ifec_rx_setup\n" ); ! 920: ! 921: priv->cur_rx = 0; ! 922: ! 923: /* init values for ifec_refill_rx_ring() */ ! 924: for ( i = 0; i < RFD_COUNT; i++ ) { ! 925: priv->rfds[i] = NULL; ! 926: priv->rx_iobs[i] = NULL; ! 927: } ! 928: ifec_refill_rx_ring ( netdev ); ! 929: ! 930: return 0; ! 931: } ! 932: ! 933: /* ! 934: * Initiates a SCB command. ! 935: * ! 936: * @v netdev Network device ! 937: * @v ptr General pointer value for command. ! 938: * @v cmd Command to issue. ! 939: * @ret rc Non-zero if command not issued. ! 940: */ ! 941: static int ifec_scb_cmd ( struct net_device *netdev, u32 ptr, u8 cmd ) ! 942: { ! 943: struct ifec_private *priv = netdev->priv; ! 944: unsigned long ioaddr = priv->ioaddr; ! 945: int rc; ! 946: ! 947: DBGP ( "ifec_scb_cmd\n" ); ! 948: ! 949: rc = ifec_scb_cmd_wait ( netdev ); /* Wait until ready */ ! 950: if ( !rc ) { ! 951: outl ( ptr, ioaddr + SCBPointer ); ! 952: outb ( cmd, ioaddr + SCBCmd ); /* Issue command */ ! 953: } ! 954: return rc; ! 955: } ! 956: ! 957: /* ! 958: * Wait for command unit to accept a command. ! 959: * ! 960: * @v cmd_ioaddr I/O address of command register. ! 961: * @ret rc Non-zero if command timed out. ! 962: */ ! 963: static int ifec_scb_cmd_wait ( struct net_device *netdev ) ! 964: { ! 965: struct ifec_private *priv = netdev->priv; ! 966: unsigned long cmd_ioaddr = priv->ioaddr + SCBCmd; ! 967: int rc, wait = CU_CMD_TIMEOUT; ! 968: ! 969: DBGP ( "ifec_scb_cmd_wait\n" ); ! 970: ! 971: for ( ; wait && ( rc = inb ( cmd_ioaddr ) ); wait-- ) ! 972: udelay ( 1 ); ! 973: ! 974: if ( !wait ) ! 975: DBG ( "ifec_scb_cmd_wait timeout!\n" ); ! 976: return rc; ! 977: } ! 978: ! 979: /* ! 980: * Check status of transmitted packets & perform tx completions. ! 981: * ! 982: * @v netdev Network device. ! 983: */ ! 984: static void ifec_tx_process ( struct net_device *netdev ) ! 985: { ! 986: struct ifec_private *priv = netdev->priv; ! 987: struct ifec_tcb *tcb = priv->tcb_tail; ! 988: s16 status; ! 989: ! 990: DBGP ( "ifec_tx_process\n" ); ! 991: ! 992: /* Check status of transmitted packets */ ! 993: while ( ( status = tcb->status ) && tcb->iob ) { ! 994: if ( status & TCB_U ) { ! 995: /* report error to iPXE */ ! 996: DBG ( "ifec_tx_process : tx error!\n " ); ! 997: netdev_tx_complete_err ( netdev, tcb->iob, -EINVAL ); ! 998: } else { ! 999: /* report successful transmit */ ! 1000: netdev_tx_complete ( netdev, tcb->iob ); ! 1001: } ! 1002: DBG2 ( "tx completion\n" ); ! 1003: ! 1004: tcb->iob = NULL; ! 1005: tcb->status = 0; ! 1006: ! 1007: priv->tcb_tail = tcb->next; /* Next TCB */ ! 1008: tcb = tcb->next; ! 1009: } ! 1010: } ! 1011: ! 1012: /* ! 1013: * Allocates & initialize tx resources. ! 1014: * ! 1015: * @v netdev Network device. ! 1016: * @ret rc Non-zero if error occurred. ! 1017: */ ! 1018: static int ifec_tx_setup ( struct net_device *netdev ) ! 1019: { ! 1020: struct ifec_private *priv = netdev->priv; ! 1021: struct ifec_tcb *tcb; ! 1022: int i; ! 1023: ! 1024: DBGP ( "ifec_tx_setup\n" ); ! 1025: ! 1026: /* allocate tx ring */ ! 1027: priv->tcbs = malloc_dma ( TX_RING_BYTES, CB_ALIGN ); ! 1028: if ( !priv->tcbs ) { ! 1029: DBG ( "TX-ring allocation failed\n" ); ! 1030: return -ENOMEM; ! 1031: } ! 1032: ! 1033: tcb = priv->tcb_tail = priv->tcbs; ! 1034: priv->tx_curr = priv->tx_tail = 0; ! 1035: priv->tx_cnt = 0; ! 1036: ! 1037: for ( i = 0; i < TCB_COUNT; i++, tcb++ ) { ! 1038: tcb->status = 0; ! 1039: tcb->count = 0x01208000; ! 1040: tcb->iob = NULL; ! 1041: tcb->tbda_addr = virt_to_bus ( &tcb->tbd_addr0 ); ! 1042: tcb->link = virt_to_bus ( tcb + 1 ); ! 1043: tcb->next = tcb + 1; ! 1044: } ! 1045: /* We point tcb_head at the last TCB, so the first ifec_net_transmit() ! 1046: * will use the first (head->next) TCB to transmit. */ ! 1047: priv->tcb_head = --tcb; ! 1048: tcb->link = virt_to_bus ( priv->tcbs ); ! 1049: tcb->next = priv->tcbs; ! 1050: ! 1051: return 0; ! 1052: } ! 1053: ! 1054: /* ! 1055: * Wake up the Command Unit and issue a Resume/Start. ! 1056: * ! 1057: * @v netdev Network device containing Command Unit ! 1058: * ! 1059: * The time between clearing the S bit and issuing Resume must be as short as ! 1060: * possible to prevent a race condition. As noted in linux eepro100.c : ! 1061: * Note: Watch out for the potential race condition here: imagine ! 1062: * erasing the previous suspend ! 1063: * the chip processes the previous command ! 1064: * the chip processes the final command, and suspends ! 1065: * doing the CU_RESUME ! 1066: * the chip processes the next-yet-valid post-final-command. ! 1067: * So blindly sending a CU_RESUME is only safe if we do it immediately after ! 1068: * erasing the previous CmdSuspend, without the possibility of an intervening ! 1069: * delay. ! 1070: */ ! 1071: void ifec_tx_wake ( struct net_device *netdev ) ! 1072: { ! 1073: struct ifec_private *priv = netdev->priv; ! 1074: unsigned long ioaddr = priv->ioaddr; ! 1075: struct ifec_tcb *tcb = priv->tcb_head->next; ! 1076: ! 1077: DBGP ( "ifec_tx_wake\n" ); ! 1078: ! 1079: /* For the special case of the first transmit, we issue a START. The ! 1080: * card won't RESUME after the configure command. */ ! 1081: if ( priv->configured ) { ! 1082: priv->configured = 0; ! 1083: ifec_scb_cmd ( netdev, virt_to_bus ( tcb ), CUStart ); ! 1084: ifec_scb_cmd_wait ( netdev ); ! 1085: return; ! 1086: } ! 1087: ! 1088: /* Resume if suspended. */ ! 1089: switch ( ( inw ( ioaddr + SCBStatus ) >> 6 ) & 0x3 ) { ! 1090: case 0: /* Idle - We should not reach this state. */ ! 1091: DBG2 ( "ifec_tx_wake: tx idle!\n" ); ! 1092: ifec_scb_cmd ( netdev, virt_to_bus ( tcb ), CUStart ); ! 1093: ifec_scb_cmd_wait ( netdev ); ! 1094: return; ! 1095: case 1: /* Suspended */ ! 1096: DBG2 ( "s" ); ! 1097: break; ! 1098: default: /* Active */ ! 1099: DBG2 ( "a" ); ! 1100: } ! 1101: ifec_scb_cmd_wait ( netdev ); ! 1102: outl ( 0, ioaddr + SCBPointer ); ! 1103: priv->tcb_head->command &= ~CmdSuspend; ! 1104: /* Immediately issue Resume command */ ! 1105: outb ( CUResume, ioaddr + SCBCmd ); ! 1106: ifec_scb_cmd_wait ( netdev ); ! 1107: } ! 1108: ! 1109: /*********************************************************************/ ! 1110: ! 1111: static struct pci_device_id ifec_nics[] = { ! 1112: PCI_ROM(0x8086, 0x1029, "id1029", "Intel EtherExpressPro100 ID1029", 0), ! 1113: PCI_ROM(0x8086, 0x1030, "id1030", "Intel EtherExpressPro100 ID1030", 0), ! 1114: PCI_ROM(0x8086, 0x1031, "82801cam", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0), ! 1115: PCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection", 0), ! 1116: PCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection", 0), ! 1117: PCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection", 0), ! 1118: PCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0), ! 1119: PCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0), ! 1120: PCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0), ! 1121: PCI_ROM(0x8086, 0x1038, "id1038", "Intel PRO/100 VM Network Connection", 0), ! 1122: PCI_ROM(0x8086, 0x1039, "82562et", "Intel PRO100 VE 82562ET", 0), ! 1123: PCI_ROM(0x8086, 0x103a, "id103a", "Intel Corporation 82559 InBusiness 10/100", 0), ! 1124: PCI_ROM(0x8086, 0x103b, "82562etb", "Intel PRO100 VE 82562ETB", 0), ! 1125: PCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection", 0), ! 1126: PCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection", 0), ! 1127: PCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection", 0), ! 1128: PCI_ROM(0x8086, 0x1051, "prove", "Intel PRO/100 VE Network Connection", 0), ! 1129: PCI_ROM(0x8086, 0x1059, "82551qm", "Intel PRO/100 M Mobile Connection", 0), ! 1130: PCI_ROM(0x8086, 0x1209, "82559er", "Intel EtherExpressPro100 82559ER", 0), ! 1131: PCI_ROM(0x8086, 0x1227, "82865", "Intel 82865 EtherExpress PRO/100A", 0), ! 1132: PCI_ROM(0x8086, 0x1228, "82556", "Intel 82556 EtherExpress PRO/100 Smart", 0), ! 1133: PCI_ROM(0x8086, 0x1229, "eepro100", "Intel EtherExpressPro100", 0), ! 1134: PCI_ROM(0x8086, 0x2449, "82562em", "Intel EtherExpressPro100 82562EM", 0), ! 1135: PCI_ROM(0x8086, 0x2459, "82562-1", "Intel 82562 based Fast Ethernet Connection", 0), ! 1136: PCI_ROM(0x8086, 0x245d, "82562-2", "Intel 82562 based Fast Ethernet Connection", 0), ! 1137: PCI_ROM(0x8086, 0x1050, "82562ez", "Intel 82562EZ Network Connection", 0), ! 1138: PCI_ROM(0x8086, 0x1051, "eepro100-1051", "Intel 82801EB/ER (ICH5/ICH5R) Chipset Ethernet Controller", 0), ! 1139: PCI_ROM(0x8086, 0x1065, "82562-3", "Intel 82562 based Fast Ethernet Connection", 0), ! 1140: PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server", 0), ! 1141: PCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server", 0), ! 1142: PCI_ROM(0x8086, 0x1092, "82562-3", "Intel Pro/100 VE Network", 0), ! 1143: PCI_ROM(0x8086, 0x27dc, "eepro100-27dc", "Intel 82801G (ICH7) Chipset Ethernet Controller", 0), ! 1144: }; ! 1145: ! 1146: /* Cards with device ids 0x1030 to 0x103F, 0x2449, 0x2459 or 0x245D might need ! 1147: * a workaround for hardware bug on 10 mbit half duplex (see linux driver eepro100.c) ! 1148: * 2003/03/17 gbaum */ ! 1149: ! 1150: struct pci_driver ifec_driver __pci_driver = { ! 1151: .ids = ifec_nics, ! 1152: .id_count = ( sizeof (ifec_nics) / sizeof (ifec_nics[0]) ), ! 1153: .probe = ifec_pci_probe, ! 1154: .remove = ifec_pci_remove ! 1155: }; ! 1156: ! 1157: /* ! 1158: * Local variables: ! 1159: * c-basic-offset: 8 ! 1160: * c-indent-level: 8 ! 1161: * tab-width: 8 ! 1162: * End: ! 1163: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.