|
|
1.1 ! root 1: /* rhine.c:Fast Ethernet driver for Linux. */ ! 2: /* ! 3: Adapted 09-jan-2000 by Paolo Marini ([email protected]) ! 4: ! 5: originally written by Donald Becker. ! 6: ! 7: This software may be used and distributed according to the terms ! 8: of the GNU Public License (GPL), incorporated herein by reference. ! 9: Drivers derived from this code also fall under the GPL and must retain ! 10: this authorship and copyright notice. ! 11: ! 12: Under no circumstances are the authors responsible for ! 13: the proper functioning of this software, nor do the authors assume any ! 14: responsibility for damages incurred with its use. ! 15: ! 16: This driver is designed for the VIA VT86C100A Rhine-II PCI Fast Ethernet ! 17: controller. ! 18: ! 19: */ ! 20: ! 21: static const char *version = "rhine.c v1.0.2 2004-10-29\n"; ! 22: ! 23: /* A few user-configurable values. */ ! 24: ! 25: // max time out delay time ! 26: #define W_MAX_TIMEOUT 0x0FFFU ! 27: ! 28: /* Size of the in-memory receive ring. */ ! 29: #define RX_BUF_LEN_IDX 3 /* 0==8K, 1==16K, 2==32K, 3==64K */ ! 30: #define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) ! 31: ! 32: /* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ ! 33: #define TX_BUF_SIZE 1536 ! 34: #define RX_BUF_SIZE 1536 ! 35: ! 36: /* PCI Tuning Parameters ! 37: Threshold is bytes transferred to chip before transmission starts. */ ! 38: #define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ ! 39: ! 40: /* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. */ ! 41: #define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ ! 42: #define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ ! 43: #define TX_DMA_BURST 4 ! 44: ! 45: /* Operational parameters that usually are not changed. */ ! 46: /* Time in jiffies before concluding the transmitter is hung. */ ! 47: #define TX_TIMEOUT ((2000*HZ)/1000) ! 48: ! 49: #include "etherboot.h" ! 50: #include "nic.h" ! 51: #include <ipxe/pci.h> ! 52: #include <ipxe/ethernet.h> ! 53: ! 54: /* define all ioaddr */ ! 55: ! 56: #define byPAR0 ioaddr ! 57: #define byRCR ioaddr + 6 ! 58: #define byTCR ioaddr + 7 ! 59: #define byCR0 ioaddr + 8 ! 60: #define byCR1 ioaddr + 9 ! 61: #define byISR0 ioaddr + 0x0c ! 62: #define byISR1 ioaddr + 0x0d ! 63: #define byIMR0 ioaddr + 0x0e ! 64: #define byIMR1 ioaddr + 0x0f ! 65: #define byMAR0 ioaddr + 0x10 ! 66: #define byMAR1 ioaddr + 0x11 ! 67: #define byMAR2 ioaddr + 0x12 ! 68: #define byMAR3 ioaddr + 0x13 ! 69: #define byMAR4 ioaddr + 0x14 ! 70: #define byMAR5 ioaddr + 0x15 ! 71: #define byMAR6 ioaddr + 0x16 ! 72: #define byMAR7 ioaddr + 0x17 ! 73: #define dwCurrentRxDescAddr ioaddr + 0x18 ! 74: #define dwCurrentTxDescAddr ioaddr + 0x1c ! 75: #define dwCurrentRDSE0 ioaddr + 0x20 ! 76: #define dwCurrentRDSE1 ioaddr + 0x24 ! 77: #define dwCurrentRDSE2 ioaddr + 0x28 ! 78: #define dwCurrentRDSE3 ioaddr + 0x2c ! 79: #define dwNextRDSE0 ioaddr + 0x30 ! 80: #define dwNextRDSE1 ioaddr + 0x34 ! 81: #define dwNextRDSE2 ioaddr + 0x38 ! 82: #define dwNextRDSE3 ioaddr + 0x3c ! 83: #define dwCurrentTDSE0 ioaddr + 0x40 ! 84: #define dwCurrentTDSE1 ioaddr + 0x44 ! 85: #define dwCurrentTDSE2 ioaddr + 0x48 ! 86: #define dwCurrentTDSE3 ioaddr + 0x4c ! 87: #define dwNextTDSE0 ioaddr + 0x50 ! 88: #define dwNextTDSE1 ioaddr + 0x54 ! 89: #define dwNextTDSE2 ioaddr + 0x58 ! 90: #define dwNextTDSE3 ioaddr + 0x5c ! 91: #define dwCurrRxDMAPtr ioaddr + 0x60 ! 92: #define dwCurrTxDMAPtr ioaddr + 0x64 ! 93: #define byMPHY ioaddr + 0x6c ! 94: #define byMIISR ioaddr + 0x6d ! 95: #define byBCR0 ioaddr + 0x6e ! 96: #define byBCR1 ioaddr + 0x6f ! 97: #define byMIICR ioaddr + 0x70 ! 98: #define byMIIAD ioaddr + 0x71 ! 99: #define wMIIDATA ioaddr + 0x72 ! 100: #define byEECSR ioaddr + 0x74 ! 101: #define byTEST ioaddr + 0x75 ! 102: #define byGPIO ioaddr + 0x76 ! 103: #define byCFGA ioaddr + 0x78 ! 104: #define byCFGB ioaddr + 0x79 ! 105: #define byCFGC ioaddr + 0x7a ! 106: #define byCFGD ioaddr + 0x7b ! 107: #define wTallyCntMPA ioaddr + 0x7c ! 108: #define wTallyCntCRC ioaddr + 0x7d ! 109: #define bySTICKHW ioaddr + 0x83 ! 110: #define byWOLcrClr ioaddr + 0xA4 ! 111: #define byWOLcgClr ioaddr + 0xA7 ! 112: #define byPwrcsrClr ioaddr + 0xAC ! 113: ! 114: /*--------------------- Exioaddr Definitions -------------------------*/ ! 115: ! 116: /* ! 117: * Bits in the RCR register ! 118: */ ! 119: ! 120: #define RCR_RRFT2 0x80 ! 121: #define RCR_RRFT1 0x40 ! 122: #define RCR_RRFT0 0x20 ! 123: #define RCR_PROM 0x10 ! 124: #define RCR_AB 0x08 ! 125: #define RCR_AM 0x04 ! 126: #define RCR_AR 0x02 ! 127: #define RCR_SEP 0x01 ! 128: ! 129: /* ! 130: * Bits in the TCR register ! 131: */ ! 132: ! 133: #define TCR_RTSF 0x80 ! 134: #define TCR_RTFT1 0x40 ! 135: #define TCR_RTFT0 0x20 ! 136: #define TCR_OFSET 0x08 ! 137: #define TCR_LB1 0x04 /* loopback[1] */ ! 138: #define TCR_LB0 0x02 /* loopback[0] */ ! 139: ! 140: /* ! 141: * Bits in the CR0 register ! 142: */ ! 143: ! 144: #define CR0_RDMD 0x40 /* rx descriptor polling demand */ ! 145: #define CR0_TDMD 0x20 /* tx descriptor polling demand */ ! 146: #define CR0_TXON 0x10 ! 147: #define CR0_RXON 0x08 ! 148: #define CR0_STOP 0x04 /* stop NIC, default = 1 */ ! 149: #define CR0_STRT 0x02 /* start NIC */ ! 150: #define CR0_INIT 0x01 /* start init process */ ! 151: ! 152: ! 153: /* ! 154: * Bits in the CR1 register ! 155: */ ! 156: ! 157: #define CR1_SFRST 0x80 /* software reset */ ! 158: #define CR1_RDMD1 0x40 /* RDMD1 */ ! 159: #define CR1_TDMD1 0x20 /* TDMD1 */ ! 160: #define CR1_KEYPAG 0x10 /* turn on par/key */ ! 161: #define CR1_DPOLL 0x08 /* disable rx/tx auto polling */ ! 162: #define CR1_FDX 0x04 /* full duplex mode */ ! 163: #define CR1_ETEN 0x02 /* early tx mode */ ! 164: #define CR1_EREN 0x01 /* early rx mode */ ! 165: ! 166: /* ! 167: * Bits in the CR register ! 168: */ ! 169: ! 170: #define CR_RDMD 0x0040 /* rx descriptor polling demand */ ! 171: #define CR_TDMD 0x0020 /* tx descriptor polling demand */ ! 172: #define CR_TXON 0x0010 ! 173: #define CR_RXON 0x0008 ! 174: #define CR_STOP 0x0004 /* stop NIC, default = 1 */ ! 175: #define CR_STRT 0x0002 /* start NIC */ ! 176: #define CR_INIT 0x0001 /* start init process */ ! 177: #define CR_SFRST 0x8000 /* software reset */ ! 178: #define CR_RDMD1 0x4000 /* RDMD1 */ ! 179: #define CR_TDMD1 0x2000 /* TDMD1 */ ! 180: #define CR_KEYPAG 0x1000 /* turn on par/key */ ! 181: #define CR_DPOLL 0x0800 /* disable rx/tx auto polling */ ! 182: #define CR_FDX 0x0400 /* full duplex mode */ ! 183: #define CR_ETEN 0x0200 /* early tx mode */ ! 184: #define CR_EREN 0x0100 /* early rx mode */ ! 185: ! 186: /* ! 187: * Bits in the IMR0 register ! 188: */ ! 189: ! 190: #define IMR0_CNTM 0x80 ! 191: #define IMR0_BEM 0x40 ! 192: #define IMR0_RUM 0x20 ! 193: #define IMR0_TUM 0x10 ! 194: #define IMR0_TXEM 0x08 ! 195: #define IMR0_RXEM 0x04 ! 196: #define IMR0_PTXM 0x02 ! 197: #define IMR0_PRXM 0x01 ! 198: ! 199: /* define imrshadow */ ! 200: ! 201: #define IMRShadow 0x5AFF ! 202: ! 203: /* ! 204: * Bits in the IMR1 register ! 205: */ ! 206: ! 207: #define IMR1_INITM 0x80 ! 208: #define IMR1_SRCM 0x40 ! 209: #define IMR1_NBFM 0x10 ! 210: #define IMR1_PRAIM 0x08 ! 211: #define IMR1_RES0M 0x04 ! 212: #define IMR1_ETM 0x02 ! 213: #define IMR1_ERM 0x01 ! 214: ! 215: /* ! 216: * Bits in the ISR register ! 217: */ ! 218: ! 219: #define ISR_INITI 0x8000 ! 220: #define ISR_SRCI 0x4000 ! 221: #define ISR_ABTI 0x2000 ! 222: #define ISR_NORBF 0x1000 ! 223: #define ISR_PKTRA 0x0800 ! 224: #define ISR_RES0 0x0400 ! 225: #define ISR_ETI 0x0200 ! 226: #define ISR_ERI 0x0100 ! 227: #define ISR_CNT 0x0080 ! 228: #define ISR_BE 0x0040 ! 229: #define ISR_RU 0x0020 ! 230: #define ISR_TU 0x0010 ! 231: #define ISR_TXE 0x0008 ! 232: #define ISR_RXE 0x0004 ! 233: #define ISR_PTX 0x0002 ! 234: #define ISR_PRX 0x0001 ! 235: ! 236: /* ! 237: * Bits in the ISR0 register ! 238: */ ! 239: ! 240: #define ISR0_CNT 0x80 ! 241: #define ISR0_BE 0x40 ! 242: #define ISR0_RU 0x20 ! 243: #define ISR0_TU 0x10 ! 244: #define ISR0_TXE 0x08 ! 245: #define ISR0_RXE 0x04 ! 246: #define ISR0_PTX 0x02 ! 247: #define ISR0_PRX 0x01 ! 248: ! 249: /* ! 250: * Bits in the ISR1 register ! 251: */ ! 252: ! 253: #define ISR1_INITI 0x80 ! 254: #define ISR1_SRCI 0x40 ! 255: #define ISR1_NORBF 0x10 ! 256: #define ISR1_PKTRA 0x08 ! 257: #define ISR1_ETI 0x02 ! 258: #define ISR1_ERI 0x01 ! 259: ! 260: /* ISR ABNORMAL CONDITION */ ! 261: ! 262: #define ISR_ABNORMAL ISR_BE+ISR_RU+ISR_TU+ISR_CNT+ISR_NORBF+ISR_PKTRA ! 263: ! 264: /* ! 265: * Bits in the MIISR register ! 266: */ ! 267: ! 268: #define MIISR_MIIERR 0x08 ! 269: #define MIISR_MRERR 0x04 ! 270: #define MIISR_LNKFL 0x02 ! 271: #define MIISR_SPEED 0x01 ! 272: ! 273: /* ! 274: * Bits in the MIICR register ! 275: */ ! 276: ! 277: #define MIICR_MAUTO 0x80 ! 278: #define MIICR_RCMD 0x40 ! 279: #define MIICR_WCMD 0x20 ! 280: #define MIICR_MDPM 0x10 ! 281: #define MIICR_MOUT 0x08 ! 282: #define MIICR_MDO 0x04 ! 283: #define MIICR_MDI 0x02 ! 284: #define MIICR_MDC 0x01 ! 285: ! 286: /* ! 287: * Bits in the EECSR register ! 288: */ ! 289: ! 290: #define EECSR_EEPR 0x80 /* eeprom programed status, 73h means programed */ ! 291: #define EECSR_EMBP 0x40 /* eeprom embeded programming */ ! 292: #define EECSR_AUTOLD 0x20 /* eeprom content reload */ ! 293: #define EECSR_DPM 0x10 /* eeprom direct programming */ ! 294: #define EECSR_CS 0x08 /* eeprom CS pin */ ! 295: #define EECSR_SK 0x04 /* eeprom SK pin */ ! 296: #define EECSR_DI 0x02 /* eeprom DI pin */ ! 297: #define EECSR_DO 0x01 /* eeprom DO pin */ ! 298: ! 299: /* ! 300: * Bits in the BCR0 register ! 301: */ ! 302: ! 303: #define BCR0_CRFT2 0x20 ! 304: #define BCR0_CRFT1 0x10 ! 305: #define BCR0_CRFT0 0x08 ! 306: #define BCR0_DMAL2 0x04 ! 307: #define BCR0_DMAL1 0x02 ! 308: #define BCR0_DMAL0 0x01 ! 309: ! 310: /* ! 311: * Bits in the BCR1 register ! 312: */ ! 313: ! 314: #define BCR1_CTSF 0x20 ! 315: #define BCR1_CTFT1 0x10 ! 316: #define BCR1_CTFT0 0x08 ! 317: #define BCR1_POT2 0x04 ! 318: #define BCR1_POT1 0x02 ! 319: #define BCR1_POT0 0x01 ! 320: ! 321: /* ! 322: * Bits in the CFGA register ! 323: */ ! 324: ! 325: #define CFGA_EELOAD 0x80 /* enable eeprom embeded and direct programming */ ! 326: #define CFGA_JUMPER 0x40 ! 327: #define CFGA_MTGPIO 0x08 ! 328: #define CFGA_T10EN 0x02 ! 329: #define CFGA_AUTO 0x01 ! 330: ! 331: /* ! 332: * Bits in the CFGB register ! 333: */ ! 334: ! 335: #define CFGB_PD 0x80 ! 336: #define CFGB_POLEN 0x02 ! 337: #define CFGB_LNKEN 0x01 ! 338: ! 339: /* ! 340: * Bits in the CFGC register ! 341: */ ! 342: ! 343: #define CFGC_M10TIO 0x80 ! 344: #define CFGC_M10POL 0x40 ! 345: #define CFGC_PHY1 0x20 ! 346: #define CFGC_PHY0 0x10 ! 347: #define CFGC_BTSEL 0x08 ! 348: #define CFGC_BPS2 0x04 /* bootrom select[2] */ ! 349: #define CFGC_BPS1 0x02 /* bootrom select[1] */ ! 350: #define CFGC_BPS0 0x01 /* bootrom select[0] */ ! 351: ! 352: /* ! 353: * Bits in the CFGD register ! 354: */ ! 355: ! 356: #define CFGD_GPIOEN 0x80 ! 357: #define CFGD_DIAG 0x40 ! 358: #define CFGD_MAGIC 0x10 ! 359: #define CFGD_RANDOM 0x08 ! 360: #define CFGD_CFDX 0x04 ! 361: #define CFGD_CEREN 0x02 ! 362: #define CFGD_CETEN 0x01 ! 363: ! 364: /* Bits in RSR */ ! 365: #define RSR_RERR 0x00000001 ! 366: #define RSR_CRC 0x00000002 ! 367: #define RSR_FAE 0x00000004 ! 368: #define RSR_FOV 0x00000008 ! 369: #define RSR_LONG 0x00000010 ! 370: #define RSR_RUNT 0x00000020 ! 371: #define RSR_SERR 0x00000040 ! 372: #define RSR_BUFF 0x00000080 ! 373: #define RSR_EDP 0x00000100 ! 374: #define RSR_STP 0x00000200 ! 375: #define RSR_CHN 0x00000400 ! 376: #define RSR_PHY 0x00000800 ! 377: #define RSR_BAR 0x00001000 ! 378: #define RSR_MAR 0x00002000 ! 379: #define RSR_RXOK 0x00008000 ! 380: #define RSR_ABNORMAL RSR_RERR+RSR_LONG+RSR_RUNT ! 381: ! 382: /* Bits in TSR */ ! 383: #define TSR_NCR0 0x00000001 ! 384: #define TSR_NCR1 0x00000002 ! 385: #define TSR_NCR2 0x00000004 ! 386: #define TSR_NCR3 0x00000008 ! 387: #define TSR_COLS 0x00000010 ! 388: #define TSR_CDH 0x00000080 ! 389: #define TSR_ABT 0x00000100 ! 390: #define TSR_OWC 0x00000200 ! 391: #define TSR_CRS 0x00000400 ! 392: #define TSR_UDF 0x00000800 ! 393: #define TSR_TBUFF 0x00001000 ! 394: #define TSR_SERR 0x00002000 ! 395: #define TSR_JAB 0x00004000 ! 396: #define TSR_TERR 0x00008000 ! 397: #define TSR_ABNORMAL TSR_TERR+TSR_OWC+TSR_ABT+TSR_JAB+TSR_CRS ! 398: #define TSR_OWN_BIT 0x80000000 ! 399: ! 400: #define CB_DELAY_LOOP_WAIT 10 /* 10ms */ ! 401: /* enabled mask value of irq */ ! 402: ! 403: #define W_IMR_MASK_VALUE 0x1BFF /* initial value of IMR */ ! 404: ! 405: /* Ethernet address filter type */ ! 406: #define PKT_TYPE_DIRECTED 0x0001 /* obsolete, directed address is always accepted */ ! 407: #define PKT_TYPE_MULTICAST 0x0002 ! 408: #define PKT_TYPE_ALL_MULTICAST 0x0004 ! 409: #define PKT_TYPE_BROADCAST 0x0008 ! 410: #define PKT_TYPE_PROMISCUOUS 0x0020 ! 411: #define PKT_TYPE_LONG 0x2000 ! 412: #define PKT_TYPE_RUNT 0x4000 ! 413: #define PKT_TYPE_ERROR 0x8000 /* accept error packets, e.g. CRC error */ ! 414: ! 415: /* Loopback mode */ ! 416: ! 417: #define NIC_LB_NONE 0x00 ! 418: #define NIC_LB_INTERNAL 0x01 ! 419: #define NIC_LB_PHY 0x02 /* MII or Internal-10BaseT loopback */ ! 420: ! 421: #define TX_RING_SIZE 2 ! 422: #define RX_RING_SIZE 2 ! 423: #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ ! 424: ! 425: #define PCI_REG_MODE3 0x53 ! 426: #define MODE3_MIION 0x04 /* in PCI_REG_MOD3 OF PCI space */ ! 427: ! 428: enum rhine_revs { ! 429: VT86C100A = 0x00, ! 430: VTunknown0 = 0x20, ! 431: VT6102 = 0x40, ! 432: VT8231 = 0x50, /* Integrated MAC */ ! 433: VT8233 = 0x60, /* Integrated MAC */ ! 434: VT8235 = 0x74, /* Integrated MAC */ ! 435: VT8237 = 0x78, /* Integrated MAC */ ! 436: VTunknown1 = 0x7C, ! 437: VT6105 = 0x80, ! 438: VT6105_B0 = 0x83, ! 439: VT6105L = 0x8A, ! 440: VT6107 = 0x8C, ! 441: VTunknown2 = 0x8E, ! 442: VT6105M = 0x90, ! 443: }; ! 444: ! 445: /* Transmit and receive descriptors definition */ ! 446: ! 447: struct rhine_tx_desc ! 448: { ! 449: union VTC_tx_status_tag ! 450: { ! 451: struct ! 452: { ! 453: unsigned long ncro:1; ! 454: unsigned long ncr1:1; ! 455: unsigned long ncr2:1; ! 456: unsigned long ncr3:1; ! 457: unsigned long cols:1; ! 458: unsigned long reserve_1:2; ! 459: unsigned long cdh:1; ! 460: unsigned long abt:1; ! 461: unsigned long owc:1; ! 462: unsigned long crs:1; ! 463: unsigned long udf:1; ! 464: unsigned long tbuff:1; ! 465: unsigned long serr:1; ! 466: unsigned long jab:1; ! 467: unsigned long terr:1; ! 468: unsigned long reserve_2:15; ! 469: unsigned long own_bit:1; ! 470: } ! 471: bits; ! 472: unsigned long lw; ! 473: } ! 474: tx_status; ! 475: ! 476: union VTC_tx_ctrl_tag ! 477: { ! 478: struct ! 479: { ! 480: unsigned long tx_buf_size:11; ! 481: unsigned long extend_tx_buf_size:4; ! 482: unsigned long chn:1; ! 483: unsigned long crc:1; ! 484: unsigned long reserve_1:4; ! 485: unsigned long stp:1; ! 486: unsigned long edp:1; ! 487: unsigned long ic:1; ! 488: unsigned long reserve_2:8; ! 489: } ! 490: bits; ! 491: unsigned long lw; ! 492: } ! 493: tx_ctrl; ! 494: ! 495: unsigned long buf_addr_1:32; ! 496: unsigned long buf_addr_2:32; ! 497: ! 498: }; ! 499: ! 500: struct rhine_rx_desc ! 501: { ! 502: union VTC_rx_status_tag ! 503: { ! 504: struct ! 505: { ! 506: unsigned long rerr:1; ! 507: unsigned long crc_error:1; ! 508: unsigned long fae:1; ! 509: unsigned long fov:1; ! 510: unsigned long toolong:1; ! 511: unsigned long runt:1; ! 512: unsigned long serr:1; ! 513: unsigned long buff:1; ! 514: unsigned long edp:1; ! 515: unsigned long stp:1; ! 516: unsigned long chn:1; ! 517: unsigned long phy:1; ! 518: unsigned long bar:1; ! 519: unsigned long mar:1; ! 520: unsigned long reserve_1:1; ! 521: unsigned long rxok:1; ! 522: unsigned long frame_length:11; ! 523: unsigned long reverve_2:4; ! 524: unsigned long own_bit:1; ! 525: } ! 526: bits; ! 527: unsigned long lw; ! 528: } ! 529: rx_status; ! 530: ! 531: union VTC_rx_ctrl_tag ! 532: { ! 533: struct ! 534: { ! 535: unsigned long rx_buf_size:11; ! 536: unsigned long extend_rx_buf_size:4; ! 537: unsigned long reserved_1:17; ! 538: } ! 539: bits; ! 540: unsigned long lw; ! 541: } ! 542: rx_ctrl; ! 543: ! 544: unsigned long buf_addr_1:32; ! 545: unsigned long buf_addr_2:32; ! 546: ! 547: }; ! 548: ! 549: struct { ! 550: char txbuf[TX_RING_SIZE * PKT_BUF_SZ + 32]; ! 551: char rxbuf[RX_RING_SIZE * PKT_BUF_SZ + 32]; ! 552: char txdesc[TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32]; ! 553: char rxdesc[RX_RING_SIZE * sizeof (struct rhine_rx_desc) + 32]; ! 554: } rhine_buffers __shared; ! 555: ! 556: /* The I/O extent. */ ! 557: #define rhine_TOTAL_SIZE 0x80 ! 558: ! 559: #ifdef HAVE_DEVLIST ! 560: struct netdev_entry rhine_drv = ! 561: { "rhine", rhine_probe, rhine_TOTAL_SIZE, NULL }; ! 562: #endif ! 563: ! 564: static int rhine_debug = 1; ! 565: ! 566: /* ! 567: Theory of Operation ! 568: ! 569: I. Board Compatibility ! 570: ! 571: This driver is designed for the VIA 86c100A Rhine-II PCI Fast Ethernet ! 572: controller. ! 573: ! 574: II. Board-specific settings ! 575: ! 576: Boards with this chip are functional only in a bus-master PCI slot. ! 577: ! 578: Many operational settings are loaded from the EEPROM to the Config word at ! 579: offset 0x78. This driver assumes that they are correct. ! 580: If this driver is compiled to use PCI memory space operations the EEPROM ! 581: must be configured to enable memory ops. ! 582: ! 583: III. Driver operation ! 584: ! 585: IIIa. Ring buffers ! 586: ! 587: This driver uses two statically allocated fixed-size descriptor lists ! 588: formed into rings by a branch from the final descriptor to the beginning of ! 589: the list. The ring sizes are set at compile time by RX/TX_RING_SIZE. ! 590: ! 591: IIIb/c. Transmit/Receive Structure ! 592: ! 593: This driver attempts to use a zero-copy receive and transmit scheme. ! 594: ! 595: Alas, all data buffers are required to start on a 32 bit boundary, so ! 596: the driver must often copy transmit packets into bounce buffers. ! 597: ! 598: The driver allocates full frame size skbuffs for the Rx ring buffers at ! 599: open() time and passes the skb->data field to the chip as receive data ! 600: buffers. When an incoming frame is less than RX_COPYBREAK bytes long, ! 601: a fresh skbuff is allocated and the frame is copied to the new skbuff. ! 602: When the incoming frame is larger, the skbuff is passed directly up the ! 603: protocol stack. Buffers consumed this way are replaced by newly allocated ! 604: skbuffs in the last phase of netdev_rx(). ! 605: ! 606: The RX_COPYBREAK value is chosen to trade-off the memory wasted by ! 607: using a full-sized skbuff for small frames vs. the copying costs of larger ! 608: frames. New boards are typically used in generously configured machines ! 609: and the underfilled buffers have negligible impact compared to the benefit of ! 610: a single allocation size, so the default value of zero results in never ! 611: copying packets. When copying is done, the cost is usually mitigated by using ! 612: a combined copy/checksum routine. Copying also preloads the cache, which is ! 613: most useful with small frames. ! 614: ! 615: Since the VIA chips are only able to transfer data to buffers on 32 bit ! 616: boundaries, the the IP header at offset 14 in an ethernet frame isn't ! 617: longword aligned for further processing. Copying these unaligned buffers ! 618: has the beneficial effect of 16-byte aligning the IP header. ! 619: ! 620: IIId. Synchronization ! 621: ! 622: The driver runs as two independent, single-threaded flows of control. One ! 623: is the send-packet routine, which enforces single-threaded use by the ! 624: dev->tbusy flag. The other thread is the interrupt handler, which is single ! 625: threaded by the hardware and interrupt handling software. ! 626: ! 627: The send packet thread has partial control over the Tx ring and 'dev->tbusy' ! 628: flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next ! 629: queue slot is empty, it clears the tbusy flag when finished otherwise it sets ! 630: the 'lp->tx_full' flag. ! 631: ! 632: The interrupt handler has exclusive control over the Rx ring and records stats ! 633: from the Tx ring. After reaping the stats, it marks the Tx queue entry as ! 634: empty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, it ! 635: clears both the tx_full and tbusy flags. ! 636: ! 637: IV. Notes ! 638: ! 639: IVb. References ! 640: ! 641: Preliminary VT86C100A manual from http://www.via.com.tw/ ! 642: http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html ! 643: http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html ! 644: ! 645: IVc. Errata ! 646: ! 647: The VT86C100A manual is not reliable information. ! 648: The chip does not handle unaligned transmit or receive buffers, resulting ! 649: in significant performance degradation for bounce buffer copies on transmit ! 650: and unaligned IP headers on receive. ! 651: The chip does not pad to minimum transmit length. ! 652: ! 653: */ ! 654: ! 655: /* The rest of these values should never change. */ ! 656: #define NUM_TX_DESC 2 /* Number of Tx descriptor registers. */ ! 657: ! 658: static struct rhine_private ! 659: { ! 660: char devname[8]; /* Used only for kernel debugging. */ ! 661: const char *product_name; ! 662: struct rhine_rx_desc *rx_ring; ! 663: struct rhine_tx_desc *tx_ring; ! 664: char *rx_buffs[RX_RING_SIZE]; ! 665: char *tx_buffs[TX_RING_SIZE]; ! 666: ! 667: /* temporary Rx buffers. */ ! 668: ! 669: int chip_id; ! 670: int chip_revision; ! 671: unsigned short ioaddr; ! 672: unsigned int cur_rx, cur_tx; /* The next free and used entries */ ! 673: unsigned int dirty_rx, dirty_tx; ! 674: /* The saved address of a sent-in-place packet/buffer, for skfree(). */ ! 675: struct sk_buff *tx_skbuff[TX_RING_SIZE]; ! 676: unsigned char mc_filter[8]; /* Current multicast filter. */ ! 677: char phys[4]; /* MII device addresses. */ ! 678: unsigned int tx_full:1; /* The Tx queue is full. */ ! 679: unsigned int full_duplex:1; /* Full-duplex operation requested. */ ! 680: unsigned int default_port:4; /* Last dev->if_port value. */ ! 681: unsigned int media2:4; /* Secondary monitored media port. */ ! 682: unsigned int medialock:1; /* Don't sense media type. */ ! 683: unsigned int mediasense:1; /* Media sensing in progress. */ ! 684: } ! 685: rhine; ! 686: ! 687: static void rhine_probe1 (struct nic *nic, struct pci_device *pci, int ioaddr, ! 688: int chip_id, int options); ! 689: static int QueryAuto (int); ! 690: static int ReadMII (int byMIIIndex, int); ! 691: static void WriteMII (char, char, char, int); ! 692: static void MIIDelay (void); ! 693: static void rhine_init_ring (struct nic *dev); ! 694: static void rhine_disable (struct nic *nic); ! 695: static void rhine_reset (struct nic *nic); ! 696: static int rhine_poll (struct nic *nic, int retreive); ! 697: static void rhine_transmit (struct nic *nic, const char *d, unsigned int t, ! 698: unsigned int s, const char *p); ! 699: static void reload_eeprom(int ioaddr); ! 700: ! 701: ! 702: static void reload_eeprom(int ioaddr) ! 703: { ! 704: int i; ! 705: outb(0x20, byEECSR); ! 706: /* Typically 2 cycles to reload. */ ! 707: for (i = 0; i < 150; i++) ! 708: if (! (inb(byEECSR) & 0x20)) ! 709: break; ! 710: } ! 711: /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ ! 712: static void ! 713: rhine_init_ring (struct nic *nic) ! 714: { ! 715: struct rhine_private *tp = (struct rhine_private *) nic->priv_data; ! 716: int i; ! 717: ! 718: tp->tx_full = 0; ! 719: tp->cur_rx = tp->cur_tx = 0; ! 720: tp->dirty_rx = tp->dirty_tx = 0; ! 721: ! 722: for (i = 0; i < RX_RING_SIZE; i++) ! 723: { ! 724: ! 725: tp->rx_ring[i].rx_status.bits.own_bit = 1; ! 726: tp->rx_ring[i].rx_ctrl.bits.rx_buf_size = 1536; ! 727: ! 728: tp->rx_ring[i].buf_addr_1 = virt_to_bus (tp->rx_buffs[i]); ! 729: tp->rx_ring[i].buf_addr_2 = virt_to_bus (&tp->rx_ring[i + 1]); ! 730: /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->rx_ring[i].buf_addr_1,tp->rx_ring[i].buf_addr_2); */ ! 731: } ! 732: /* Mark the last entry as wrapping the ring. */ ! 733: /* tp->rx_ring[i-1].rx_ctrl.bits.rx_buf_size =1518; */ ! 734: tp->rx_ring[i - 1].buf_addr_2 = virt_to_bus (&tp->rx_ring[0]); ! 735: /*printf("[%d]buf1=%hX,buf2=%hX",i-1,tp->rx_ring[i-1].buf_addr_1,tp->rx_ring[i-1].buf_addr_2); */ ! 736: ! 737: /* The Tx buffer descriptor is filled in as needed, but we ! 738: do need to clear the ownership bit. */ ! 739: ! 740: for (i = 0; i < TX_RING_SIZE; i++) ! 741: { ! 742: ! 743: tp->tx_ring[i].tx_status.lw = 0; ! 744: tp->tx_ring[i].tx_ctrl.lw = 0x00e08000; ! 745: tp->tx_ring[i].buf_addr_1 = virt_to_bus (tp->tx_buffs[i]); ! 746: tp->tx_ring[i].buf_addr_2 = virt_to_bus (&tp->tx_ring[i + 1]); ! 747: /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->tx_ring[i].buf_addr_1,tp->tx_ring[i].buf_addr_2); */ ! 748: } ! 749: ! 750: tp->tx_ring[i - 1].buf_addr_2 = virt_to_bus (&tp->tx_ring[0]); ! 751: /* printf("[%d]buf1=%hX,buf2=%hX",i,tp->tx_ring[i-1].buf_addr_1,tp->tx_ring[i-1].buf_addr_2); */ ! 752: } ! 753: ! 754: int ! 755: QueryAuto (int ioaddr) ! 756: { ! 757: int byMIIIndex; ! 758: int MIIReturn; ! 759: ! 760: int advertising,mii_reg5; ! 761: int negociated; ! 762: ! 763: byMIIIndex = 0x04; ! 764: MIIReturn = ReadMII (byMIIIndex, ioaddr); ! 765: advertising=MIIReturn; ! 766: ! 767: byMIIIndex = 0x05; ! 768: MIIReturn = ReadMII (byMIIIndex, ioaddr); ! 769: mii_reg5=MIIReturn; ! 770: ! 771: negociated=mii_reg5 & advertising; ! 772: ! 773: if ( (negociated & 0x100) || (negociated & 0x1C0) == 0x40 ) ! 774: return 1; ! 775: else ! 776: return 0; ! 777: ! 778: } ! 779: ! 780: int ! 781: ReadMII (int byMIIIndex, int ioaddr) ! 782: { ! 783: int ReturnMII; ! 784: char byMIIAdrbak; ! 785: char byMIICRbak; ! 786: char byMIItemp; ! 787: unsigned long ct; ! 788: ! 789: byMIIAdrbak = inb (byMIIAD); ! 790: byMIICRbak = inb (byMIICR); ! 791: outb (byMIICRbak & 0x7f, byMIICR); ! 792: MIIDelay (); ! 793: ! 794: outb (byMIIIndex, byMIIAD); ! 795: MIIDelay (); ! 796: ! 797: outb (inb (byMIICR) | 0x40, byMIICR); ! 798: ! 799: byMIItemp = inb (byMIICR); ! 800: byMIItemp = byMIItemp & 0x40; ! 801: ! 802: ct = currticks(); ! 803: while (byMIItemp != 0 && ct + 2*1000 < currticks()) ! 804: { ! 805: byMIItemp = inb (byMIICR); ! 806: byMIItemp = byMIItemp & 0x40; ! 807: } ! 808: MIIDelay (); ! 809: ! 810: ReturnMII = inw (wMIIDATA); ! 811: ! 812: outb (byMIIAdrbak, byMIIAD); ! 813: outb (byMIICRbak, byMIICR); ! 814: MIIDelay (); ! 815: ! 816: return (ReturnMII); ! 817: ! 818: } ! 819: ! 820: void ! 821: WriteMII (char byMIISetByte, char byMIISetBit, char byMIIOP, int ioaddr) ! 822: { ! 823: int ReadMIItmp; ! 824: int MIIMask; ! 825: char byMIIAdrbak; ! 826: char byMIICRbak; ! 827: char byMIItemp; ! 828: unsigned long ct; ! 829: ! 830: ! 831: byMIIAdrbak = inb (byMIIAD); ! 832: ! 833: byMIICRbak = inb (byMIICR); ! 834: outb (byMIICRbak & 0x7f, byMIICR); ! 835: MIIDelay (); ! 836: outb (byMIISetByte, byMIIAD); ! 837: MIIDelay (); ! 838: ! 839: outb (inb (byMIICR) | 0x40, byMIICR); ! 840: ! 841: byMIItemp = inb (byMIICR); ! 842: byMIItemp = byMIItemp & 0x40; ! 843: ! 844: ct = currticks(); ! 845: while (byMIItemp != 0 && ct + 2*1000 < currticks()) ! 846: { ! 847: byMIItemp = inb (byMIICR); ! 848: byMIItemp = byMIItemp & 0x40; ! 849: } ! 850: MIIDelay (); ! 851: ! 852: ReadMIItmp = inw (wMIIDATA); ! 853: MIIMask = 0x0001; ! 854: MIIMask = MIIMask << byMIISetBit; ! 855: ! 856: ! 857: if (byMIIOP == 0) ! 858: { ! 859: MIIMask = ~MIIMask; ! 860: ReadMIItmp = ReadMIItmp & MIIMask; ! 861: } ! 862: else ! 863: { ! 864: ReadMIItmp = ReadMIItmp | MIIMask; ! 865: ! 866: } ! 867: outw (ReadMIItmp, wMIIDATA); ! 868: MIIDelay (); ! 869: ! 870: outb (inb (byMIICR) | 0x20, byMIICR); ! 871: byMIItemp = inb (byMIICR); ! 872: byMIItemp = byMIItemp & 0x20; ! 873: ! 874: ct = currticks(); ! 875: while (byMIItemp != 0 && ct + 2*1000 < currticks()) ! 876: { ! 877: byMIItemp = inb (byMIICR); ! 878: byMIItemp = byMIItemp & 0x20; ! 879: } ! 880: MIIDelay (); ! 881: ! 882: outb (byMIIAdrbak & 0x7f, byMIIAD); ! 883: outb (byMIICRbak, byMIICR); ! 884: MIIDelay (); ! 885: ! 886: } ! 887: ! 888: void ! 889: MIIDelay (void) ! 890: { ! 891: int i; ! 892: for (i = 0; i < 0x7fff; i++) ! 893: { ! 894: ( void ) inb (0x61); ! 895: ( void ) inb (0x61); ! 896: ( void ) inb (0x61); ! 897: ( void ) inb (0x61); ! 898: } ! 899: } ! 900: ! 901: /* Offsets to the device registers. */ ! 902: enum register_offsets { ! 903: StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08, ! 904: IntrStatus=0x0C, IntrEnable=0x0E, ! 905: MulticastFilter0=0x10, MulticastFilter1=0x14, ! 906: RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54, ! 907: MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E, ! 908: MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74, ! 909: ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B, ! 910: RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81, ! 911: StickyHW=0x83, IntrStatus2=0x84, WOLcrClr=0xA4, WOLcgClr=0xA7, ! 912: PwrcsrClr=0xAC, ! 913: }; ! 914: ! 915: /* Bits in the interrupt status/mask registers. */ ! 916: enum intr_status_bits { ! 917: IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020, ! 918: IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210, ! 919: IntrPCIErr=0x0040, ! 920: IntrStatsMax=0x0080, IntrRxEarly=0x0100, ! 921: IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000, ! 922: IntrTxAborted=0x2000, IntrLinkChange=0x4000, ! 923: IntrRxWakeUp=0x8000, ! 924: IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260, ! 925: IntrTxDescRace=0x080000, /* mapped from IntrStatus2 */ ! 926: IntrTxErrSummary=0x082218, ! 927: }; ! 928: #define DEFAULT_INTR (IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | \ ! 929: IntrRxDropped | IntrRxNoBuf) ! 930: ! 931: /*************************************************************************** ! 932: IRQ - PXE IRQ Handler ! 933: ***************************************************************************/ ! 934: void rhine_irq ( struct nic *nic, irq_action_t action ) { ! 935: struct rhine_private *tp = (struct rhine_private *) nic->priv_data; ! 936: /* Enable interrupts by setting the interrupt mask. */ ! 937: unsigned int intr_status; ! 938: ! 939: switch ( action ) { ! 940: case DISABLE : ! 941: case ENABLE : ! 942: intr_status = inw(nic->ioaddr + IntrStatus); ! 943: /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */ ! 944: ! 945: /* added comment by guard */ ! 946: /* For supporting VT6107, please use revision id to recognize different chips in driver */ ! 947: // if (tp->chip_id == 0x3065) ! 948: if( tp->chip_revision < 0x80 && tp->chip_revision >=0x40 ) ! 949: intr_status |= inb(nic->ioaddr + IntrStatus2) << 16; ! 950: intr_status = (intr_status & ~DEFAULT_INTR); ! 951: if ( action == ENABLE ) ! 952: intr_status = intr_status | DEFAULT_INTR; ! 953: outw(intr_status, nic->ioaddr + IntrEnable); ! 954: break; ! 955: case FORCE : ! 956: outw(0x0010, nic->ioaddr + 0x84); ! 957: break; ! 958: } ! 959: } ! 960: ! 961: static struct nic_operations rhine_operations; ! 962: ! 963: static int ! 964: rhine_probe ( struct nic *nic, struct pci_device *pci ) { ! 965: ! 966: struct rhine_private *tp = (struct rhine_private *) nic->priv_data; ! 967: ! 968: if (!pci->ioaddr) ! 969: return 0; ! 970: ! 971: rhine_probe1 (nic, pci, pci->ioaddr, pci->device, -1); ! 972: ! 973: adjust_pci_device ( pci ); ! 974: ! 975: rhine_reset (nic); ! 976: ! 977: nic->nic_op = &rhine_operations; ! 978: ! 979: nic->irqno = pci->irq; ! 980: nic->ioaddr = tp->ioaddr; ! 981: ! 982: return 1; ! 983: } ! 984: ! 985: static void set_rx_mode(struct nic *nic __unused) { ! 986: struct rhine_private *tp = (struct rhine_private *) nic->priv_data; ! 987: unsigned char rx_mode; ! 988: int ioaddr = tp->ioaddr; ! 989: ! 990: /* ! IFF_PROMISC */ ! 991: outl(0xffffffff, byMAR0); ! 992: outl(0xffffffff, byMAR4); ! 993: rx_mode = 0x0C; ! 994: ! 995: outb(0x60 /* thresh */ | rx_mode, byRCR ); ! 996: } ! 997: ! 998: static void ! 999: rhine_probe1 (struct nic *nic, struct pci_device *pci, int ioaddr, int chip_id, int options) ! 1000: { ! 1001: struct rhine_private *tp; ! 1002: static int did_version = 0; /* Already printed version info. */ ! 1003: unsigned int i, ww; ! 1004: unsigned int timeout; ! 1005: int FDXFlag; ! 1006: int byMIIvalue, LineSpeed, MIICRbak; ! 1007: uint8_t revision_id; ! 1008: unsigned char mode3_reg; ! 1009: ! 1010: if (rhine_debug > 0 && did_version++ == 0) ! 1011: printf ("%s",version); ! 1012: ! 1013: // get revision id. ! 1014: pci_read_config_byte(pci, PCI_REVISION, &revision_id); ! 1015: ! 1016: /* D-Link provided reset code (with comment additions) */ ! 1017: if (revision_id >= 0x40) { ! 1018: unsigned char byOrgValue; ! 1019: ! 1020: if(rhine_debug > 0) ! 1021: printf("Enabling Sticky Bit Workaround for Chip_id: 0x%hX\n" ! 1022: , chip_id); ! 1023: /* clear sticky bit before reset & read ethernet address */ ! 1024: byOrgValue = inb(bySTICKHW); ! 1025: byOrgValue = byOrgValue & 0xFC; ! 1026: outb(byOrgValue, bySTICKHW); ! 1027: ! 1028: /* (bits written are cleared?) */ ! 1029: /* disable force PME-enable */ ! 1030: outb(0x80, byWOLcgClr); ! 1031: /* disable power-event config bit */ ! 1032: outb(0xFF, byWOLcrClr); ! 1033: /* clear power status (undocumented in vt6102 docs?) */ ! 1034: outb(0xFF, byPwrcsrClr); ! 1035: ! 1036: } ! 1037: ! 1038: /* Reset the chip to erase previous misconfiguration. */ ! 1039: outw(CR_SFRST, byCR0); ! 1040: // if vt3043 delay after reset ! 1041: if (revision_id <0x40) { ! 1042: udelay(10000); ! 1043: } ! 1044: // polling till software reset complete ! 1045: // W_MAX_TIMEOUT is the timeout period ! 1046: for(ww = 0; ww < W_MAX_TIMEOUT; ww++) { ! 1047: if ((inw(byCR0) & CR_SFRST) == 0) ! 1048: break; ! 1049: } ! 1050: ! 1051: // issue AUTOLoad in EECSR to reload eeprom ! 1052: outb(0x20, byEECSR ); ! 1053: ! 1054: // if vt3065 delay after reset ! 1055: if (revision_id >=0x40) { ! 1056: // delay 8ms to let MAC stable ! 1057: mdelay(8); ! 1058: /* ! 1059: * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA ! 1060: * turned on. it makes MAC receive magic packet ! 1061: * automatically. So, we turn it off. (D-Link) ! 1062: */ ! 1063: outb(inb(byCFGA) & 0xFE, byCFGA); ! 1064: } ! 1065: ! 1066: /* turn on bit2 in PCI configuration register 0x53 , only for 3065*/ ! 1067: if (revision_id >= 0x40) { ! 1068: pci_read_config_byte(pci, PCI_REG_MODE3, &mode3_reg); ! 1069: pci_write_config_byte(pci, PCI_REG_MODE3, mode3_reg|MODE3_MIION); ! 1070: } ! 1071: ! 1072: ! 1073: /* back off algorithm ,disable the right-most 4-bit off CFGD*/ ! 1074: outb(inb(byCFGD) & (~(CFGD_RANDOM | CFGD_CFDX | CFGD_CEREN | CFGD_CETEN)), byCFGD); ! 1075: ! 1076: /* reload eeprom */ ! 1077: reload_eeprom(ioaddr); ! 1078: ! 1079: /* Perhaps this should be read from the EEPROM? */ ! 1080: for (i = 0; i < ETH_ALEN; i++) ! 1081: nic->node_addr[i] = inb (byPAR0 + i); ! 1082: ! 1083: DBG ( "IO address %#hX Ethernet Address: %s\n", ioaddr, eth_ntoa ( nic->node_addr ) ); ! 1084: ! 1085: /* restart MII auto-negotiation */ ! 1086: WriteMII (0, 9, 1, ioaddr); ! 1087: printf ("Analyzing Media type,this may take several seconds... "); ! 1088: for (i = 0; i < 5; i++) ! 1089: { ! 1090: /* need to wait 1 millisecond - we will round it up to 50-100ms */ ! 1091: timeout = currticks() + 2; ! 1092: for (timeout = currticks() + 2; currticks() < timeout;) ! 1093: /* nothing */; ! 1094: if (ReadMII (1, ioaddr) & 0x0020) ! 1095: break; ! 1096: } ! 1097: printf ("OK.\n"); ! 1098: ! 1099: #if 0 ! 1100: /* JJM : for Debug */ ! 1101: printf("MII : Address %hhX ",inb(ioaddr+0x6c)); ! 1102: { ! 1103: unsigned char st1,st2,adv1,adv2,l1,l2; ! 1104: ! 1105: st1=ReadMII(1,ioaddr)>>8; ! 1106: st2=ReadMII(1,ioaddr)&0xFF; ! 1107: adv1=ReadMII(4,ioaddr)>>8; ! 1108: adv2=ReadMII(4,ioaddr)&0xFF; ! 1109: l1=ReadMII(5,ioaddr)>>8; ! 1110: l2=ReadMII(5,ioaddr)&0xFF; ! 1111: printf(" status 0x%hhX%hhX, advertising 0x%hhX%hhX, link 0x%hhX%hhX\n", st1,st2,adv1,adv2,l1,l2); ! 1112: } ! 1113: #endif ! 1114: ! 1115: ! 1116: /* query MII to know LineSpeed,duplex mode */ ! 1117: byMIIvalue = inb (ioaddr + 0x6d); ! 1118: LineSpeed = byMIIvalue & MIISR_SPEED; ! 1119: if (LineSpeed != 0) //JJM ! 1120: { ! 1121: printf ("Linespeed=10Mbs"); ! 1122: } ! 1123: else ! 1124: { ! 1125: printf ("Linespeed=100Mbs"); ! 1126: } ! 1127: ! 1128: FDXFlag = QueryAuto (ioaddr); ! 1129: if (FDXFlag == 1) ! 1130: { ! 1131: printf (" Fullduplex\n"); ! 1132: outw (CR_FDX, byCR0); ! 1133: } ! 1134: else ! 1135: { ! 1136: printf (" Halfduplex\n"); ! 1137: } ! 1138: ! 1139: ! 1140: /* set MII 10 FULL ON, only apply in vt3043 */ ! 1141: if(chip_id == 0x3043) ! 1142: WriteMII (0x17, 1, 1, ioaddr); ! 1143: ! 1144: /* turn on MII link change */ ! 1145: MIICRbak = inb (byMIICR); ! 1146: outb (MIICRbak & 0x7F, byMIICR); ! 1147: MIIDelay (); ! 1148: outb (0x41, byMIIAD); ! 1149: MIIDelay (); ! 1150: ! 1151: /* while((inb(byMIIAD)&0x20)==0) ; */ ! 1152: outb (MIICRbak | 0x80, byMIICR); ! 1153: ! 1154: nic->priv_data = &rhine; ! 1155: tp = &rhine; ! 1156: tp->chip_id = chip_id; ! 1157: tp->ioaddr = ioaddr; ! 1158: tp->phys[0] = -1; ! 1159: tp->chip_revision = revision_id; ! 1160: ! 1161: /* The lower four bits are the media type. */ ! 1162: if (options > 0) ! 1163: { ! 1164: tp->full_duplex = (options & 16) ? 1 : 0; ! 1165: tp->default_port = options & 15; ! 1166: if (tp->default_port) ! 1167: tp->medialock = 1; ! 1168: } ! 1169: return; ! 1170: } ! 1171: ! 1172: static void ! 1173: rhine_disable ( struct nic *nic ) { ! 1174: ! 1175: struct rhine_private *tp = (struct rhine_private *) nic->priv_data; ! 1176: int ioaddr = tp->ioaddr; ! 1177: ! 1178: rhine_reset(nic); ! 1179: ! 1180: printf ("rhine disable\n"); ! 1181: /* Switch to loopback mode to avoid hardware races. */ ! 1182: outb(0x60 | 0x01, byTCR); ! 1183: /* Stop the chip's Tx and Rx processes. */ ! 1184: outw(CR_STOP, byCR0); ! 1185: } ! 1186: ! 1187: /************************************************************************** ! 1188: ETH_RESET - Reset adapter ! 1189: ***************************************************************************/ ! 1190: static void ! 1191: rhine_reset (struct nic *nic) ! 1192: { ! 1193: struct rhine_private *tp = (struct rhine_private *) nic->priv_data; ! 1194: int ioaddr = tp->ioaddr; ! 1195: int i, j; ! 1196: int FDXFlag, CRbak; ! 1197: void *rx_ring_tmp; ! 1198: void *tx_ring_tmp; ! 1199: void *rx_bufs_tmp; ! 1200: void *tx_bufs_tmp; ! 1201: unsigned long rx_ring_tmp1; ! 1202: unsigned long tx_ring_tmp1; ! 1203: unsigned long rx_bufs_tmp1; ! 1204: unsigned long tx_bufs_tmp1; ! 1205: ! 1206: /* printf ("rhine_reset\n"); */ ! 1207: /* Soft reset the chip. */ ! 1208: /*outb(CmdReset, ioaddr + ChipCmd); */ ! 1209: ! 1210: tx_bufs_tmp = rhine_buffers.txbuf; ! 1211: tx_ring_tmp = rhine_buffers.txdesc; ! 1212: rx_bufs_tmp = rhine_buffers.rxbuf; ! 1213: rx_ring_tmp = rhine_buffers.rxdesc; ! 1214: ! 1215: /* tune RD TD 32 byte alignment */ ! 1216: rx_ring_tmp1 = virt_to_bus ( rx_ring_tmp ); ! 1217: j = (rx_ring_tmp1 + 32) & (~0x1f); ! 1218: /* printf ("txring[%d]", j); */ ! 1219: tp->rx_ring = (struct rhine_rx_desc *) bus_to_virt (j); ! 1220: ! 1221: tx_ring_tmp1 = virt_to_bus ( tx_ring_tmp ); ! 1222: j = (tx_ring_tmp1 + 32) & (~0x1f); ! 1223: tp->tx_ring = (struct rhine_tx_desc *) bus_to_virt (j); ! 1224: /* printf ("rxring[%X]", j); */ ! 1225: ! 1226: ! 1227: tx_bufs_tmp1 = virt_to_bus ( tx_bufs_tmp ); ! 1228: j = (int) (tx_bufs_tmp1 + 32) & (~0x1f); ! 1229: tx_bufs_tmp = bus_to_virt (j); ! 1230: /* printf ("txb[%X]", j); */ ! 1231: ! 1232: rx_bufs_tmp1 = virt_to_bus ( rx_bufs_tmp ); ! 1233: j = (int) (rx_bufs_tmp1 + 32) & (~0x1f); ! 1234: rx_bufs_tmp = bus_to_virt (j); ! 1235: /* printf ("rxb[%X][%X]", rx_bufs_tmp1, j); */ ! 1236: ! 1237: for (i = 0; i < RX_RING_SIZE; i++) ! 1238: { ! 1239: tp->rx_buffs[i] = (char *) rx_bufs_tmp; ! 1240: /* printf("r[%X]",tp->rx_buffs[i]); */ ! 1241: rx_bufs_tmp += 1536; ! 1242: } ! 1243: ! 1244: for (i = 0; i < TX_RING_SIZE; i++) ! 1245: { ! 1246: tp->tx_buffs[i] = (char *) tx_bufs_tmp; ! 1247: /* printf("t[%X]",tp->tx_buffs[i]); */ ! 1248: tx_bufs_tmp += 1536; ! 1249: } ! 1250: ! 1251: /* software reset */ ! 1252: outb (CR1_SFRST, byCR1); ! 1253: MIIDelay (); ! 1254: ! 1255: /* printf ("init ring"); */ ! 1256: rhine_init_ring (nic); ! 1257: /*write TD RD Descriptor to MAC */ ! 1258: outl (virt_to_bus (tp->rx_ring), dwCurrentRxDescAddr); ! 1259: outl (virt_to_bus (tp->tx_ring), dwCurrentTxDescAddr); ! 1260: ! 1261: /* Setup Multicast */ ! 1262: set_rx_mode(nic); ! 1263: ! 1264: /* set TCR RCR threshold to store and forward*/ ! 1265: outb (0x3e, byBCR0); ! 1266: outb (0x38, byBCR1); ! 1267: outb (0x2c, byRCR); ! 1268: outb (0x60, byTCR); ! 1269: /* Set Fulldupex */ ! 1270: FDXFlag = QueryAuto (ioaddr); ! 1271: if (FDXFlag == 1) ! 1272: { ! 1273: outb (CFGD_CFDX, byCFGD); ! 1274: outw (CR_FDX, byCR0); ! 1275: } ! 1276: ! 1277: /* KICK NIC to WORK */ ! 1278: CRbak = inw (byCR0); ! 1279: CRbak = CRbak & 0xFFFB; /* not CR_STOP */ ! 1280: outw ((CRbak | CR_STRT | CR_TXON | CR_RXON | CR_DPOLL), byCR0); ! 1281: ! 1282: /* disable all known interrupt */ ! 1283: outw (0, byIMR0); ! 1284: } ! 1285: /* Beware of PCI posted writes */ ! 1286: #define IOSYNC do { inb(nic->ioaddr + StationAddr); } while (0) ! 1287: ! 1288: static int ! 1289: rhine_poll (struct nic *nic, int retreive) ! 1290: { ! 1291: struct rhine_private *tp = (struct rhine_private *) nic->priv_data; ! 1292: int rxstatus, good = 0;; ! 1293: ! 1294: if (tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit == 0) ! 1295: { ! 1296: unsigned int intr_status; ! 1297: /* There is a packet ready */ ! 1298: if(!retreive) ! 1299: return 1; ! 1300: ! 1301: intr_status = inw(nic->ioaddr + IntrStatus); ! 1302: /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */ ! 1303: #if 0 ! 1304: if (tp->chip_id == 0x3065) ! 1305: intr_status |= inb(nic->ioaddr + IntrStatus2) << 16; ! 1306: #endif ! 1307: /* Acknowledge all of the current interrupt sources ASAP. */ ! 1308: if (intr_status & IntrTxDescRace) ! 1309: outb(0x08, nic->ioaddr + IntrStatus2); ! 1310: outw(intr_status & 0xffff, nic->ioaddr + IntrStatus); ! 1311: IOSYNC; ! 1312: ! 1313: rxstatus = tp->rx_ring[tp->cur_rx].rx_status.lw; ! 1314: if ((rxstatus & 0x0300) != 0x0300) ! 1315: { ! 1316: printf("rhine_poll: bad status\n"); ! 1317: } ! 1318: else if (rxstatus & (RSR_ABNORMAL)) ! 1319: { ! 1320: printf ("rxerr[%X]\n", rxstatus); ! 1321: } ! 1322: else ! 1323: good = 1; ! 1324: ! 1325: if (good) ! 1326: { ! 1327: nic->packetlen = tp->rx_ring[tp->cur_rx].rx_status.bits.frame_length; ! 1328: memcpy (nic->packet, tp->rx_buffs[tp->cur_rx], nic->packetlen); ! 1329: /* printf ("Packet RXed\n"); */ ! 1330: } ! 1331: tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit = 1; ! 1332: tp->cur_rx++; ! 1333: tp->cur_rx = tp->cur_rx % RX_RING_SIZE; ! 1334: } ! 1335: /* Acknowledge all of the current interrupt sources ASAP. */ ! 1336: outw(DEFAULT_INTR & ~IntrRxDone, nic->ioaddr + IntrStatus); ! 1337: ! 1338: IOSYNC; ! 1339: ! 1340: return good; ! 1341: } ! 1342: ! 1343: static void ! 1344: rhine_transmit (struct nic *nic, ! 1345: const char *d, unsigned int t, unsigned int s, const char *p) ! 1346: { ! 1347: struct rhine_private *tp = (struct rhine_private *) nic->priv_data; ! 1348: int ioaddr = tp->ioaddr; ! 1349: int entry; ! 1350: unsigned char CR1bak; ! 1351: unsigned char CR0bak; ! 1352: unsigned int nstype; ! 1353: unsigned long ct; ! 1354: ! 1355: ! 1356: /*printf ("rhine_transmit\n"); */ ! 1357: /* setup ethernet header */ ! 1358: ! 1359: ! 1360: /* Calculate the next Tx descriptor entry. */ ! 1361: entry = tp->cur_tx % TX_RING_SIZE; ! 1362: ! 1363: memcpy (tp->tx_buffs[entry], d, ETH_ALEN); /* dst */ ! 1364: memcpy (tp->tx_buffs[entry] + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ ! 1365: ! 1366: nstype=htons(t); ! 1367: memcpy(tp->tx_buffs[entry] + 2 * ETH_ALEN, (char*)&nstype, 2); ! 1368: ! 1369: memcpy (tp->tx_buffs[entry] + ETH_HLEN, p, s); ! 1370: s += ETH_HLEN; ! 1371: while (s < ETH_ZLEN) ! 1372: *((char *) tp->tx_buffs[entry] + (s++)) = 0; ! 1373: ! 1374: tp->tx_ring[entry].tx_ctrl.bits.tx_buf_size = s; ! 1375: ! 1376: tp->tx_ring[entry].tx_status.bits.own_bit = 1; ! 1377: ! 1378: ! 1379: CR1bak = inb (byCR1); ! 1380: ! 1381: CR1bak = CR1bak | CR1_TDMD1; ! 1382: /*printf("tdsw=[%X]",tp->tx_ring[entry].tx_status.lw); */ ! 1383: /*printf("tdcw=[%X]",tp->tx_ring[entry].tx_ctrl.lw); */ ! 1384: /*printf("tdbuf1=[%X]",tp->tx_ring[entry].buf_addr_1); */ ! 1385: /*printf("tdbuf2=[%X]",tp->tx_ring[entry].buf_addr_2); */ ! 1386: /*printf("td1=[%X]",inl(dwCurrentTDSE0)); */ ! 1387: /*printf("td2=[%X]",inl(dwCurrentTDSE1)); */ ! 1388: /*printf("td3=[%X]",inl(dwCurrentTDSE2)); */ ! 1389: /*printf("td4=[%X]",inl(dwCurrentTDSE3)); */ ! 1390: ! 1391: outb (CR1bak, byCR1); ! 1392: do ! 1393: { ! 1394: ct = currticks(); ! 1395: /* Wait until transmit is finished or timeout*/ ! 1396: while((tp->tx_ring[entry].tx_status.bits.own_bit !=0) && ! 1397: ct + 10*1000 < currticks()) ! 1398: ; ! 1399: ! 1400: if(tp->tx_ring[entry].tx_status.bits.terr == 0) ! 1401: break; ! 1402: ! 1403: if(tp->tx_ring[entry].tx_status.bits.abt == 1) ! 1404: { ! 1405: // turn on TX ! 1406: CR0bak = inb(byCR0); ! 1407: CR0bak = CR0bak|CR_TXON; ! 1408: outb(CR0bak,byCR0); ! 1409: } ! 1410: }while(0); ! 1411: tp->cur_tx++; ! 1412: ! 1413: /*outw(IMRShadow,byIMR0); */ ! 1414: /*dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE); */ ! 1415: /*tp->tx_skbuff[entry] = 0; */ ! 1416: } ! 1417: ! 1418: static struct nic_operations rhine_operations = { ! 1419: .connect = dummy_connect, ! 1420: .poll = rhine_poll, ! 1421: .transmit = rhine_transmit, ! 1422: .irq = rhine_irq, ! 1423: ! 1424: }; ! 1425: ! 1426: static struct pci_device_id rhine_nics[] = { ! 1427: PCI_ROM(0x1106, 0x3065, "dlink-530tx", "VIA 6102", 0), ! 1428: PCI_ROM(0x1106, 0x3106, "via-rhine-6105", "VIA 6105", 0), ! 1429: PCI_ROM(0x1106, 0x3043, "dlink-530tx-old", "VIA 3043", 0), /* Rhine-I 86c100a */ ! 1430: PCI_ROM(0x1106, 0x3053, "via6105m", "VIA 6105M", 0), ! 1431: PCI_ROM(0x1106, 0x6100, "via-rhine-old", "VIA 86C100A", 0), /* Rhine-II */ ! 1432: }; ! 1433: ! 1434: PCI_DRIVER ( rhine_driver, rhine_nics, PCI_NO_CLASS ); ! 1435: ! 1436: DRIVER ( "VIA 86C100", nic_driver, pci_driver, rhine_driver, ! 1437: rhine_probe, rhine_disable ); ! 1438: ! 1439: /* EOF via-rhine.c */ ! 1440: ! 1441: /* ! 1442: * Local variables: ! 1443: * c-basic-offset: 8 ! 1444: * c-indent-level: 8 ! 1445: * tab-width: 8 ! 1446: * End: ! 1447: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.