1 /* 2 Via Rhine driver, written for VT6102. 3 Uses the ethermii to control PHY. 4 5 Currently always copies on both, tx and rx. 6 rx side could be copy-free, and tx-side might be made 7 (almost) copy-free by using (possibly) two descriptors (if it allows 8 arbitrary tx lengths, which it should..): first for alignment and 9 second for rest of the frame. Rx-part should be worth doing. 10 */ 11 #include "u.h" 12 #include "lib.h" 13 #include "mem.h" 14 #include "dat.h" 15 #include "fns.h" 16 #include "io.h" 17 18 typedef struct QLock { int r; } QLock; 19 #define qlock(i) while(0) 20 #define qunlock(i) while(0) 21 #define iprint print 22 23 #include "etherif.h" 24 #include "ethermii.h" 25 26 enum { 27 Ntxd = 4, 28 Nrxd = 4, 29 Nwait = 50, 30 BIGSTR = 8192, 31 }; 32 33 typedef struct Desc Desc; 34 typedef struct Ctlr Ctlr; 35 36 struct Desc { 37 ulong stat; 38 ulong size; 39 ulong addr; 40 ulong next; 41 char *buf; 42 ulong pad[3]; 43 }; 44 45 struct Ctlr { 46 Pcidev *pci; 47 int attached; 48 int txused; 49 int txhead; 50 int txtail; 51 int rxtail; 52 ulong port; 53 54 Mii mii; 55 56 Desc *txd; /* wants to be aligned on 16-byte boundary */ 57 Desc *rxd; 58 59 QLock attachlck; 60 Lock tlock; 61 }; 62 63 #define ior8(c, r) (inb((c)->port+(r))) 64 #define iow8(c, r, b) (outb((c)->port+(r), (int)(b))) 65 #define ior16(c, r) (ins((c)->port+(r))) 66 #define ior32(c, r) (inl((c)->port+(r))) 67 #define iow16(c, r, w) (outs((c)->port+(r), (ushort)(w))) 68 #define iow32(c, r, l) (outl((c)->port+(r), (ulong)(l))) 69 70 /* names used everywhere else */ 71 #define csr8r ior8 72 #define csr8w iow8 73 #define csr16r ior16 74 #define csr16w iow16 75 #define csr32r ior32 76 #define csr32w iow32 77 78 enum Regs { 79 Eaddr = 0x0, 80 Rcr = 0x6, 81 Tcr = 0x7, 82 Cr = 0x8, 83 Isr = 0xc, 84 Imr = 0xe, 85 McastAddr = 0x10, 86 RxdAddr = 0x18, 87 TxdAddr = 0x1C, 88 Bcr0 = 0x6E, /* Bus Control */ 89 Bcr1 = 0x6F, 90 RhineMiiPhy = 0x6C, 91 RhineMiiSr = 0x6D, 92 RhineMiiCr = 0x70, 93 RhineMiiAddr = 0x71, 94 RhineMiiData = 0x72, 95 Eecsr = 0x74, 96 ConfigB = 0x79, 97 ConfigD = 0x7B, 98 MiscCr = 0x80, 99 HwSticky = 0x83, 100 MiscIsr = 0x84, 101 MiscImr = 0x86, 102 WolCrSet = 0xA0, 103 WolCfgSet = 0xA1, 104 WolCgSet = 0xA3, 105 WolCrClr = 0xA4, 106 PwrCfgClr = 0xA5, 107 WolCgClr = 0xA7, 108 }; 109 110 enum { /* Rcr */ 111 Sep = 0x01, /* Accept Error Packets */ 112 Ar = 0x02, /* Accept Small Packets */ 113 Am = 0x04, /* Accept Multicast */ 114 Ab = 0x08, /* Accept Broadcast */ 115 RxBcast = Ab, 116 Prom = 0x10, /* Accept Physical Address Packets */ 117 RxProm = Prom, 118 RrftMASK = 0xE0, /* Receive FIFO Threshold */ 119 RrftSHIFT = 5, 120 Rrft64 = 0<<RrftSHIFT, 121 Rrft32 = 1<<RrftSHIFT, 122 Rrft128 = 2<<RrftSHIFT, 123 Rrft256 = 3<<RrftSHIFT, 124 Rrft512 = 4<<RrftSHIFT, 125 Rrft768 = 5<<RrftSHIFT, 126 Rrft1024 = 6<<RrftSHIFT, 127 RrftSAF = 7<<RrftSHIFT, 128 }; 129 130 enum { /* Tcr */ 131 Lb0 = 0x02, /* Loopback Mode */ 132 Lb1 = 0x04, 133 Ofset = 0x08, /* Back-off Priority Selection */ 134 RtsfMASK = 0xE0, /* Transmit FIFO Threshold */ 135 RtsfSHIFT = 5, 136 Rtsf128 = 0<<RtsfSHIFT, 137 Rtsf256 = 1<<RtsfSHIFT, 138 Rtsf512 = 2<<RtsfSHIFT, 139 Rtsf1024 = 3<<RtsfSHIFT, 140 RtsfSAF = 7<<RtsfSHIFT, 141 }; 142 143 enum Crbits { 144 Init = 1<<0, 145 Start = 1<<1, 146 Stop = 1<<2, 147 RxOn = 1<<3, 148 TxOn = 1<<4, 149 Tdmd = 1<<5, 150 Rdmd = 1<<6, 151 EarlyRx = 1<<8, 152 Reserved0 = 1<<9, 153 FullDuplex = 1<<10, 154 NoAutoPoll = 1<<11, 155 Reserved1 = 1<<12, 156 Tdmd1 = 1<<13, 157 Rdmd1 = 1<<14, 158 Reset = 1<<15, 159 }; 160 161 enum Isrbits { 162 RxOk = 1<<0, 163 TxOk = 1<<1, 164 RxErr = 1<<2, 165 TxErr = 1<<3, 166 TxBufUdf = 1<<4, 167 RxBufLinkErr = 1<<5, 168 BusErr = 1<<6, 169 CrcOvf = 1<<7, 170 EarlyRxInt = 1<<8, 171 TxFifoUdf = 1<<9, 172 RxFifoOvf = 1<<10, 173 TxPktRace = 1<<11, 174 NoRxbuf = 1<<12, 175 TxCollision = 1<<13, 176 PortCh = 1<<14, 177 GPInt = 1<<15, 178 }; 179 180 enum { /* Bcr0 */ 181 DmaMASK = 0x07, /* DMA Length */ 182 DmaSHIFT = 0, 183 Dma32 = 0<<DmaSHIFT, 184 Dma64 = 1<<DmaSHIFT, 185 Dma128 = 2<<DmaSHIFT, 186 Dma256 = 3<<DmaSHIFT, 187 Dma512 = 4<<DmaSHIFT, 188 Dma1024 = 5<<DmaSHIFT, 189 DmaSAF = 7<<DmaSHIFT, 190 CrftMASK = 0x38, /* Rx FIFO Threshold */ 191 CrftSHIFT = 3, 192 Crft64 = 1<<CrftSHIFT, 193 Crft128 = 2<<CrftSHIFT, 194 Crft256 = 3<<CrftSHIFT, 195 Crft512 = 4<<CrftSHIFT, 196 Crft1024 = 5<<CrftSHIFT, 197 CrftSAF = 7<<CrftSHIFT, 198 Extled = 0x40, /* Extra LED Support Control */ 199 Med2 = 0x80, /* Medium Select Control */ 200 }; 201 202 enum { /* Bcr1 */ 203 PotMASK = 0x07, /* Polling Timer Interval */ 204 PotSHIFT = 0, 205 CtftMASK = 0x38, /* Tx FIFO Threshold */ 206 CtftSHIFT = 3, 207 Ctft64 = 1<<CtftSHIFT, 208 Ctft128 = 2<<CtftSHIFT, 209 Ctft256 = 3<<CtftSHIFT, 210 Ctft512 = 4<<CtftSHIFT, 211 Ctft1024 = 5<<CtftSHIFT, 212 CtftSAF = 7<<CtftSHIFT, 213 }; 214 215 216 enum Eecsrbits { 217 EeAutoLoad = 1<<5, 218 }; 219 220 enum Descbits { 221 OwnNic = 1<<31, /* stat */ 222 TxAbort = 1<<8, /* stat */ 223 TxError = 1<<15, /* stat */ 224 RxChainbuf = 1<<10, /* stat */ 225 RxChainStart = 1<<9, /* stat */ 226 RxChainEnd = 1<<8, /* stat */ 227 Chainbuf = 1<<15, /* size rx & tx*/ 228 TxDisableCrc = 1<<16, /* size */ 229 TxChainStart = 1<<21, /* size */ 230 TxChainEnd = 1<<22, /* size */ 231 TxInt = 1<<23, /* size */ 232 }; 233 234 enum RhineMiiCrbits { 235 Mdc = 1<<0, 236 Mdi = 1<<1, 237 Mdo = 1<<2, 238 Mdout = 1<<3, 239 Mdpm = 1<<4, 240 Wcmd = 1<<5, 241 Rcmd = 1<<6, 242 Mauto = 1<<7, 243 }; 244 245 static void 246 attach(Ether *edev) 247 { 248 Ctlr *ctlr; 249 Desc *txd, *rxd, *td, *rd; 250 Mii *mi; 251 MiiPhy *phy; 252 int i, s; 253 254 ctlr = edev->ctlr; 255 qlock(&ctlr->attachlck); 256 if (ctlr->attached == 0) { 257 txd = ctlr->txd; 258 rxd = ctlr->rxd; 259 for (i = 0; i < Ntxd; ++i) { 260 td = &txd[i]; 261 td->next = PCIWADDR(&txd[(i+1) % Ntxd]); 262 td->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0); 263 td->addr = PCIWADDR(td->buf); 264 td->size = 0; 265 coherence(); 266 td->stat = 0; 267 } 268 for (i = 0; i < Nrxd; ++i) { 269 rd = &rxd[i]; 270 rd->next = PCIWADDR(&rxd[(i+1) % Nrxd]); 271 rd->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0); 272 rd->addr = PCIWADDR(rd->buf); 273 rd->size = sizeof(Etherpkt)+4; 274 coherence(); 275 rd->stat = OwnNic; 276 } 277 278 ctlr->txhead = ctlr->txtail = ctlr->rxtail = 0; 279 mi = &ctlr->mii; 280 miistatus(mi); 281 phy = mi->curphy; 282 s = splhi(); 283 iow32(ctlr, TxdAddr, PCIWADDR(&txd[0])); 284 iow32(ctlr, RxdAddr, PCIWADDR(&rxd[0])); 285 iow16(ctlr, Cr, (phy->fd? FullDuplex: 0) | NoAutoPoll | TxOn | 286 RxOn | Start | Rdmd); 287 iow16(ctlr, Isr, 0xFFFF); 288 iow16(ctlr, Imr, 0xFFFF); 289 iow8(ctlr, MiscIsr, 0xFF); 290 iow8(ctlr, MiscImr, ~(3<<5)); 291 splx(s); 292 ctlr->attached = 1; 293 } 294 qunlock(&ctlr->attachlck); 295 } 296 297 static void 298 txstart(Ether *edev) 299 { 300 Ctlr *ctlr; 301 Desc *txd, *td; 302 int i, txused, n; 303 RingBuf *tb; 304 305 ctlr = edev->ctlr; 306 txd = ctlr->txd; 307 i = ctlr->txhead; 308 n = 0; 309 for (txused = ctlr->txused; txused < Ntxd; txused++) { 310 tb = &edev->tb[edev->ti]; 311 if(tb->owner != Interface) 312 break; 313 314 td = &txd[i]; 315 memmove(td->buf, tb->pkt, tb->len); 316 /* could reduce number of intrs here */ 317 td->size = tb->len | TxChainStart | TxChainEnd | TxInt; 318 coherence(); 319 td->stat = OwnNic; 320 i = (i + 1) % Ntxd; 321 n++; 322 323 tb->owner = Host; 324 edev->ti = NEXT(edev->ti, edev->ntb); 325 } 326 if (n) 327 iow16(ctlr, Cr, ior16(ctlr, Cr) | Tdmd); 328 329 ctlr->txhead = i; 330 ctlr->txused = txused; 331 } 332 333 static void 334 transmit(Ether *edev) 335 { 336 Ctlr *ctlr; 337 338 ctlr = edev->ctlr; 339 ilock(&ctlr->tlock); 340 txstart(edev); 341 iunlock(&ctlr->tlock); 342 } 343 344 static void 345 txcomplete(Ether *edev) 346 { 347 Ctlr *ctlr; 348 Desc *txd, *td; 349 int i, txused; 350 ulong stat; 351 352 ctlr = edev->ctlr; 353 txd = ctlr->txd; 354 i = ctlr->txtail; 355 for (txused = ctlr->txused; txused > 0; txused--) { 356 td = &txd[i]; 357 stat = td->stat; 358 if (stat & OwnNic) 359 break; 360 i = (i + 1) % Ntxd; 361 } 362 ctlr->txused = txused; 363 ctlr->txtail = i; 364 365 if (txused <= Ntxd/2) 366 txstart(edev); 367 } 368 369 static void 370 interrupt(Ureg *, void *arg) 371 { 372 Ether *edev; 373 Ctlr *ctlr; 374 RingBuf *rb; 375 ushort isr, misr; 376 ulong stat; 377 Desc *rxd, *rd; 378 int i, n, size; 379 380 edev = (Ether*)arg; 381 ctlr = edev->ctlr; 382 iow16(ctlr, Imr, 0); 383 isr = ior16(ctlr, Isr); 384 iow16(ctlr, Isr, 0xFFFF); 385 /* don't care about used defined intrs */ 386 misr = ior16(ctlr, MiscIsr) & ~(3<<5); 387 388 if (isr & RxOk) { 389 rxd = ctlr->rxd; 390 i = ctlr->rxtail; 391 392 n = 0; 393 while ((rxd[i].stat & OwnNic) == 0) { 394 rd = &rxd[i]; 395 stat = rd->stat; 396 if (stat & 0xFF) 397 iprint("rx: %lux\n", stat & 0xFF); 398 size = ((rd->stat>>16) & (2048-1)) - 4; 399 400 rb = &edev->rb[edev->ri]; 401 if(rb->owner == Interface){ 402 rb->owner = Host; 403 rb->len = size; 404 memmove(rb->pkt, rd->buf, size); 405 edev->ri = NEXT(edev->ri, edev->nrb); 406 } 407 408 rd->size = sizeof(Etherpkt)+4; 409 coherence(); 410 rd->stat = OwnNic; 411 i = (i + 1) % Nrxd; 412 n++; 413 } 414 if (n) 415 iow16(ctlr, Cr, ior16(ctlr, Cr) | Rdmd); 416 ctlr->rxtail = i; 417 isr &= ~RxOk; 418 } 419 if (isr & TxOk) { 420 txcomplete(edev); 421 isr &= ~TxOk; 422 } 423 if (isr | misr) 424 iprint("etherrhine: unhandled irq(s). isr:%x misr:%x\n", 425 isr, misr); 426 iow16(ctlr, Imr, 0xFFFF); 427 } 428 429 static int 430 miiread(Mii *mii, int phy, int reg) 431 { 432 Ctlr *ctlr; 433 int n; 434 435 ctlr = mii->ctlr; 436 437 n = Nwait; 438 while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd)) 439 microdelay(1); 440 if (n == Nwait) 441 iprint("etherrhine: miiread: timeout\n"); 442 443 iow8(ctlr, RhineMiiCr, 0); 444 iow8(ctlr, RhineMiiPhy, phy); 445 iow8(ctlr, RhineMiiAddr, reg); 446 iow8(ctlr, RhineMiiCr, Rcmd); 447 448 n = Nwait; 449 while (n-- && ior8(ctlr, RhineMiiCr) & Rcmd) 450 microdelay(1); 451 if (n == Nwait) 452 iprint("etherrhine: miiread: timeout\n"); 453 454 return ior16(ctlr, RhineMiiData); 455 } 456 457 static int 458 miiwrite(Mii *mii, int phy, int reg, int data) 459 { 460 int n; 461 Ctlr *ctlr; 462 463 ctlr = mii->ctlr; 464 465 n = Nwait; 466 while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd)) 467 microdelay(1); 468 if (n == Nwait) 469 iprint("etherrhine: miiwrite: timeout\n"); 470 471 iow8(ctlr, RhineMiiCr, 0); 472 iow8(ctlr, RhineMiiPhy, phy); 473 iow8(ctlr, RhineMiiAddr, reg); 474 iow16(ctlr, RhineMiiData, data); 475 iow8(ctlr, RhineMiiCr, Wcmd); 476 477 n = Nwait; 478 while (n-- && ior8(ctlr, RhineMiiCr) & Wcmd) 479 microdelay(1); 480 if (n == Nwait) 481 iprint("etherrhine: miiwrite: timeout\n"); 482 483 return 0; 484 } 485 486 static void 487 reset(Ctlr* ctlr) 488 { 489 int r, timeo; 490 491 /* 492 * Soft reset the controller. 493 */ 494 csr16w(ctlr, Cr, Stop); 495 csr16w(ctlr, Cr, Stop|Reset); 496 for(timeo = 0; timeo < 10000; timeo++){ 497 if(!(csr16r(ctlr, Cr) & Reset)) 498 break; 499 microdelay(1); 500 } 501 if(timeo >= 1000) 502 return; 503 504 /* 505 * Load the MAC address into the PAR[01] 506 * registers. 507 */ 508 r = csr8r(ctlr, Eecsr); 509 csr8w(ctlr, Eecsr, EeAutoLoad|r); 510 for(timeo = 0; timeo < 100; timeo++){ 511 if(!(csr8r(ctlr, Cr) & EeAutoLoad)) 512 break; 513 microdelay(1); 514 } 515 if(timeo >= 100) 516 return; 517 518 /* 519 * Configure DMA and Rx/Tx thresholds. 520 * If the Rx/Tx threshold bits in Bcr[01] are 0 then 521 * the thresholds are determined by Rcr/Tcr. 522 */ 523 r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK); 524 csr8w(ctlr, Bcr0, r|Crft64|Dma64); 525 r = csr8r(ctlr, Bcr1) & ~CtftMASK; 526 csr8w(ctlr, Bcr1, r|Ctft64); 527 528 r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep); 529 csr8w(ctlr, Rcr, r|Ab|Am); 530 531 r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0); 532 csr8w(ctlr, Tcr, r); 533 } 534 535 static void 536 detach(Ether* edev) 537 { 538 reset(edev->ctlr); 539 } 540 541 static void 542 init(Ether *edev) 543 { 544 Ctlr *ctlr; 545 int i; 546 547 ctlr = edev->ctlr; 548 ilock(&ctlr->tlock); 549 550 pcisetbme(ctlr->pci); 551 reset(ctlr); 552 553 iow8(ctlr, Eecsr, ior8(ctlr, Eecsr) | EeAutoLoad); 554 for (i = 0; i < Nwait; ++i) { 555 if ((ior8(ctlr, Eecsr) & EeAutoLoad) == 0) 556 break; 557 delay(5); 558 } 559 if (i >= Nwait) 560 iprint("etherrhine: eeprom autoload timeout\n"); 561 562 for (i = 0; i < Eaddrlen; ++i) 563 edev->ea[i] = ior8(ctlr, Eaddr + i); 564 565 ctlr->mii.mir = miiread; 566 ctlr->mii.miw = miiwrite; 567 ctlr->mii.ctlr = ctlr; 568 569 if(mii(&ctlr->mii, ~0) == 0 || ctlr->mii.curphy == nil){ 570 iunlock(&ctlr->tlock); 571 iprint("etherrhine: init mii failure\n"); 572 return; 573 } 574 for (i = 0; i < NMiiPhy; ++i) 575 if (ctlr->mii.phy[i]) 576 if (ctlr->mii.phy[i]->oui != 0xFFFFF) 577 ctlr->mii.curphy = ctlr->mii.phy[i]; 578 miistatus(&ctlr->mii); 579 580 iow16(ctlr, Imr, 0); 581 iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop); 582 583 iunlock(&ctlr->tlock); 584 } 585 586 static Pcidev * 587 rhinematch(ulong) 588 { 589 static int nrhines = 0; 590 int nfound = 0; 591 Pcidev *p = nil; 592 593 while(p = pcimatch(p, 0x1106, 0)){ 594 if(p->ccrb != Pcibcnet || p->ccru != Pciscether) 595 continue; 596 switch((p->did<<16)|p->vid){ 597 default: 598 continue; 599 case (0x3053<<16)|0x1106: /* Rhine III vt6105m (Soekris) */ 600 case (0x3065<<16)|0x1106: /* Rhine II */ 601 case (0x3106<<16)|0x1106: /* Rhine III */ 602 if (++nfound > nrhines) { 603 nrhines++; 604 return p; 605 } 606 break; 607 } 608 } 609 return p; 610 } 611 612 int 613 rhinepnp(Ether *edev) 614 { 615 Pcidev *p; 616 Ctlr *ctlr; 617 ulong port; 618 619 if (edev->attach) 620 return 0; 621 p = rhinematch(edev->port); 622 if (p == nil) 623 return -1; 624 625 port = p->mem[0].bar & ~1; 626 627 if ((ctlr = malloc(sizeof(Ctlr))) == nil) { 628 print("etherrhine: couldn't allocate memory for ctlr\n"); 629 return -1; 630 } 631 memset(ctlr, 0, sizeof(Ctlr)); 632 ctlr->txd = xspanalloc(sizeof(Desc) * Ntxd, 16, 0); 633 ctlr->rxd = xspanalloc(sizeof(Desc) * Nrxd, 16, 0); 634 635 ctlr->pci = p; 636 ctlr->port = port; 637 638 edev->ctlr = ctlr; 639 edev->port = ctlr->port; 640 edev->irq = p->intl; 641 edev->tbdf = p->tbdf; 642 643 init(edev); 644 645 edev->attach = attach; 646 edev->transmit = transmit; 647 edev->interrupt = interrupt; 648 edev->detach = detach; 649 650 return 0; 651 } 652 653 int 654 vt6102pnp(Ether *edev) 655 { 656 return rhinepnp(edev); 657 } 658