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