1 /* 2 * VIA VT6105M Fast Ethernet Controller (Rhine III). 3 * To do: 4 * cache-line size alignments - done 5 * reduce tx interrupts - done 6 * reorganise initialisation/shutdown/reset 7 * adjust Tx FIFO threshold on underflow - untested 8 * why does the link status never cause an interrupt? 9 * use the lproc as a periodic timer for stalls, etc. 10 * checksum offload - done 11 * take non-HW stuff out of descriptor for 64-bit 12 * cleanliness 13 * why does the receive buffer alloc have a +3? 14 */ 15 #include "u.h" 16 #include "../port/lib.h" 17 #include "mem.h" 18 #include "dat.h" 19 #include "fns.h" 20 #include "io.h" 21 #include "../port/error.h" 22 #include "../port/netif.h" 23 24 #include "etherif.h" 25 #include "ethermii.h" 26 27 enum { 28 Par0 = 0x00, /* Ethernet Address */ 29 Rcr = 0x06, /* Receive Configuration */ 30 Tcr = 0x07, /* Transmit Configuration */ 31 Cr = 0x08, /* Control */ 32 Tqw = 0x0A, /* Transmit Queue Wake */ 33 Isr = 0x0C, /* Interrupt Status */ 34 Imr = 0x0E, /* Interrupt Mask */ 35 Mcfilt0 = 0x10, /* Multicast Filter 0 */ 36 Mcfilt1 = 0x14, /* Multicast Filter 1 */ 37 Rxdaddr = 0x18, /* Current Rd Address */ 38 Txdaddr = 0x1C, /* Current Td Address */ 39 Phyadr = 0x6C, /* Phy Address */ 40 Miisr = 0x6D, /* MII Status */ 41 Bcr0 = 0x6E, /* Bus Control */ 42 Bcr1 = 0x6F, 43 Miicr = 0x70, /* MII Control */ 44 Miiadr = 0x71, /* MII Address */ 45 Miidata = 0x72, /* MII Data */ 46 Eecsr = 0x74, /* EEPROM Control and Status */ 47 CfgA = 0x78, /* Chip Configuration A */ 48 CfgB = 0x79, 49 CfgC = 0x7A, 50 CfgD = 0x7B, 51 Cr0 = 0x80, /* Miscellaneous Control */ 52 Cr1 = 0x81, 53 Pmcc = 0x82, /* Power Mgmt Capability Control */ 54 Stickhw = 0x83, /* Sticky Hardware Control */ 55 Misr = 0x84, /* MII Interrupt Control */ 56 Mimr = 0x85, /* MII Interrupt Mask */ 57 Wolcrclr = 0xA4, 58 Wolcgclr = 0xA7, 59 Pwrcsrclr = 0xAC, 60 }; 61 62 enum { /* Rcr */ 63 Sep = 0x01, /* Accept Error Packets */ 64 Ar = 0x02, /* Accept Small Packets */ 65 Am = 0x04, /* Accept Multicast */ 66 Ab = 0x08, /* Accept Broadcast */ 67 Prom = 0x10, /* Accept Physical Address Packets */ 68 RrftMASK = 0xE0, /* Receive FIFO Threshold */ 69 RrftSHIFT = 5, 70 Rrft64 = 0<<RrftSHIFT, 71 Rrft32 = 1<<RrftSHIFT, 72 Rrft128 = 2<<RrftSHIFT, 73 Rrft256 = 3<<RrftSHIFT, 74 Rrft512 = 4<<RrftSHIFT, 75 Rrft768 = 5<<RrftSHIFT, 76 Rrft1024 = 6<<RrftSHIFT, 77 RrftSAF = 7<<RrftSHIFT, 78 }; 79 80 enum { /* Tcr */ 81 Lb0 = 0x02, /* Loopback Mode */ 82 Lb1 = 0x04, 83 Ofset = 0x08, /* Select Back-off Priority */ 84 RtsfMASK = 0xE0, /* Transmit FIFO Threshold */ 85 RtsfSHIFT = 5, 86 Rtsf128 = 0<<RtsfSHIFT, 87 Rtsf256 = 1<<RtsfSHIFT, 88 Rtsf512 = 2<<RtsfSHIFT, 89 Rtsf1024 = 3<<RtsfSHIFT, 90 RtsfSAF = 7<<RtsfSHIFT, 91 }; 92 93 enum { /* Cr */ 94 Init = 0x0001, /* INIT Process Begin */ 95 Strt = 0x0002, /* Start NIC */ 96 Stop = 0x0004, /* Stop NIC */ 97 Rxon = 0x0008, /* Turn on Receive Process */ 98 Txon = 0x0010, /* Turn on Transmit Process */ 99 Tdmd = 0x0020, /* Transmit Poll Demand */ 100 Rdmd = 0x0040, /* Receive Poll Demand */ 101 Eren = 0x0100, /* Early Receive Enable */ 102 Fdx = 0x0400, /* Set MAC to Full Duplex */ 103 Dpoll = 0x0800, /* Disable Td/Rd Auto Polling */ 104 Tdmd1 = 0x2000, /* Transmit Poll Demand 1 */ 105 Rdmd1 = 0x4000, /* Receive Poll Demand 1 */ 106 Sfrst = 0x8000, /* Software Reset */ 107 }; 108 109 enum { /* Isr/Imr */ 110 Prx = 0x0001, /* Packet Received OK */ 111 Ptx = 0x0002, /* Packet Transmitted OK */ 112 Rxe = 0x0004, /* Receive Error */ 113 Txe = 0x0008, /* Transmit Error */ 114 Tu = 0x0010, /* Transmit Buffer Underflow */ 115 Ru = 0x0020, /* Receive Buffer Link Error */ 116 Be = 0x0040, /* PCI Bus Error */ 117 Cnt = 0x0080, /* Counter Overflow */ 118 Eri = 0x0100, /* Early Receive Interrupt */ 119 Udfi = 0x0200, /* Tx FIFO Underflow */ 120 Ovfi = 0x0400, /* Receive FIFO Overflow */ 121 Pktrace = 0x0800, /* Hmmm... */ 122 Norbf = 0x1000, /* No Receive Buffers */ 123 Abti = 0x2000, /* Transmission Abort */ 124 Srci = 0x4000, /* Port State Change */ 125 Geni = 0x8000, /* General Purpose Interrupt */ 126 }; 127 128 enum { /* Phyadr */ 129 PhyadMASK = 0x1F, /* PHY Address */ 130 PhyadSHIFT = 0, 131 Mfdc = 0x20, /* Accelerate MDC Speed */ 132 Mpo0 = 0x40, /* MII Polling Timer Interval */ 133 Mpo1 = 0x80, 134 }; 135 136 enum { /* Bcr0 */ 137 DmaMASK = 0x07, /* DMA Length */ 138 DmaSHIFT = 0, 139 Dma32 = 0<<DmaSHIFT, 140 Dma64 = 1<<DmaSHIFT, 141 Dma128 = 2<<DmaSHIFT, 142 Dma256 = 3<<DmaSHIFT, 143 Dma512 = 4<<DmaSHIFT, 144 Dma1024 = 5<<DmaSHIFT, 145 DmaSAF = 7<<DmaSHIFT, 146 CrftMASK = 0x38, /* Rx FIFO Threshold */ 147 CrftSHIFT = 3, 148 Crft64 = 1<<CrftSHIFT, 149 Crft128 = 2<<CrftSHIFT, 150 Crft256 = 3<<CrftSHIFT, 151 Crft512 = 4<<CrftSHIFT, 152 Crft1024 = 5<<CrftSHIFT, 153 CrftSAF = 7<<CrftSHIFT, 154 Extled = 0x40, /* Extra LED Support Control */ 155 Med2 = 0x80, /* Medium Select Control */ 156 }; 157 158 enum { /* Bcr1 */ 159 PotMASK = 0x07, /* Polling Timer Interval */ 160 PotSHIFT = 0, 161 CtftMASK = 0x38, /* Tx FIFO Threshold */ 162 CtftSHIFT = 3, 163 Ctft64 = 1<<CtftSHIFT, 164 Ctft128 = 2<<CtftSHIFT, 165 Ctft256 = 3<<CtftSHIFT, 166 Ctft512 = 4<<CtftSHIFT, 167 Ctft1024 = 5<<CtftSHIFT, 168 CtftSAF = 7<<CtftSHIFT, 169 }; 170 171 enum { /* Miicr */ 172 Mdc = 0x01, /* Clock */ 173 Mdi = 0x02, /* Data In */ 174 Mdo = 0x04, /* Data Out */ 175 Mout = 0x08, /* Output Enable */ 176 Mdpm = 0x10, /* Direct Program Mode Enable */ 177 Wcmd = 0x20, /* Write Enable */ 178 Rcmd = 0x40, /* Read Enable */ 179 Mauto = 0x80, /* Auto Polling Enable */ 180 }; 181 182 enum { /* Miiadr */ 183 MadMASK = 0x1F, /* MII Port Address */ 184 MadSHIFT = 0, 185 Mdone = 0x20, /* Accelerate MDC Speed */ 186 Msrcen = 0x40, /* MII Polling Timer Interval */ 187 Midle = 0x80, 188 }; 189 190 enum { /* Eecsr */ 191 Edo = 0x01, /* Data Out */ 192 Edi = 0x02, /* Data In */ 193 Eck = 0x04, /* Clock */ 194 Ecs = 0x08, /* Chip Select */ 195 Dpm = 0x10, /* Direct Program Mode Enable */ 196 Autold = 0x20, /* Dynamic Reload */ 197 Embp = 0x40, /* Embedded Program Enable */ 198 Eepr = 0x80, /* Programmed */ 199 }; 200 201 /* 202 * Ring descriptor. The space allocated for each 203 * of these will be rounded up to a cache-line boundary. 204 * The first 4 elements are known to the hardware. 205 */ 206 typedef struct Ds Ds; 207 typedef struct Ds { 208 u32int status; 209 u32int control; 210 u32int addr; 211 u32int branch; 212 213 Block* bp; 214 Ds* next; 215 Ds* prev; 216 } Ds; 217 218 enum { /* Rx Ds status */ 219 Rerr = 0x00000001, /* Buff|Rxserr|Fov|Fae|Crc */ 220 Crc = 0x00000002, /* CRC Error */ 221 Fae = 0x00000004, /* Frame Alignment Error */ 222 Fov = 0x00000008, /* FIFO Overflow */ 223 Long = 0x00000010, /* A Long Packet */ 224 Runt = 0x00000020, /* A Runt Packet */ 225 Rxserr = 0x00000040, /* System Error */ 226 Buff = 0x00000080, /* Buffer Underflow Error */ 227 Rxedp = 0x00000100, /* End of Packet Buffer */ 228 Rxstp = 0x00000200, /* Packet Start */ 229 Chn = 0x00000400, /* Chain Buffer */ 230 Phy = 0x00000800, /* Physical Address Packet */ 231 Bar = 0x00001000, /* Broadcast Packet */ 232 Mar = 0x00002000, /* Multicast Packet */ 233 Rxok = 0x00008000, /* Packet Received OK */ 234 LengthMASK = 0x07FF0000, /* Received Packet Length */ 235 LengthSHIFT = 16, 236 237 Own = 0x80000000, /* Descriptor Owned by NIC */ 238 }; 239 240 enum { /* Rx Ds control */ 241 RbsizeMASK = 0x000007FF, /* Receive Buffer Size */ 242 RbsizeSHIFT = 0, 243 Tag = 0x00010000, /* Receive a Tagged Packet */ 244 Udpkt = 0x00020000, /* Receive a UDP Packet */ 245 Tcpkt = 0x00040000, /* Receive a TCP Packet */ 246 Ipkt = 0x00080000, /* Receive an IP Packet */ 247 Tuok = 0x00100000, /* TCP/UDP Checksum OK */ 248 Ipok = 0x00200000, /* IP Checksum OK */ 249 Snaptag = 0x00400000, /* Snap Packet + 802.1q Tag */ 250 Rxlerr = 0x00800000, /* Receive Length Check Error */ 251 IpktMASK = 0xff000000, /* Interesting Packet */ 252 IpktSHIFT = 24, 253 }; 254 255 enum { /* Tx Ds status */ 256 NcrMASK = 0x0000000F, /* Collision Retry Count */ 257 NcrSHIFT = 0, 258 Cols = 0x00000010, /* Experienced Collisions */ 259 Cdh = 0x00000080, /* CD Heartbeat */ 260 Abt = 0x00000100, /* Aborted after Excessive Collisions */ 261 Owc = 0x00000200, /* Out of Window Collision */ 262 Crs = 0x00000400, /* Carrier Sense Lost */ 263 Udf = 0x00000800, /* FIFO Underflow */ 264 Tbuff = 0x00001000, /* Invalid Td */ 265 Txserr = 0x00002000, /* System Error */ 266 Terr = 0x00008000, /* Excessive Collisions */ 267 }; 268 269 enum { /* Tx Ds control */ 270 TbsMASK = 0x000007FF, /* Tx Buffer Size */ 271 TbsSHIFT = 0, 272 Chain = 0x00008000, /* Chain Buffer */ 273 Crcdisable = 0x00010000, /* Disable CRC generation */ 274 Stp = 0x00200000, /* Start of Packet */ 275 Edp = 0x00400000, /* End of Packet */ 276 Ic = 0x00800000, /* Interrupt Control */ 277 }; 278 279 enum { /* Tx Ds branch */ 280 Tdctl = 0x00000001, /* No Interrupt Generated */ 281 }; 282 283 enum { 284 Nrd = 196, 285 Ntd = 64, 286 Crcsz = 4, 287 Bslop = 48, 288 Rdbsz = ETHERMAXTU+Crcsz+Bslop, 289 290 Nrxstats = 8, 291 Ntxstats = 9, 292 293 Txcopy = 128, 294 }; 295 296 typedef struct Ctlr Ctlr; 297 typedef struct Ctlr { 298 int port; 299 Pcidev* pcidev; 300 Ctlr* next; 301 int active; 302 int id; 303 uchar par[Eaddrlen]; 304 305 QLock alock; /* attach */ 306 void* alloc; /* descriptors, etc. */ 307 int cls; /* alignment */ 308 int nrd; 309 int ntd; 310 311 Ds* rd; 312 Ds* rdh; 313 314 Lock tlock; 315 Ds* td; 316 Ds* tdh; 317 Ds* tdt; 318 int tdused; 319 320 Lock clock; /* */ 321 int cr; 322 int imr; 323 int tft; /* Tx threshold */ 324 325 Mii* mii; 326 Rendez lrendez; 327 int lwakeup; 328 329 uint rxstats[Nrxstats]; /* statistics */ 330 uint txstats[Ntxstats]; 331 ulong totalt; 332 uint intr; 333 uint lintr; 334 uint lsleep; 335 uint rintr; 336 uint tintr; 337 uint txdw; 338 int tdumax; 339 340 uint abt; 341 uint tbuff; 342 uint udf; 343 344 uint abti; 345 uint udfi; 346 uint tu; 347 348 uint tuok; 349 uint ipok; 350 } Ctlr; 351 352 static Ctlr* vt6105Mctlrhead; 353 static Ctlr* vt6105Mctlrtail; 354 355 #define csr8r(c, r) (inb((c)->port+(r))) 356 #define csr16r(c, r) (ins((c)->port+(r))) 357 #define csr32r(c, r) (inl((c)->port+(r))) 358 #define csr8w(c, r, b) (outb((c)->port+(r), (int)(b))) 359 #define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w))) 360 #define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w))) 361 362 static Lock vt6105Mrblock; /* receive Block freelist */ 363 static Block* vt6105Mrbpool; 364 static uint vt6105Mrbpoolsz; 365 366 typedef struct Regs Regs; 367 typedef struct Regs { 368 char* name; 369 int offset; 370 int size; 371 } Regs; 372 373 static Regs regs[] = { 374 // "Par0", Par0, 1, 375 // "Par1", Par0+1, 1, 376 // "Par2", Par0+2, 1, 377 // "Par3", Par0+3, 1, 378 // "Par4", Par0+4, 1, 379 // "Par5", Par0+5, 1, 380 "Rcr", Rcr, 1, 381 "Tcr", Tcr, 1, 382 "Cr0", Cr, 1, 383 "Cr1", Cr+1, 1, 384 "Isr0", Isr, 1, 385 "Isr1", Isr+1, 1, 386 "Imr0", Imr, 1, 387 "Imr1", Imr+1, 1, 388 // "Mcfilt0", Mcfilt0,4, 389 // "Mcfilt1", Mcfilt1,4, 390 // "Rxdaddr", Rxdaddr,4, 391 // "Txdaddr", Txdaddr,4, 392 "Phyadr", Phyadr, 1, 393 "Miisr", Miisr, 1, 394 "Bcr0", Bcr0, 1, 395 "Bcr1", Bcr1, 1, 396 "Miicr", Miicr, 1, 397 "Miiadr", Miiadr, 1, 398 // "Miidata", Miidata,2, 399 "Eecsr", Eecsr, 1, 400 "CfgA", CfgA, 1, 401 "CfgB", CfgB, 1, 402 "CfgC", CfgC, 1, 403 "CfgD", CfgD, 1, 404 "Cr0", Cr0, 1, 405 "Cr1", Cr1, 1, 406 "Pmcc", Pmcc, 1, 407 "Stickhw", Stickhw,1, 408 "Misr", Misr, 1, 409 "Mimr", Mimr, 1, 410 nil, 411 }; 412 413 static char* rxstats[Nrxstats] = { 414 "Receiver Error", 415 "CRC Error", 416 "Frame Alignment Error", 417 "FIFO Overflow", 418 "Long Packet", 419 "Runt Packet", 420 "System Error", 421 "Buffer Underflow Error", 422 }; 423 static char* txstats[Ntxstats] = { 424 "Aborted after Excessive Collisions", 425 "Out of Window Collision Seen", 426 "Carrier Sense Lost", 427 "FIFO Underflow", 428 "Invalid Td", 429 "System Error", 430 nil, 431 "Excessive Collisions", 432 }; 433 434 static long 435 vt6105Mifstat(Ether* edev, void* a, long n, ulong offset) 436 { 437 int i, r; 438 Ctlr *ctlr; 439 char *alloc, *e, *p; 440 441 ctlr = edev->ctlr; 442 443 alloc = malloc(READSTR); 444 p = alloc; 445 if(p == nil) 446 error(Enomem); 447 e = p + READSTR; 448 for(i = 0; i < Nrxstats; i++){ 449 p = seprint(p, e, "%s: %ud\n", rxstats[i], ctlr->rxstats[i]); 450 } 451 for(i = 0; i < Ntxstats; i++){ 452 if(txstats[i] == nil) 453 continue; 454 p = seprint(p, e, "%s: %ud\n", txstats[i], ctlr->txstats[i]); 455 } 456 p = seprint(p, e, "cls: %ud\n", ctlr->cls); 457 p = seprint(p, e, "intr: %ud\n", ctlr->intr); 458 p = seprint(p, e, "lintr: %ud\n", ctlr->lintr); 459 p = seprint(p, e, "lsleep: %ud\n", ctlr->lsleep); 460 p = seprint(p, e, "rintr: %ud\n", ctlr->rintr); 461 p = seprint(p, e, "tintr: %ud\n", ctlr->tintr); 462 p = seprint(p, e, "txdw: %ud\n", ctlr->txdw); 463 p = seprint(p, e, "tdumax: %ud\n", ctlr->tdumax); 464 p = seprint(p, e, "tft: %ud\n", ctlr->tft); 465 466 p = seprint(p, e, "abt: %ud\n", ctlr->abt); 467 p = seprint(p, e, "tbuff: %ud\n", ctlr->tbuff); 468 p = seprint(p, e, "udf: %ud\n", ctlr->udf); 469 p = seprint(p, e, "abti: %ud\n", ctlr->abti); 470 p = seprint(p, e, "udfi: %ud\n", ctlr->udfi); 471 p = seprint(p, e, "tu: %ud\n", ctlr->tu); 472 473 p = seprint(p, e, "tuok: %ud\n", ctlr->tuok); 474 p = seprint(p, e, "ipok: %ud\n", ctlr->ipok); 475 476 p = seprint(p, e, "rbpoolsz: %ud\n", vt6105Mrbpoolsz); 477 p = seprint(p, e, "totalt: %uld\n", ctlr->totalt); 478 479 for(i = 0; regs[i].name != nil; i++){ 480 p = seprint(p, e, "%s: %2.2x\n", 481 regs[i].name, csr8r(ctlr, regs[i].offset)); 482 } 483 484 if(ctlr->mii != nil && ctlr->mii->curphy != nil){ 485 p = seprint(p, e, "phy: "); 486 for(i = 0; i < NMiiPhyr; i++){ 487 if(i && ((i & 0x07) == 0)) 488 p = seprint(p, e, "\n "); 489 r = miimir(ctlr->mii, i); 490 p = seprint(p, e, " %4.4uX", r); 491 } 492 seprint(p, e, "\n"); 493 } 494 495 n = readstr(offset, a, n, alloc); 496 free(alloc); 497 498 return n; 499 } 500 501 static void 502 vt6105Mpromiscuous(void* arg, int on) 503 { 504 int rcr; 505 Ctlr *ctlr; 506 Ether *edev; 507 508 edev = arg; 509 ctlr = edev->ctlr; 510 rcr = csr8r(ctlr, Rcr); 511 if(on) 512 rcr |= Prom; 513 else 514 rcr &= ~Prom; 515 csr8w(ctlr, Rcr, rcr); 516 } 517 518 static void 519 vt6105Mmulticast(void* arg, uchar* addr, int on) 520 { 521 /* 522 * For now Am is set in Rcr. 523 * Will need to interlock with promiscuous 524 * when this gets filled in. 525 */ 526 USED(arg, addr, on); 527 } 528 529 static int 530 vt6105Mwakeup(void* v) 531 { 532 return *((int*)v) != 0; 533 } 534 535 static void 536 vt6105Mimr(Ctlr* ctlr, int imr) 537 { 538 ilock(&ctlr->clock); 539 ctlr->imr |= imr; 540 csr16w(ctlr, Imr, ctlr->imr); 541 iunlock(&ctlr->clock); 542 } 543 544 static void 545 vt6105Mlproc(void* arg) 546 { 547 Ctlr *ctlr; 548 Ether *edev; 549 MiiPhy *phy; 550 551 edev = arg; 552 ctlr = edev->ctlr; 553 for(;;){ 554 if(ctlr->mii == nil || ctlr->mii->curphy == nil) 555 break; 556 if(miistatus(ctlr->mii) < 0) 557 goto enable; 558 559 phy = ctlr->mii->curphy; 560 ilock(&ctlr->clock); 561 csr16w(ctlr, Cr, ctlr->cr & ~(Txon|Rxon)); 562 if(phy->fd) 563 ctlr->cr |= Fdx; 564 else 565 ctlr->cr &= ~Fdx; 566 csr16w(ctlr, Cr, ctlr->cr); 567 iunlock(&ctlr->clock); 568 enable: 569 ctlr->lwakeup = 0; 570 vt6105Mimr(ctlr, Srci); 571 572 ctlr->lsleep++; 573 sleep(&ctlr->lrendez, vt6105Mwakeup, &ctlr->lwakeup); 574 575 } 576 pexit("vt6105Mlproc: done", 1); 577 } 578 579 static void 580 vt6105Mrbfree(Block* bp) 581 { 582 bp->rp = bp->lim - (Rdbsz+3); 583 bp->wp = bp->rp; 584 bp->flag &= ~(Bipck | Budpck | Btcpck | Bpktck); 585 586 ilock(&vt6105Mrblock); 587 bp->next = vt6105Mrbpool; 588 vt6105Mrbpool = bp; 589 iunlock(&vt6105Mrblock); 590 } 591 592 static Block* 593 vt6105Mrballoc(void) 594 { 595 Block *bp; 596 597 ilock(&vt6105Mrblock); 598 if((bp = vt6105Mrbpool) != nil){ 599 vt6105Mrbpool = bp->next; 600 bp->next = nil; 601 _xinc(&bp->ref); /* prevent bp from being freed */ 602 } 603 iunlock(&vt6105Mrblock); 604 605 if(bp == nil && (bp = iallocb(Rdbsz+3)) != nil){ 606 bp->free = vt6105Mrbfree; 607 vt6105Mrbpoolsz++; 608 } 609 return bp; 610 } 611 612 static void 613 vt6105Mattach(Ether* edev) 614 { 615 Ctlr *ctlr; 616 // MiiPhy *phy; 617 uchar *alloc; 618 Ds *ds, *prev; 619 int dsz, i, timeo; 620 char name[KNAMELEN]; 621 622 ctlr = edev->ctlr; 623 qlock(&ctlr->alock); 624 if(ctlr->alloc != nil){ 625 qunlock(&ctlr->alock); 626 return; 627 } 628 629 /* 630 * Descriptor space. 631 * Receive descriptors should all be aligned on a 4-byte boundary, 632 * but try to do cache-line alignment. 633 */ 634 ctlr->nrd = Nrd; 635 ctlr->ntd = Ntd; 636 dsz = ROUNDUP(sizeof(Ds), ctlr->cls); 637 alloc = mallocalign((ctlr->nrd+ctlr->ntd)*dsz, dsz, 0, 0); 638 if(alloc == nil){ 639 qunlock(&ctlr->alock); 640 error(Enomem); 641 } 642 ctlr->alloc = alloc; 643 644 ctlr->rd = (Ds*)alloc; 645 646 if(waserror()){ 647 ds = ctlr->rd; 648 for(i = 0; i < ctlr->nrd; i++){ 649 if(ds->bp != nil){ 650 freeb(ds->bp); 651 ds->bp = nil; 652 } 653 if((ds = ds->next) == nil) 654 break; 655 } 656 free(ctlr->alloc); 657 ctlr->alloc = nil; 658 qunlock(&ctlr->alock); 659 nexterror(); 660 } 661 662 prev = (Ds*)(alloc + (ctlr->nrd-1)*dsz); 663 for(i = 0; i < ctlr->nrd; i++){ 664 ds = (Ds*)alloc; 665 alloc += dsz; 666 667 ds->control = Ipkt|Tcpkt|Udpkt|Rdbsz; 668 ds->branch = PCIWADDR(alloc); 669 670 ds->bp = vt6105Mrballoc(); 671 if(ds->bp == nil) 672 error("vt6105M: can't allocate receive ring\n"); 673 ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4); 674 ds->addr = PCIWADDR(ds->bp->rp); 675 676 ds->next = (Ds*)alloc; 677 ds->prev = prev; 678 prev = ds; 679 680 ds->status = Own; 681 } 682 prev->branch = 0; 683 prev->next = ctlr->rd; 684 prev->status = 0; 685 ctlr->rdh = ctlr->rd; 686 687 ctlr->td = (Ds*)alloc; 688 prev = (Ds*)(alloc + (ctlr->ntd-1)*dsz); 689 for(i = 0; i < ctlr->ntd; i++){ 690 ds = (Ds*)alloc; 691 alloc += dsz; 692 693 ds->next = (Ds*)alloc; 694 ds->prev = prev; 695 prev = ds; 696 } 697 prev->next = ctlr->td; 698 ctlr->tdh = ctlr->tdt = ctlr->td; 699 ctlr->tdused = 0; 700 701 ctlr->cr = Dpoll|Rdmd/*|Txon|Rxon*/|Strt; 702 /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/ 703 ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx; 704 705 ilock(&ctlr->clock); 706 csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd)); 707 csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td)); 708 csr16w(ctlr, Isr, ~0); 709 csr16w(ctlr, Imr, ctlr->imr); 710 csr16w(ctlr, Cr, ctlr->cr); 711 iunlock(&ctlr->clock); 712 713 /* 714 * Wait for link to be ready. 715 */ 716 for(timeo = 0; timeo < 350; timeo++){ 717 if(miistatus(ctlr->mii) == 0) 718 break; 719 tsleep(&up->sleep, return0, 0, 10); 720 } 721 // phy = ctlr->mii->curphy; 722 // print("%s: speed %d fd %d link %d rfc %d tfc %d\n", 723 // edev->name, phy->speed, phy->fd, phy->link, phy->rfc, phy->tfc); 724 725 ilock(&ctlr->clock); 726 ctlr->cr |= Txon|Rxon; 727 csr16w(ctlr, Cr, ctlr->cr); 728 iunlock(&ctlr->clock); 729 730 snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno); 731 kproc(name, vt6105Mlproc, edev); 732 733 qunlock(&ctlr->alock); 734 poperror(); 735 } 736 737 static void 738 vt6105Mtransmit(Ether* edev) 739 { 740 Block *bp; 741 Ctlr *ctlr; 742 Ds *ds, *next; 743 int control, i, size, tdused, timeo; 744 long t; 745 746 ctlr = edev->ctlr; 747 748 ilock(&ctlr->tlock); 749 t = lcycles(); 750 751 /* 752 * Free any completed packets 753 */ 754 ds = ctlr->tdh; 755 for(tdused = ctlr->tdused; tdused > 0; tdused--){ 756 /* 757 * For some errors the chip will turn the Tx engine 758 * off. Wait for that to happen. 759 * Could reset and re-init the chip here if it doesn't 760 * play fair. 761 * To do: adjust Tx FIFO threshold on underflow. 762 */ 763 if(ds->status & (Abt|Tbuff|Udf)){ 764 if(ds->status & Abt) 765 ctlr->abt++; 766 if(ds->status & Tbuff) 767 ctlr->tbuff++; 768 if(ds->status & Udf) 769 ctlr->udf++; 770 for(timeo = 0; timeo < 1000; timeo++){ 771 if(!(csr16r(ctlr, Cr) & Txon)) 772 break; 773 microdelay(1); 774 } 775 ds->status = Own; 776 csr32w(ctlr, Txdaddr, PCIWADDR(ds)); 777 } 778 779 if(ds->status & Own) 780 break; 781 ds->addr = 0; 782 ds->branch = 0; 783 784 if(ds->bp != nil){ 785 freeb(ds->bp); 786 ds->bp = nil; 787 } 788 for(i = 0; i < Ntxstats-1; i++){ 789 if(ds->status & (1<<i)) 790 ctlr->txstats[i]++; 791 } 792 ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT; 793 794 ds = ds->next; 795 } 796 ctlr->tdh = ds; 797 798 /* 799 * Try to fill the ring back up. 800 */ 801 ds = ctlr->tdt; 802 while(tdused < ctlr->ntd-2){ 803 if((bp = qget(edev->oq)) == nil) 804 break; 805 tdused++; 806 807 size = BLEN(bp); 808 809 next = ds->next; 810 ds->branch = PCIWADDR(ds->next)|Tdctl; 811 812 ds->bp = bp; 813 ds->addr = PCIWADDR(bp->rp); 814 control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK); 815 816 ds->control = control; 817 if(tdused >= ctlr->ntd-2){ 818 ctlr->txdw++; 819 ds->branch &= ~Tdctl; 820 } 821 coherence(); 822 ds->status = Own; 823 824 ds = next; 825 } 826 ctlr->tdt = ds; 827 ctlr->tdused = tdused; 828 if(ctlr->tdused){ 829 csr16w(ctlr, Cr, Tdmd|ctlr->cr); 830 if(tdused > ctlr->tdumax) 831 ctlr->tdumax = tdused; 832 } 833 834 ctlr->totalt += lcycles() - t; 835 iunlock(&ctlr->tlock); 836 } 837 838 static void 839 vt6105Mreceive(Ether* edev) 840 { 841 Ds *ds; 842 Block *bp; 843 Ctlr *ctlr; 844 int i, len; 845 846 ctlr = edev->ctlr; 847 848 ds = ctlr->rdh; 849 while(!(ds->status & Own) && ds->status != 0){ 850 /* 851 * Can Long packets be received OK? 852 * What happens to the Rxok bit? 853 */ 854 if(ds->status & Rerr){ 855 for(i = 0; i < Nrxstats; i++){ 856 if(ds->status & (1<<i)) 857 ctlr->rxstats[i]++; 858 } 859 } 860 else if(bp = vt6105Mrballoc()){ 861 if(ds->control & Tuok){ 862 ds->bp->flag |= Btcpck|Budpck; 863 ctlr->tuok++; 864 } 865 if(ds->control & Ipok){ 866 ds->bp->flag |= Bipck; 867 ctlr->ipok++; 868 } 869 len = ((ds->status & LengthMASK)>>LengthSHIFT)-4; 870 ds->bp->wp = ds->bp->rp+len; 871 etheriq(edev, ds->bp, 1); 872 bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4); 873 ds->addr = PCIWADDR(bp->rp); 874 ds->bp = bp; 875 } 876 ds->control = Ipkt|Tcpkt|Udpkt|Rdbsz; 877 ds->branch = 0; 878 ds->status = 0; 879 880 ds->prev->branch = PCIWADDR(ds); 881 coherence(); 882 ds->prev->status = Own; 883 884 ds = ds->next; 885 } 886 ctlr->rdh = ds; 887 888 csr16w(ctlr, Cr, ctlr->cr); 889 } 890 891 static void 892 vt6105Minterrupt(Ureg*, void* arg) 893 { 894 Ctlr *ctlr; 895 Ether *edev; 896 int imr, isr, r, timeo; 897 long t; 898 899 edev = arg; 900 ctlr = edev->ctlr; 901 902 ilock(&ctlr->clock); 903 t = lcycles(); 904 905 csr16w(ctlr, Imr, 0); 906 imr = ctlr->imr; 907 ctlr->intr++; 908 for(;;){ 909 if((isr = csr16r(ctlr, Isr)) != 0) 910 csr16w(ctlr, Isr, isr); 911 if((isr & ctlr->imr) == 0) 912 break; 913 914 if(isr & Srci){ 915 imr &= ~Srci; 916 ctlr->lwakeup = isr & Srci; 917 wakeup(&ctlr->lrendez); 918 isr &= ~Srci; 919 ctlr->lintr++; 920 } 921 if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){ 922 vt6105Mreceive(edev); 923 isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx); 924 ctlr->rintr++; 925 } 926 if(isr & (Abti|Udfi|Tu|Txe|Ptx)){ 927 if(isr & (Abti|Udfi|Tu)){ 928 if(isr & Abti) 929 ctlr->abti++; 930 if(isr & Udfi) 931 ctlr->udfi++; 932 if(isr & Tu) 933 ctlr->tu++; 934 for(timeo = 0; timeo < 1000; timeo++){ 935 if(!(csr16r(ctlr, Cr) & Txon)) 936 break; 937 microdelay(1); 938 } 939 940 if((isr & Udfi) && ctlr->tft < CtftSAF){ 941 ctlr->tft += 1<<CtftSHIFT; 942 r = csr8r(ctlr, Bcr1) & ~CtftMASK; 943 csr8w(ctlr, Bcr1, r|ctlr->tft); 944 } 945 } 946 947 948 ctlr->totalt += lcycles() - t; 949 vt6105Mtransmit(edev); 950 t = lcycles(); 951 isr &= ~(Abti|Udfi|Tu|Txe|Ptx); 952 ctlr->tintr++; 953 } 954 if(isr) 955 panic("vt6105M: isr %4.4uX\n", isr); 956 } 957 ctlr->imr = imr; 958 csr16w(ctlr, Imr, ctlr->imr); 959 960 ctlr->totalt += lcycles() - t; 961 iunlock(&ctlr->clock); 962 } 963 964 static int 965 vt6105Mmiimicmd(Mii* mii, int pa, int ra, int cmd, int data) 966 { 967 Ctlr *ctlr; 968 int r, timeo; 969 970 ctlr = mii->ctlr; 971 972 csr8w(ctlr, Miicr, 0); 973 r = csr8r(ctlr, Phyadr); 974 csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa); 975 csr8w(ctlr, Phyadr, pa); 976 csr8w(ctlr, Miiadr, ra); 977 if(cmd == Wcmd) 978 csr16w(ctlr, Miidata, data); 979 csr8w(ctlr, Miicr, cmd); 980 981 for(timeo = 0; timeo < 10000; timeo++){ 982 if(!(csr8r(ctlr, Miicr) & cmd)) 983 break; 984 microdelay(1); 985 } 986 if(timeo >= 10000) 987 return -1; 988 989 if(cmd == Wcmd) 990 return 0; 991 return csr16r(ctlr, Miidata); 992 } 993 994 static int 995 vt6105Mmiimir(Mii* mii, int pa, int ra) 996 { 997 return vt6105Mmiimicmd(mii, pa, ra, Rcmd, 0); 998 } 999 1000 static int 1001 vt6105Mmiimiw(Mii* mii, int pa, int ra, int data) 1002 { 1003 return vt6105Mmiimicmd(mii, pa, ra, Wcmd, data); 1004 } 1005 1006 static int 1007 vt6105Mdetach(Ctlr* ctlr) 1008 { 1009 int revid, timeo; 1010 1011 /* 1012 * Reset power management registers. 1013 */ 1014 revid = pcicfgr8(ctlr->pcidev, PciRID); 1015 if(revid >= 0x40){ 1016 /* Set power state D0. */ 1017 csr8w(ctlr, Stickhw, csr8r(ctlr, Stickhw) & 0xFC); 1018 1019 /* Disable force PME-enable. */ 1020 csr8w(ctlr, Wolcgclr, 0x80); 1021 1022 /* Clear WOL config and status bits. */ 1023 csr8w(ctlr, Wolcrclr, 0xFF); 1024 csr8w(ctlr, Pwrcsrclr, 0xFF); 1025 } 1026 1027 /* 1028 * Soft reset the controller. 1029 */ 1030 csr16w(ctlr, Cr, Stop); 1031 csr16w(ctlr, Cr, Stop|Sfrst); 1032 for(timeo = 0; timeo < 10000; timeo++){ 1033 if(!(csr16r(ctlr, Cr) & Sfrst)) 1034 break; 1035 microdelay(1); 1036 } 1037 if(timeo >= 1000) 1038 return -1; 1039 1040 return 0; 1041 } 1042 1043 static void 1044 vt6105Mshutdown(Ether *ether) 1045 { 1046 Ctlr *ctlr = ether->ctlr; 1047 1048 vt6105Mdetach(ctlr); 1049 } 1050 1051 static int 1052 vt6105Mreset(Ctlr* ctlr) 1053 { 1054 MiiPhy *phy; 1055 int i, r, timeo; 1056 1057 if(vt6105Mdetach(ctlr) < 0) 1058 return -1; 1059 1060 /* 1061 * Load the MAC address into the PAR[01] 1062 * registers. 1063 */ 1064 r = csr8r(ctlr, Eecsr); 1065 csr8w(ctlr, Eecsr, Autold|r); 1066 for(timeo = 0; timeo < 100; timeo++){ 1067 if(!(csr8r(ctlr, Cr) & Autold)) 1068 break; 1069 microdelay(1); 1070 } 1071 if(timeo >= 100) 1072 return -1; 1073 1074 for(i = 0; i < Eaddrlen; i++) 1075 ctlr->par[i] = csr8r(ctlr, Par0+i); 1076 1077 /* 1078 * Configure DMA and Rx/Tx thresholds. 1079 * If the Rx/Tx threshold bits in Bcr[01] are 0 then 1080 * the thresholds are determined by Rcr/Tcr. 1081 */ 1082 r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK); 1083 csr8w(ctlr, Bcr0, r|Crft128|DmaSAF); 1084 r = csr8r(ctlr, Bcr1) & ~CtftMASK; 1085 csr8w(ctlr, Bcr1, r|ctlr->tft); 1086 1087 r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep); 1088 csr8w(ctlr, Rcr, r|Ab|Am); 1089 csr32w(ctlr, Mcfilt0, ~0UL); /* accept all multicast */ 1090 csr32w(ctlr, Mcfilt1, ~0UL); 1091 1092 r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0); 1093 csr8w(ctlr, Tcr, r); 1094 1095 /* 1096 * Link management. 1097 */ 1098 if((ctlr->mii = malloc(sizeof(Mii))) == nil) 1099 return -1; 1100 ctlr->mii->mir = vt6105Mmiimir; 1101 ctlr->mii->miw = vt6105Mmiimiw; 1102 ctlr->mii->ctlr = ctlr; 1103 1104 if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){ 1105 free(ctlr->mii); 1106 ctlr->mii = nil; 1107 return -1; 1108 } 1109 // print("oui %X phyno %d\n", phy->oui, phy->phyno); 1110 USED(phy); 1111 1112 if(miistatus(ctlr->mii) < 0){ 1113 // miireset(ctlr->mii); 1114 miiane(ctlr->mii, ~0, ~0, ~0); 1115 } 1116 1117 return 0; 1118 } 1119 1120 static void 1121 vt6105Mpci(void) 1122 { 1123 Pcidev *p; 1124 Ctlr *ctlr; 1125 int cls, port; 1126 1127 p = nil; 1128 while(p = pcimatch(p, 0, 0)){ 1129 if(p->ccrb != Pcibcnet || p->ccru != Pciscether) 1130 continue; 1131 1132 switch((p->did<<16)|p->vid){ 1133 default: 1134 continue; 1135 case (0x3053<<16)|0x1106: /* Rhine III-M vt6105M */ 1136 break; 1137 } 1138 1139 port = p->mem[0].bar & ~0x01; 1140 if(ioalloc(port, p->mem[0].size, 0, "vt6105M") < 0){ 1141 print("vt6105M: port 0x%uX in use\n", port); 1142 continue; 1143 } 1144 ctlr = malloc(sizeof(Ctlr)); 1145 if(ctlr == nil) { 1146 iofree(port); 1147 error(Enomem); 1148 } 1149 ctlr->port = port; 1150 ctlr->pcidev = p; 1151 ctlr->id = (p->did<<16)|p->vid; 1152 if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF) 1153 cls = 0x10; 1154 ctlr->cls = cls*4; 1155 if(ctlr->cls < sizeof(Ds)){ 1156 print("vt6105M: cls %d < sizeof(Ds)\n", ctlr->cls); 1157 iofree(port); 1158 free(ctlr); 1159 continue; 1160 } 1161 ctlr->tft = CtftSAF; 1162 1163 if(vt6105Mreset(ctlr)){ 1164 iofree(port); 1165 free(ctlr); 1166 continue; 1167 } 1168 pcisetbme(p); 1169 1170 if(vt6105Mctlrhead != nil) 1171 vt6105Mctlrtail->next = ctlr; 1172 else 1173 vt6105Mctlrhead = ctlr; 1174 vt6105Mctlrtail = ctlr; 1175 } 1176 } 1177 1178 static int 1179 vt6105Mpnp(Ether* edev) 1180 { 1181 Ctlr *ctlr; 1182 1183 if(vt6105Mctlrhead == nil) 1184 vt6105Mpci(); 1185 1186 /* 1187 * Any adapter matches if no edev->port is supplied, 1188 * otherwise the ports must match. 1189 */ 1190 for(ctlr = vt6105Mctlrhead; ctlr != nil; ctlr = ctlr->next){ 1191 if(ctlr->active) 1192 continue; 1193 if(edev->port == 0 || edev->port == ctlr->port){ 1194 ctlr->active = 1; 1195 break; 1196 } 1197 } 1198 if(ctlr == nil) 1199 return -1; 1200 1201 edev->ctlr = ctlr; 1202 edev->port = ctlr->port; 1203 edev->irq = ctlr->pcidev->intl; 1204 edev->tbdf = ctlr->pcidev->tbdf; 1205 /* 1206 * Set to 1000Mb/s to fool the bsz calculation. We need 1207 * something better, though. 1208 */ 1209 edev->mbps = 1000; 1210 memmove(edev->ea, ctlr->par, Eaddrlen); 1211 1212 /* 1213 * Linkage to the generic ethernet driver. 1214 */ 1215 edev->attach = vt6105Mattach; 1216 edev->transmit = vt6105Mtransmit; 1217 edev->interrupt = vt6105Minterrupt; 1218 edev->ifstat = vt6105Mifstat; 1219 edev->shutdown = vt6105Mshutdown; 1220 edev->ctl = nil; 1221 1222 edev->arg = edev; 1223 edev->promiscuous = vt6105Mpromiscuous; 1224 edev->multicast = vt6105Mmulticast; 1225 1226 edev->maxmtu = ETHERMAXTU+Bslop; 1227 1228 return 0; 1229 } 1230 1231 void 1232 ethervt6105mlink(void) 1233 { 1234 addethercard("vt6105M", vt6105Mpnp); 1235 } 1236