1 /* 2 * AMD79C970 3 * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus 4 * To do: 5 * finish this rewrite 6 */ 7 #include "u.h" 8 #include "../port/lib.h" 9 #include "mem.h" 10 #include "dat.h" 11 #include "fns.h" 12 #include "io.h" 13 #include "../port/error.h" 14 #include "../port/netif.h" 15 16 #include "etherif.h" 17 18 enum { 19 Lognrdre = 6, 20 Nrdre = (1<<Lognrdre),/* receive descriptor ring entries */ 21 Logntdre = 4, 22 Ntdre = (1<<Logntdre),/* transmit descriptor ring entries */ 23 24 Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */ 25 }; 26 27 enum { /* DWIO I/O resource map */ 28 Aprom = 0x0000, /* physical address */ 29 Rdp = 0x0010, /* register data port */ 30 Rap = 0x0014, /* register address port */ 31 Sreset = 0x0018, /* software reset */ 32 Bdp = 0x001C, /* bus configuration register data port */ 33 }; 34 35 enum { /* CSR0 */ 36 Init = 0x0001, /* begin initialisation */ 37 Strt = 0x0002, /* enable chip */ 38 Stop = 0x0004, /* disable chip */ 39 Tdmd = 0x0008, /* transmit demand */ 40 Txon = 0x0010, /* transmitter on */ 41 Rxon = 0x0020, /* receiver on */ 42 Iena = 0x0040, /* interrupt enable */ 43 Intr = 0x0080, /* interrupt flag */ 44 Idon = 0x0100, /* initialisation done */ 45 Tint = 0x0200, /* transmit interrupt */ 46 Rint = 0x0400, /* receive interrupt */ 47 Merr = 0x0800, /* memory error */ 48 Miss = 0x1000, /* missed frame */ 49 Cerr = 0x2000, /* collision */ 50 Babl = 0x4000, /* transmitter timeout */ 51 Err = 0x8000, /* Babl|Cerr|Miss|Merr */ 52 }; 53 54 enum { /* CSR3 */ 55 Bswp = 0x0004, /* byte swap */ 56 Emba = 0x0008, /* enable modified back-off algorithm */ 57 Dxmt2pd = 0x0010, /* disable transmit two part deferral */ 58 Lappen = 0x0020, /* look-ahead packet processing enable */ 59 }; 60 61 enum { /* CSR4 */ 62 ApadXmt = 0x0800, /* auto pad transmit */ 63 }; 64 65 enum { /* CSR15 */ 66 Prom = 0x8000, /* promiscuous mode */ 67 }; 68 69 typedef struct Iblock Iblock; 70 struct Iblock { /* Initialisation Block */ 71 ushort mode; 72 uchar rlen; /* upper 4 bits */ 73 uchar tlen; /* upper 4 bits */ 74 uchar padr[6]; 75 uchar res[2]; 76 uchar ladr[8]; 77 ulong rdra; 78 ulong tdra; 79 }; 80 81 typedef struct Dre Dre; 82 struct Dre { /* descriptor ring entry */ 83 ulong addr; 84 ulong md1; /* status|bcnt */ 85 ulong md2; /* rcc|rpc|mcnt */ 86 Block* bp; 87 }; 88 89 enum { /* md1 */ 90 Enp = 0x01000000, /* end of packet */ 91 Stp = 0x02000000, /* start of packet */ 92 RxBuff = 0x04000000, /* buffer error */ 93 Def = 0x04000000, /* deferred */ 94 Crc = 0x08000000, /* CRC error */ 95 One = 0x08000000, /* one retry needed */ 96 Oflo = 0x10000000, /* overflow error */ 97 More = 0x10000000, /* more than one retry needed */ 98 Fram = 0x20000000, /* framing error */ 99 RxErr = 0x40000000, /* Fram|Oflo|Crc|RxBuff */ 100 TxErr = 0x40000000, /* Uflo|Lcol|Lcar|Rtry */ 101 Own = 0x80000000, 102 }; 103 104 enum { /* md2 */ 105 Rtry = 0x04000000, /* failed after repeated retries */ 106 Lcar = 0x08000000, /* loss of carrier */ 107 Lcol = 0x10000000, /* late collision */ 108 Uflo = 0x40000000, /* underflow error */ 109 TxBuff = 0x80000000, /* buffer error */ 110 }; 111 112 typedef struct Ctlr Ctlr; 113 struct Ctlr { 114 Lock; 115 int port; 116 Pcidev* pcidev; 117 Ctlr* next; 118 int active; 119 120 int init; /* initialisation in progress */ 121 Iblock iblock; 122 123 Dre* rdr; /* receive descriptor ring */ 124 int rdrx; 125 126 Dre* tdr; /* transmit descriptor ring */ 127 int tdrh; /* host index into tdr */ 128 int tdri; /* interface index into tdr */ 129 int ntq; /* descriptors active */ 130 131 ulong rxbuff; /* receive statistics */ 132 ulong crc; 133 ulong oflo; 134 ulong fram; 135 136 ulong rtry; /* transmit statistics */ 137 ulong lcar; 138 ulong lcol; 139 ulong uflo; 140 ulong txbuff; 141 142 ulong merr; /* bobf is such a whiner */ 143 ulong miss; 144 ulong babl; 145 146 int (*ior)(Ctlr*, int); 147 void (*iow)(Ctlr*, int, int); 148 }; 149 150 static Ctlr* ctlrhead; 151 static Ctlr* ctlrtail; 152 153 /* 154 * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above. 155 * To get to 16-bit offsets, scale down with 0x10 staying the same. 156 */ 157 static int 158 io16r(Ctlr *c, int r) 159 { 160 if(r >= Rdp) 161 r = (r-Rdp)/2+Rdp; 162 return ins(c->port+r); 163 } 164 165 static void 166 io16w(Ctlr *c, int r, int v) 167 { 168 if(r >= Rdp) 169 r = (r-Rdp)/2+Rdp; 170 outs(c->port+r, v); 171 } 172 173 static int 174 io32r(Ctlr *c, int r) 175 { 176 return inl(c->port+r); 177 } 178 179 static void 180 io32w(Ctlr *c, int r, int v) 181 { 182 outl(c->port+r, v); 183 } 184 185 static void 186 attach(Ether*) 187 { 188 } 189 190 static long 191 ifstat(Ether* ether, void* a, long n, ulong offset) 192 { 193 char *p; 194 int len; 195 Ctlr *ctlr; 196 197 ctlr = ether->ctlr; 198 199 ether->crcs = ctlr->crc; 200 ether->frames = ctlr->fram; 201 ether->buffs = ctlr->rxbuff+ctlr->txbuff; 202 ether->overflows = ctlr->oflo; 203 204 if(n == 0) 205 return 0; 206 207 p = malloc(READSTR); 208 if(p == nil) 209 error(Enomem); 210 len = snprint(p, READSTR, "Rxbuff: %ld\n", ctlr->rxbuff); 211 len += snprint(p+len, READSTR-len, "Crc: %ld\n", ctlr->crc); 212 len += snprint(p+len, READSTR-len, "Oflo: %ld\n", ctlr->oflo); 213 len += snprint(p+len, READSTR-len, "Fram: %ld\n", ctlr->fram); 214 len += snprint(p+len, READSTR-len, "Rtry: %ld\n", ctlr->rtry); 215 len += snprint(p+len, READSTR-len, "Lcar: %ld\n", ctlr->lcar); 216 len += snprint(p+len, READSTR-len, "Lcol: %ld\n", ctlr->lcol); 217 len += snprint(p+len, READSTR-len, "Uflo: %ld\n", ctlr->uflo); 218 len += snprint(p+len, READSTR-len, "Txbuff: %ld\n", ctlr->txbuff); 219 len += snprint(p+len, READSTR-len, "Merr: %ld\n", ctlr->merr); 220 len += snprint(p+len, READSTR-len, "Miss: %ld\n", ctlr->miss); 221 snprint(p+len, READSTR-len, "Babl: %ld\n", ctlr->babl); 222 223 n = readstr(offset, a, n, p); 224 free(p); 225 226 return n; 227 } 228 229 static void 230 ringinit(Ctlr* ctlr) 231 { 232 Dre *dre; 233 234 /* 235 * Initialise the receive and transmit buffer rings. 236 * The ring entries must be aligned on 16-byte boundaries. 237 * 238 * This routine is protected by ctlr->init. 239 */ 240 if(ctlr->rdr == 0){ 241 ctlr->rdr = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0); 242 for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){ 243 dre->bp = iallocb(Rbsize); 244 if(dre->bp == nil) 245 panic("can't allocate ethernet receive ring\n"); 246 dre->addr = PADDR(dre->bp->rp); 247 dre->md2 = 0; 248 dre->md1 = Own|(-Rbsize & 0xFFFF); 249 } 250 } 251 ctlr->rdrx = 0; 252 253 if(ctlr->tdr == 0) 254 ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0); 255 memset(ctlr->tdr, 0, Ntdre*sizeof(Dre)); 256 ctlr->tdrh = ctlr->tdri = 0; 257 } 258 259 static void 260 promiscuous(void* arg, int on) 261 { 262 Ether *ether; 263 int x; 264 Ctlr *ctlr; 265 266 ether = arg; 267 ctlr = ether->ctlr; 268 269 /* 270 * Put the chip into promiscuous mode. First must wait until 271 * anyone transmitting is done, then stop the chip and put 272 * it in promiscuous mode. Restarting is made harder by the chip 273 * reloading the transmit and receive descriptor pointers with their 274 * base addresses when Strt is set (unlike the older Lance chip), 275 * so the rings must be re-initialised. 276 */ 277 ilock(ctlr); 278 if(ctlr->init){ 279 iunlock(ctlr); 280 return; 281 } 282 ctlr->init = 1; 283 iunlock(ctlr); 284 285 while(ctlr->ntq) 286 ; 287 288 ctlr->iow(ctlr, Rdp, Stop); 289 290 ctlr->iow(ctlr, Rap, 15); 291 x = ctlr->ior(ctlr, Rdp) & ~Prom; 292 if(on) 293 x |= Prom; 294 ctlr->iow(ctlr, Rdp, x); 295 ctlr->iow(ctlr, Rap, 0); 296 297 ringinit(ctlr); 298 299 ilock(ctlr); 300 ctlr->init = 0; 301 ctlr->iow(ctlr, Rdp, Iena|Strt); 302 iunlock(ctlr); 303 } 304 305 static void 306 multicast(void* arg, uchar*, int) 307 { 308 promiscuous(arg, 1); 309 } 310 311 static void 312 shutdown(Ether *ether) 313 { 314 Ctlr *ctlr; 315 316 ctlr = ether->ctlr; 317 ilock(ctlr); 318 io32r(ctlr, Sreset); 319 io16r(ctlr, Sreset); 320 iunlock(ctlr); 321 } 322 323 static void 324 txstart(Ether* ether) 325 { 326 Ctlr *ctlr; 327 Block *bp; 328 Dre *dre; 329 330 ctlr = ether->ctlr; 331 332 if(ctlr->init) 333 return; 334 335 while(ctlr->ntq < (Ntdre-1)){ 336 bp = qget(ether->oq); 337 if(bp == nil) 338 break; 339 340 /* 341 * Give ownership of the descriptor to the chip, 342 * increment the software ring descriptor pointer 343 * and tell the chip to poll. 344 * There's no need to pad to ETHERMINTU 345 * here as ApadXmt is set in CSR4. 346 */ 347 dre = &ctlr->tdr[ctlr->tdrh]; 348 dre->bp = bp; 349 dre->addr = PADDR(bp->rp); 350 dre->md2 = 0; 351 dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF); 352 ctlr->ntq++; 353 ctlr->iow(ctlr, Rdp, Iena|Tdmd); 354 ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre); 355 } 356 } 357 358 static void 359 transmit(Ether* ether) 360 { 361 Ctlr *ctlr; 362 363 ctlr = ether->ctlr; 364 ilock(ctlr); 365 txstart(ether); 366 iunlock(ctlr); 367 } 368 369 static void 370 interrupt(Ureg*, void* arg) 371 { 372 Ctlr *ctlr; 373 Ether *ether; 374 int csr0, len; 375 Dre *dre; 376 Block *bp; 377 378 ether = arg; 379 ctlr = ether->ctlr; 380 381 /* 382 * Acknowledge all interrupts and whine about those that shouldn't 383 * happen. 384 */ 385 intrloop: 386 csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF; 387 ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena); 388 if(csr0 & Merr) 389 ctlr->merr++; 390 if(csr0 & Miss) 391 ctlr->miss++; 392 if(csr0 & Babl) 393 ctlr->babl++; 394 //if(csr0 & (Babl|Miss|Merr)) 395 // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0); 396 if(!(csr0 & (Rint|Tint))) 397 return; 398 399 /* 400 * Receiver interrupt: run round the descriptor ring logging 401 * errors and passing valid receive data up to the higher levels 402 * until a descriptor is encountered still owned by the chip. 403 */ 404 if(csr0 & Rint){ 405 dre = &ctlr->rdr[ctlr->rdrx]; 406 while(!(dre->md1 & Own)){ 407 if(dre->md1 & RxErr){ 408 if(dre->md1 & RxBuff) 409 ctlr->rxbuff++; 410 if(dre->md1 & Crc) 411 ctlr->crc++; 412 if(dre->md1 & Oflo) 413 ctlr->oflo++; 414 if(dre->md1 & Fram) 415 ctlr->fram++; 416 } 417 else if(bp = iallocb(Rbsize)){ 418 len = (dre->md2 & 0x0FFF)-4; 419 dre->bp->wp = dre->bp->rp+len; 420 etheriq(ether, dre->bp, 1); 421 dre->bp = bp; 422 dre->addr = PADDR(bp->rp); 423 } 424 425 /* 426 * Finished with this descriptor, reinitialise it, 427 * give it back to the chip, then on to the next... 428 */ 429 dre->md2 = 0; 430 dre->md1 = Own|(-Rbsize & 0xFFFF); 431 432 ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre); 433 dre = &ctlr->rdr[ctlr->rdrx]; 434 } 435 } 436 437 /* 438 * Transmitter interrupt: wakeup anyone waiting for a free descriptor. 439 */ 440 if(csr0 & Tint){ 441 lock(ctlr); 442 while(ctlr->ntq){ 443 dre = &ctlr->tdr[ctlr->tdri]; 444 if(dre->md1 & Own) 445 break; 446 447 if(dre->md1 & TxErr){ 448 if(dre->md2 & Rtry) 449 ctlr->rtry++; 450 if(dre->md2 & Lcar) 451 ctlr->lcar++; 452 if(dre->md2 & Lcol) 453 ctlr->lcol++; 454 if(dre->md2 & Uflo) 455 ctlr->uflo++; 456 if(dre->md2 & TxBuff) 457 ctlr->txbuff++; 458 ether->oerrs++; 459 } 460 461 freeb(dre->bp); 462 463 ctlr->ntq--; 464 ctlr->tdri = NEXT(ctlr->tdri, Ntdre); 465 } 466 txstart(ether); 467 unlock(ctlr); 468 } 469 goto intrloop; 470 } 471 472 static void 473 amd79c970pci(void) 474 { 475 int port; 476 Ctlr *ctlr; 477 Pcidev *p; 478 479 p = nil; 480 while(p = pcimatch(p, 0x1022, 0x2000)){ 481 port = p->mem[0].bar & ~0x01; 482 if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){ 483 print("amd79c970: port 0x%uX in use\n", port); 484 continue; 485 } 486 ctlr = malloc(sizeof(Ctlr)); 487 if(ctlr == nil) 488 error(Enomem); 489 ctlr->port = p->mem[0].bar & ~0x01; 490 ctlr->pcidev = p; 491 492 if(ctlrhead != nil) 493 ctlrtail->next = ctlr; 494 else 495 ctlrhead = ctlr; 496 ctlrtail = ctlr; 497 } 498 } 499 500 static int 501 reset(Ether* ether) 502 { 503 int x; 504 uchar ea[Eaddrlen]; 505 Ctlr *ctlr; 506 507 if(ctlrhead == nil) 508 amd79c970pci(); 509 510 /* 511 * Any adapter matches if no port is supplied, 512 * otherwise the ports must match. 513 */ 514 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){ 515 if(ctlr->active) 516 continue; 517 if(ether->port == 0 || ether->port == ctlr->port){ 518 ctlr->active = 1; 519 break; 520 } 521 } 522 if(ctlr == nil) 523 return -1; 524 525 /* 526 * Allocate a controller structure and start to initialise it. 527 */ 528 ether->ctlr = ctlr; 529 ether->port = ctlr->port; 530 ether->irq = ctlr->pcidev->intl; 531 ether->tbdf = ctlr->pcidev->tbdf; 532 pcisetbme(ctlr->pcidev); 533 shutdown(ether); 534 ilock(ctlr); 535 ctlr->init = 1; 536 537 if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){ 538 ctlr->ior = io16r; 539 ctlr->iow = io16w; 540 }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){ 541 ctlr->ior = io32r; 542 ctlr->iow = io32w; 543 }else{ 544 print("#l%d: card doesn't talk right\n", ether->ctlrno); 545 iunlock(ctlr); 546 return -1; 547 } 548 549 ctlr->iow(ctlr, Rap, 88); 550 x = ctlr->ior(ctlr, Rdp); 551 ctlr->iow(ctlr, Rap, 89); 552 x |= ctlr->ior(ctlr, Rdp)<<16; 553 554 switch(x&0xFFFFFFF){ 555 case 0x2420003: /* PCnet/PCI 79C970 */ 556 case 0x2621003: /* PCnet/PCI II 79C970A */ 557 case 0x2625003: /* PCnet-FAST III 79C973 */ 558 break; 559 default: 560 print("#l%d: unknown PCnet card version 0x%.7ux\n", 561 ether->ctlrno, x&0xFFFFFFF); 562 iunlock(ctlr); 563 return -1; 564 } 565 566 /* 567 * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access. 568 * Set the auto pad transmit in CSR4. 569 */ 570 ctlr->iow(ctlr, Rap, 20); 571 ctlr->iow(ctlr, Bdp, 0x0002); 572 573 ctlr->iow(ctlr, Rap, 4); 574 x = ctlr->ior(ctlr, Rdp) & 0xFFFF; 575 ctlr->iow(ctlr, Rdp, ApadXmt|x); 576 577 ctlr->iow(ctlr, Rap, 0); 578 579 /* 580 * Check if the adapter's station address is to be overridden. 581 * If not, read it from the I/O-space and set in ether->ea prior to 582 * loading the station address in the initialisation block. 583 */ 584 memset(ea, 0, Eaddrlen); 585 if(!memcmp(ea, ether->ea, Eaddrlen)){ 586 x = ctlr->ior(ctlr, Aprom); 587 ether->ea[0] = x; 588 ether->ea[1] = x>>8; 589 if(ctlr->ior == io16r) 590 x = ctlr->ior(ctlr, Aprom+2); 591 else 592 x >>= 16; 593 ether->ea[2] = x; 594 ether->ea[3] = x>>8; 595 x = ctlr->ior(ctlr, Aprom+4); 596 ether->ea[4] = x; 597 ether->ea[5] = x>>8; 598 } 599 600 /* 601 * Start to fill in the initialisation block 602 * (must be DWORD aligned). 603 */ 604 ctlr->iblock.rlen = Lognrdre<<4; 605 ctlr->iblock.tlen = Logntdre<<4; 606 memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr)); 607 608 ringinit(ctlr); 609 ctlr->iblock.rdra = PADDR(ctlr->rdr); 610 ctlr->iblock.tdra = PADDR(ctlr->tdr); 611 612 /* 613 * Point the chip at the initialisation block and tell it to go. 614 * Mask the Idon interrupt and poll for completion. Strt and interrupt 615 * enables will be set later when attaching to the network. 616 */ 617 x = PADDR(&ctlr->iblock); 618 ctlr->iow(ctlr, Rap, 1); 619 ctlr->iow(ctlr, Rdp, x & 0xFFFF); 620 ctlr->iow(ctlr, Rap, 2); 621 ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF); 622 ctlr->iow(ctlr, Rap, 3); 623 ctlr->iow(ctlr, Rdp, Idon); 624 ctlr->iow(ctlr, Rap, 0); 625 ctlr->iow(ctlr, Rdp, Init); 626 627 while(!(ctlr->ior(ctlr, Rdp) & Idon)) 628 ; 629 630 /* 631 * We used to set CSR0 to Idon|Stop here, and then 632 * in attach change it to Iena|Strt. Apparently the simulated 633 * 79C970 in VMware never enables after a write of Idon|Stop, 634 * so we enable the device here now. 635 */ 636 ctlr->iow(ctlr, Rdp, Iena|Strt); 637 ctlr->init = 0; 638 iunlock(ctlr); 639 640 /* 641 * Linkage to the generic ethernet driver. 642 */ 643 ether->attach = attach; 644 ether->transmit = transmit; 645 ether->interrupt = interrupt; 646 ether->ifstat = ifstat; 647 648 ether->arg = ether; 649 ether->promiscuous = promiscuous; 650 ether->multicast = multicast; 651 ether->shutdown = shutdown; 652 653 return 0; 654 } 655 656 void 657 ether79c970link(void) 658 { 659 addethercard("AMD79C970", reset); 660 } 661