1 /* 2 * FCCn ethernet 3 */ 4 5 #include "u.h" 6 #include "../port/lib.h" 7 #include "mem.h" 8 #include "dat.h" 9 #include "fns.h" 10 #include "io.h" 11 #include "imm.h" 12 #include "../port/error.h" 13 #include "../port/netif.h" 14 15 #include "etherif.h" 16 #include "../ppc/ethermii.h" 17 18 #define DBG 1 19 20 enum { 21 Nrdre = 128, /* receive descriptor ring entries */ 22 Ntdre = 128, /* transmit descriptor ring entries */ 23 24 Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */ 25 Bufsize = Rbsize+CACHELINESZ, /* extra room for alignment */ 26 }; 27 28 enum { 29 30 /* ether-specific Rx BD bits */ 31 RxMiss= SBIT(7), 32 RxeLG= SBIT(10), 33 RxeNO= SBIT(11), 34 RxeSH= SBIT(12), 35 RxeCR= SBIT(13), 36 RxeOV= SBIT(14), 37 RxeCL= SBIT(15), 38 RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */ 39 40 /* ether-specific Tx BD bits */ 41 TxPad= SBIT(1), /* pad short frames */ 42 TxTC= SBIT(5), /* transmit CRC */ 43 TxeDEF= SBIT(6), 44 TxeHB= SBIT(7), 45 TxeLC= SBIT(8), 46 TxeRL= SBIT(9), 47 TxeUN= SBIT(14), 48 TxeCSL= SBIT(15), 49 50 /* psmr */ 51 CRCE= BIT(24), /* Ethernet CRC */ 52 FCE= BIT(10), /* flow control */ 53 PRO= BIT(9), /* promiscuous mode */ 54 FDE= BIT(5), /* full duplex ethernet */ 55 LPB= BIT(3), /* local protect bit */ 56 57 /* gfmr */ 58 ENET= 0xc, /* ethernet mode */ 59 ENT= BIT(27), 60 ENR= BIT(26), 61 TCI= BIT(2), 62 63 /* FCC function code register */ 64 GBL= 0x20, 65 BO= 0x18, 66 EB= 0x10, /* Motorola byte order */ 67 TC2= 0x04, 68 DTB= 0x02, 69 BDB= 0x01, 70 71 /* FCC Event/Mask bits */ 72 GRA= SBIT(8), 73 RXC= SBIT(9), 74 TXC= SBIT(10), 75 TXE= SBIT(11), 76 RXF= SBIT(12), 77 BSY= SBIT(13), 78 TXB= SBIT(14), 79 RXB= SBIT(15), 80 }; 81 82 enum { /* Mcr */ 83 MDIread = 0x60020000, /* read opcode */ 84 MDIwrite = 0x50020000, /* write opcode */ 85 }; 86 87 typedef struct Etherparam Etherparam; 88 struct Etherparam { 89 /*0x00*/ FCCparam; 90 /*0x3c*/ ulong stat_buf; 91 /*0x40*/ ulong cam_ptr; 92 /*0x44*/ ulong cmask; 93 /*0x48*/ ulong cpres; 94 /*0x4c*/ ulong crcec; 95 /*0x50*/ ulong alec; 96 /*0x54*/ ulong disfc; 97 /*0x58*/ ushort retlim; 98 /*0x5a*/ ushort retcnt; 99 /*0x5c*/ ushort p_per; 100 /*0x5e*/ ushort boff_cnt; 101 /*0x60*/ ulong gaddr[2]; 102 /*0x68*/ ushort tfcstat; 103 /*0x6a*/ ushort tfclen; 104 /*0x6c*/ ulong tfcptr; 105 /*0x70*/ ushort mflr; 106 /*0x72*/ ushort paddr[3]; 107 /*0x78*/ ushort ibd_cnt; 108 /*0x7a*/ ushort ibd_start; 109 /*0x7c*/ ushort ibd_end; 110 /*0x7e*/ ushort tx_len; 111 /*0x80*/ uchar ibd_base[32]; 112 /*0xa0*/ ulong iaddr[2]; 113 /*0xa8*/ ushort minflr; 114 /*0xaa*/ ushort taddr[3]; 115 /*0xb0*/ ushort padptr; 116 /*0xb2*/ ushort Rsvdb2; 117 /*0xb4*/ ushort cf_range; 118 /*0xb6*/ ushort max_b; 119 /*0xb8*/ ushort maxd1; 120 /*0xba*/ ushort maxd2; 121 /*0xbc*/ ushort maxd; 122 /*0xbe*/ ushort dma_cnt; 123 /*0xc0*/ ulong octc; 124 /*0xc4*/ ulong colc; 125 /*0xc8*/ ulong broc; 126 /*0xcc*/ ulong mulc; 127 /*0xd0*/ ulong uspc; 128 /*0xd4*/ ulong frgc; 129 /*0xd8*/ ulong ospc; 130 /*0xdc*/ ulong jbrc; 131 /*0xe0*/ ulong p64c; 132 /*0xe4*/ ulong p65c; 133 /*0xe8*/ ulong p128c; 134 /*0xec*/ ulong p256c; 135 /*0xf0*/ ulong p512c; 136 /*0xf4*/ ulong p1024c; 137 /*0xf8*/ ulong cam_buf; 138 /*0xfc*/ ulong Rsvdfc; 139 /*0x100*/ 140 }; 141 142 typedef struct Ctlr Ctlr; 143 struct Ctlr { 144 Lock; 145 int fccid; 146 int port; 147 ulong pmdio; 148 ulong pmdck; 149 int init; 150 int active; 151 int duplex; /* 1 == full */ 152 FCC* fcc; 153 154 Ring; 155 Block* rcvbufs[Nrdre]; 156 Mii* mii; 157 Timer; 158 159 ulong interrupts; /* statistics */ 160 ulong deferred; 161 ulong heartbeat; 162 ulong latecoll; 163 ulong retrylim; 164 ulong underrun; 165 ulong overrun; 166 ulong carrierlost; 167 ulong retrycount; 168 }; 169 170 static int fccirq[] = {0x20, 0x21, 0x22}; 171 static int fccid[] = {FCC1ID, FCC2ID, FCC3ID}; 172 173 #ifdef DBG 174 ulong fccrhisto[16]; 175 ulong fccthisto[16]; 176 ulong fccrthisto[16]; 177 ulong fcctrhisto[16]; 178 ulong ehisto[0x80]; 179 #endif 180 181 static int fccmiimir(Mii*, int, int); 182 static int fccmiimiw(Mii*, int, int, int); 183 static void fccltimer(Ureg*, Timer*); 184 185 static void 186 attach(Ether *ether) 187 { 188 Ctlr *ctlr; 189 190 ctlr = ether->ctlr; 191 ilock(ctlr); 192 ctlr->active = 1; 193 ctlr->fcc->gfmr |= ENR|ENT; 194 iunlock(ctlr); 195 ctlr->tmode = Tperiodic; 196 ctlr->tf = fccltimer; 197 ctlr->ta = ether; 198 ctlr->tns = 5000000000LL; /* 5 seconds */ 199 timeradd(ctlr); 200 } 201 202 static void 203 closed(Ether *ether) 204 { 205 Ctlr *ctlr; 206 207 ctlr = ether->ctlr; 208 ilock(ctlr); 209 ctlr->active = 0; 210 ctlr->fcc->gfmr &= ~(ENR|ENT); 211 iunlock(ctlr); 212 print("Ether closed\n"); 213 } 214 215 static void 216 promiscuous(void* arg, int on) 217 { 218 Ether *ether; 219 Ctlr *ctlr; 220 221 ether = (Ether*)arg; 222 ctlr = ether->ctlr; 223 224 ilock(ctlr); 225 if(on || ether->nmaddr) 226 ctlr->fcc->fpsmr |= PRO; 227 else 228 ctlr->fcc->fpsmr &= ~PRO; 229 iunlock(ctlr); 230 } 231 232 static void 233 multicast(void* arg, uchar *addr, int on) 234 { 235 Ether *ether; 236 Ctlr *ctlr; 237 238 USED(addr, on); /* if on, could SetGroupAddress; if !on, it's hard */ 239 240 ether = (Ether*)arg; 241 ctlr = ether->ctlr; 242 243 ilock(ctlr); 244 if(ether->prom || ether->nmaddr) 245 ctlr->fcc->fpsmr |= PRO; 246 else 247 ctlr->fcc->fpsmr &= ~PRO; 248 iunlock(ctlr); 249 } 250 251 static void 252 txstart(Ether *ether) 253 { 254 int len; 255 Ctlr *ctlr; 256 Block *b; 257 BD *dre; 258 259 ctlr = ether->ctlr; 260 if(ctlr->init) 261 return; 262 while(ctlr->ntq < Ntdre-1){ 263 b = qget(ether->oq); 264 if(b == 0) 265 break; 266 267 dre = &ctlr->tdr[ctlr->tdrh]; 268 dczap(dre, sizeof(BD)); 269 if(dre->status & BDReady) 270 panic("ether: txstart"); 271 272 /* 273 * Give ownership of the descriptor to the chip, increment the 274 * software ring descriptor pointer and tell the chip to poll. 275 */ 276 len = BLEN(b); 277 if(ctlr->txb[ctlr->tdrh] != nil) 278 panic("fcc/ether: txstart"); 279 ctlr->txb[ctlr->tdrh] = b; 280 if((ulong)b->rp&1) 281 panic("fcc/ether: txstart align"); /* TO DO: ensure alignment */ 282 dre->addr = PADDR(b->rp); 283 dre->length = len; 284 dcflush(b->rp, len); 285 dcflush(dre, sizeof(BD)); 286 dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC; 287 dcflush(dre, sizeof(BD)); 288 /* ctlr->fcc->ftodr = 1<<15; /* transmit now; Don't do this according to errata */ 289 ctlr->ntq++; 290 ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre); 291 } 292 } 293 294 static void 295 transmit(Ether* ether) 296 { 297 Ctlr *ctlr; 298 299 ctlr = ether->ctlr; 300 ilock(ctlr); 301 txstart(ether); 302 iunlock(ctlr); 303 } 304 305 static void 306 interrupt(Ureg*, void *arg) 307 { 308 int len, status, rcvd, xmtd, restart; 309 ushort events; 310 Ctlr *ctlr; 311 BD *dre; 312 Block *b, *nb; 313 Ether *ether = arg; 314 315 ctlr = ether->ctlr; 316 if(!ctlr->active) 317 return; /* not ours */ 318 319 /* 320 * Acknowledge all interrupts and whine about those that shouldn't 321 * happen. 322 */ 323 events = ctlr->fcc->fcce; 324 ctlr->fcc->fcce = events; /* clear events */ 325 326 #ifdef DBG 327 ehisto[events & 0x7f]++; 328 #endif 329 330 ctlr->interrupts++; 331 332 if(events & BSY) 333 ctlr->overrun++; 334 if(events & TXE) 335 ether->oerrs++; 336 337 #ifdef DBG 338 rcvd = xmtd = 0; 339 #endif 340 /* 341 * Receiver interrupt: run round the descriptor ring logging 342 * errors and passing valid receive data up to the higher levels 343 * until we encounter a descriptor still owned by the chip. 344 */ 345 if(events & RXF){ 346 dre = &ctlr->rdr[ctlr->rdrx]; 347 dczap(dre, sizeof(BD)); 348 while(((status = dre->status) & BDEmpty) == 0){ 349 rcvd++; 350 if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){ 351 if(status & (RxeLG|RxeSH)) 352 ether->buffs++; 353 if(status & RxeNO) 354 ether->frames++; 355 if(status & RxeCR) 356 ether->crcs++; 357 if(status & RxeOV) 358 ether->overflows++; 359 print("eth rx: %ux\n", status); 360 }else{ 361 /* 362 * We have a packet. Read it in. 363 */ 364 len = dre->length-4; 365 b = ctlr->rcvbufs[ctlr->rdrx]; 366 assert(dre->addr == PADDR(b->rp)); 367 dczap(b->rp, len); 368 if(nb = iallocb(Bufsize)){ 369 b->wp += len; 370 etheriq(ether, b, 1); 371 b = nb; 372 b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1)); 373 b->wp = b->rp; 374 ctlr->rcvbufs[ctlr->rdrx] = b; 375 ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp); 376 }else 377 ether->soverflows++; 378 } 379 380 /* 381 * Finished with this descriptor, reinitialise it, 382 * give it back to the chip, then on to the next... 383 */ 384 dre->length = 0; 385 dre->status = (status & BDWrap) | BDEmpty | BDInt; 386 dcflush(dre, sizeof(BD)); 387 388 ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre); 389 dre = &ctlr->rdr[ctlr->rdrx]; 390 dczap(dre, sizeof(BD)); 391 } 392 } 393 394 /* 395 * Transmitter interrupt: handle anything queued for a free descriptor. 396 */ 397 if(events & (TXB|TXE)){ 398 ilock(ctlr); 399 restart = 0; 400 while(ctlr->ntq){ 401 dre = &ctlr->tdr[ctlr->tdri]; 402 dczap(dre, sizeof(BD)); 403 status = dre->status; 404 if(status & BDReady) 405 break; 406 if(status & TxeDEF) 407 ctlr->deferred++; 408 if(status & TxeHB) 409 ctlr->heartbeat++; 410 if(status & TxeLC) 411 ctlr->latecoll++; 412 if(status & TxeRL) 413 ctlr->retrylim++; 414 if(status & TxeUN) 415 ctlr->underrun++; 416 if(status & TxeCSL) 417 ctlr->carrierlost++; 418 if(status & (TxeLC|TxeRL|TxeUN)) 419 restart = 1; 420 ctlr->retrycount += (status>>2)&0xF; 421 b = ctlr->txb[ctlr->tdri]; 422 if(b == nil) 423 panic("fcce/interrupt: bufp"); 424 ctlr->txb[ctlr->tdri] = nil; 425 freeb(b); 426 ctlr->ntq--; 427 ctlr->tdri = NEXT(ctlr->tdri, Ntdre); 428 xmtd++; 429 } 430 431 if(restart){ 432 ctlr->fcc->gfmr &= ~ENT; 433 delay(10); 434 ctlr->fcc->gfmr |= ENT; 435 cpmop(RestartTx, ctlr->fccid, 0xc); 436 } 437 txstart(ether); 438 iunlock(ctlr); 439 } 440 #ifdef DBG 441 if(rcvd >= nelem(fccrhisto)) 442 rcvd = nelem(fccrhisto) - 1; 443 if(xmtd >= nelem(fccthisto)) 444 xmtd = nelem(fccthisto) - 1; 445 if(rcvd) 446 fcctrhisto[xmtd]++; 447 else 448 fccthisto[xmtd]++; 449 if(xmtd) 450 fccrthisto[rcvd]++; 451 else 452 fccrhisto[rcvd]++; 453 #endif 454 } 455 456 static long 457 ifstat(Ether* ether, void* a, long n, ulong offset) 458 { 459 char *p; 460 int len, i, r; 461 Ctlr *ctlr; 462 MiiPhy *phy; 463 464 if(n == 0) 465 return 0; 466 467 ctlr = ether->ctlr; 468 469 p = malloc(READSTR); 470 len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts); 471 len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost); 472 len += snprint(p+len, READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat); 473 len += snprint(p+len, READSTR-len, "retrylimit: %lud\n", ctlr->retrylim); 474 len += snprint(p+len, READSTR-len, "retrycount: %lud\n", ctlr->retrycount); 475 len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", ctlr->latecoll); 476 len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", ctlr->overrun); 477 len += snprint(p+len, READSTR-len, "txunderruns: %lud\n", ctlr->underrun); 478 len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->deferred); 479 miistatus(ctlr->mii); 480 phy = ctlr->mii->curphy; 481 len += snprint(p+len, READSTR-len, "phy: link=%d, tfc=%d, rfc=%d, speed=%d, fd=%d\n", 482 phy->link, phy->tfc, phy->rfc, phy->speed, phy->fd); 483 484 #ifdef DBG 485 if(ctlr->mii != nil && ctlr->mii->curphy != nil){ 486 len += snprint(p+len, READSTR, "phy: "); 487 for(i = 0; i < NMiiPhyr; i++){ 488 if(i && ((i & 0x07) == 0)) 489 len += snprint(p+len, READSTR-len, "\n "); 490 r = miimir(ctlr->mii, i); 491 len += snprint(p+len, READSTR-len, " %4.4uX", r); 492 } 493 snprint(p+len, READSTR-len, "\n"); 494 } 495 #endif 496 snprint(p+len, READSTR-len, "\n"); 497 498 n = readstr(offset, a, n, p); 499 free(p); 500 501 return n; 502 } 503 504 /* 505 * This follows the MPC8260 user guide: section28.9's initialisation sequence. 506 */ 507 static int 508 fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea) 509 { 510 int i; 511 Etherparam *p; 512 MiiPhy *phy; 513 514 /* Turn Ethernet off */ 515 fcc->gfmr &= ~(ENR | ENT); 516 517 ioplock(); 518 switch(ctlr->port) { 519 default: 520 iopunlock(); 521 return -1; 522 case 0: 523 /* Step 1 (Section 28.9), write the parallel ports */ 524 ctlr->pmdio = 0x01000000; 525 ctlr->pmdck = 0x08000000; 526 imm->port[0].pdir &= ~A1dir0; 527 imm->port[0].pdir |= A1dir1; 528 imm->port[0].psor &= ~A1psor0; 529 imm->port[0].psor |= A1psor1; 530 imm->port[0].ppar |= (A1dir0 | A1dir1); 531 /* Step 2, Port C clocks */ 532 imm->port[2].psor &= ~0x00000c00; 533 imm->port[2].pdir &= ~0x00000c00; 534 imm->port[2].ppar |= 0x00000c00; 535 imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck); 536 imm->port[3].podr |= ctlr->pmdio; 537 imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck); 538 imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck); 539 eieio(); 540 /* Step 3, Serial Interface clock routing */ 541 imm->cmxfcr &= ~0xff000000; /* Clock mask */ 542 imm->cmxfcr |= 0x37000000; /* Clock route */ 543 break; 544 545 case 1: 546 /* Step 1 (Section 28.9), write the parallel ports */ 547 ctlr->pmdio = 0x00400000; 548 ctlr->pmdck = 0x00200000; 549 imm->port[1].pdir &= ~B2dir0; 550 imm->port[1].pdir |= B2dir1; 551 imm->port[1].psor &= ~B2psor0; 552 imm->port[1].psor |= B2psor1; 553 imm->port[1].ppar |= (B2dir0 | B2dir1); 554 /* Step 2, Port C clocks */ 555 imm->port[2].psor &= ~0x00003000; 556 imm->port[2].pdir &= ~0x00003000; 557 imm->port[2].ppar |= 0x00003000; 558 559 imm->port[2].pdat |= (ctlr->pmdio | ctlr->pmdck); 560 imm->port[2].podr |= ctlr->pmdio; 561 imm->port[2].pdir |= (ctlr->pmdio | ctlr->pmdck); 562 imm->port[2].ppar &= ~(ctlr->pmdio | ctlr->pmdck); 563 eieio(); 564 /* Step 3, Serial Interface clock routing */ 565 imm->cmxfcr &= ~0x00ff0000; 566 imm->cmxfcr |= 0x00250000; 567 break; 568 569 case 2: 570 /* Step 1 (Section 28.9), write the parallel ports */ 571 imm->port[1].pdir &= ~B3dir0; 572 imm->port[1].pdir |= B3dir1; 573 imm->port[1].psor &= ~B3psor0; 574 imm->port[1].psor |= B3psor1; 575 imm->port[1].ppar |= (B3dir0 | B3dir1); 576 /* Step 2, Port C clocks */ 577 imm->port[2].psor &= ~0x0000c000; 578 imm->port[2].pdir &= ~0x0000c000; 579 imm->port[2].ppar |= 0x0000c000; 580 imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck); 581 imm->port[3].podr |= ctlr->pmdio; 582 imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck); 583 imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck); 584 eieio(); 585 /* Step 3, Serial Interface clock routing */ 586 imm->cmxfcr &= ~0x0000ff00; 587 imm->cmxfcr |= 0x00003700; 588 break; 589 } 590 iopunlock(); 591 592 p = (Etherparam*)(m->immr->prmfcc + ctlr->port); 593 memset(p, 0, sizeof(Etherparam)); 594 595 /* Step 4 */ 596 fcc->gfmr |= ENET; 597 598 /* Step 5 */ 599 fcc->fpsmr = CRCE | FDE | LPB; /* full duplex operation */ 600 ctlr->duplex = ~0; 601 602 /* Step 6 */ 603 fcc->fdsr = 0xd555; 604 605 /* Step 7, initialize parameter ram */ 606 p->rbase = PADDR(ctlr->rdr); 607 p->tbase = PADDR(ctlr->tdr); 608 p->rstate = (GBL | EB) << 24; 609 p->tstate = (GBL | EB) << 24; 610 611 p->cmask = 0xdebb20e3; 612 p->cpres = 0xffffffff; 613 614 p->retlim = 15; /* retry limit */ 615 616 p->mrblr = (Rbsize+0x1f)&~0x1f; /* multiple of 32 */ 617 p->mflr = Rbsize; 618 p->minflr = ETHERMINTU; 619 p->maxd1 = (Rbsize+7) & ~7; 620 p->maxd2 = (Rbsize+7) & ~7; 621 622 for(i=0; i<Eaddrlen; i+=2) 623 p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i]; 624 625 /* Step 7, initialize parameter ram, configuration-dependent values */ 626 p->riptr = m->immr->fccextra[ctlr->port].ri - (uchar*)IMMR; 627 p->tiptr = m->immr->fccextra[ctlr->port].ti - (uchar*)IMMR; 628 p->padptr = m->immr->fccextra[ctlr->port].pad - (uchar*)IMMR; 629 memset(m->immr->fccextra[ctlr->port].pad, 0x88, 0x20); 630 631 /* Step 8, clear out events */ 632 fcc->fcce = ~0; 633 634 /* Step 9, Interrupt enable */ 635 fcc->fccm = TXE | RXF | TXB; 636 637 /* Step 10, Configure interrupt priority (not done here) */ 638 /* Step 11, Clear out current events */ 639 /* Step 12, Enable interrupts to the CP interrupt controller */ 640 641 /* Step 13, Issue the Init Tx and Rx command, specifying 0xc for ethernet*/ 642 cpmop(InitRxTx, fccid[ctlr->port], 0xc); 643 644 /* Step 14, Link management */ 645 if((ctlr->mii = malloc(sizeof(Mii))) == nil) 646 return -1; 647 ctlr->mii->mir = fccmiimir; 648 ctlr->mii->miw = fccmiimiw; 649 ctlr->mii->ctlr = ctlr; 650 651 if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){ 652 free(ctlr->mii); 653 ctlr->mii = nil; 654 return -1; 655 } 656 miiane(ctlr->mii, ~0, ~0, ~0); 657 #ifdef DBG 658 print("oui=%X, phyno=%d, ", phy->oui, phy->phyno); 659 print("anar=%ux, ", phy->anar); 660 print("fc=%ux, ", phy->fc); 661 print("mscr=%ux, ", phy->mscr); 662 663 print("link=%ux, ", phy->link); 664 print("speed=%ux, ", phy->speed); 665 print("fd=%ux, ", phy->fd); 666 print("rfc=%ux, ", phy->rfc); 667 print("tfc=%ux\n", phy->tfc); 668 #endif 669 /* Step 15, Enable ethernet: done at attach time */ 670 return 0; 671 } 672 673 static int 674 reset(Ether* ether) 675 { 676 uchar ea[Eaddrlen]; 677 Ctlr *ctlr; 678 FCC *fcc; 679 Block *b; 680 int i; 681 682 if(m->cpuhz < 24000000){ 683 print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type); 684 return -1; 685 } 686 687 if(ether->port > 3){ 688 print("%s ether: no FCC port %ld\n", ether->type, ether->port); 689 return -1; 690 } 691 ether->irq = fccirq[ether->port]; 692 ether->tbdf = BusPPC; 693 fcc = imm->fcc + ether->port; 694 695 ctlr = malloc(sizeof(*ctlr)); 696 ether->ctlr = ctlr; 697 memset(ctlr, 0, sizeof(*ctlr)); 698 ctlr->fcc = fcc; 699 ctlr->port = ether->port; 700 ctlr->fccid = fccid[ether->port]; 701 702 /* Ioringinit will allocate the buffer descriptors in normal memory 703 * and NOT in Dual-Ported Ram, as prescribed by the MPC8260 704 * PowerQUICC II manual (Section 28.6). When they are allocated 705 * in DPram and the Dcache is enabled, the processor will hang 706 */ 707 if(ioringinit(ctlr, Nrdre, Ntdre, 0) < 0) 708 panic("etherfcc init"); 709 for(i = 0; i < Nrdre; i++){ 710 b = iallocb(Bufsize); 711 b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1)); 712 b->wp = b->rp; 713 ctlr->rcvbufs[i] = b; 714 ctlr->rdr[i].addr = PADDR(b->wp); 715 } 716 717 fccsetup(ctlr, fcc, ether->ea); 718 719 ether->mbps = 100; /* TO DO: could be 10mbps */ 720 ether->attach = attach; 721 ether->transmit = transmit; 722 ether->interrupt = interrupt; 723 ether->ifstat = ifstat; 724 725 ether->arg = ether; 726 ether->promiscuous = promiscuous; 727 ether->multicast = multicast; 728 729 /* 730 * Until we know where to find it, insist that the plan9.ini 731 * entry holds the Ethernet address. 732 */ 733 memset(ea, 0, Eaddrlen); 734 if(memcmp(ea, ether->ea, Eaddrlen) == 0){ 735 print("no ether address"); 736 return -1; 737 } 738 739 return 0; 740 } 741 742 void 743 etherfcclink(void) 744 { 745 addethercard("fcc", reset); 746 } 747 748 static void 749 nanodelay(void) 750 { 751 static int count; 752 int i; 753 754 for(i = 0; i < 500; i++) 755 count++; 756 return; 757 } 758 759 static 760 void miiwriteloop(Ctlr *ctlr, Port *port, int cnt, ulong cmd) 761 { 762 int i; 763 764 for(i = 0; i < cnt; i++){ 765 port->pdat &= ~ctlr->pmdck; 766 if(cmd & BIT(i)) 767 port->pdat |= ctlr->pmdio; 768 else 769 port->pdat &= ~ctlr->pmdio; 770 nanodelay(); 771 port->pdat |= ctlr->pmdck; 772 nanodelay(); 773 } 774 } 775 776 static int 777 fccmiimiw(Mii *mii, int pa, int ra, int data) 778 { 779 int x; 780 Port *port; 781 ulong cmd; 782 Ctlr *ctlr; 783 784 /* 785 * MII Management Interface Write. 786 */ 787 788 ctlr = mii->ctlr; 789 port = imm->port + 3; 790 cmd = MDIwrite | (pa<<(5+2+16))| (ra<<(2+16)) | (data & 0xffff); 791 792 x = splhi(); 793 794 port->pdir |= (ctlr->pmdio|ctlr->pmdck); 795 nanodelay(); 796 797 miiwriteloop(ctlr, port, 32, ~0); 798 miiwriteloop(ctlr, port, 32, cmd); 799 800 port->pdir |= (ctlr->pmdio|ctlr->pmdck); 801 nanodelay(); 802 803 miiwriteloop(ctlr, port, 32, ~0); 804 805 splx(x); 806 return 1; 807 } 808 809 static int 810 fccmiimir(Mii *mii, int pa, int ra) 811 { 812 int data, i, x; 813 Port *port; 814 ulong cmd; 815 Ctlr *ctlr; 816 817 ctlr = mii->ctlr; 818 port = imm->port + 3; 819 820 cmd = MDIread | pa<<(5+2+16) | ra<<(2+16); 821 822 x = splhi(); 823 port->pdir |= (ctlr->pmdio|ctlr->pmdck); 824 nanodelay(); 825 826 miiwriteloop(ctlr, port, 32, ~0); 827 828 /* Clock out the first 14 MS bits of the command */ 829 miiwriteloop(ctlr, port, 14, cmd); 830 831 /* Turn-around */ 832 port->pdat &= ~ctlr->pmdck; 833 port->pdir &= ~ctlr->pmdio; 834 nanodelay(); 835 836 /* For read, clock in 18 bits, use 16 */ 837 data = 0; 838 for(i=0; i<18; i++){ 839 data <<= 1; 840 if(port->pdat & ctlr->pmdio) 841 data |= 1; 842 port->pdat |= ctlr->pmdck; 843 nanodelay(); 844 port->pdat &= ~ctlr->pmdck; 845 nanodelay(); 846 } 847 port->pdir |= (ctlr->pmdio|ctlr->pmdck); 848 nanodelay(); 849 miiwriteloop(ctlr, port, 32, ~0); 850 splx(x); 851 return data & 0xffff; 852 } 853 854 static void 855 fccltimer(Ureg*, Timer *t) 856 { 857 Ether *ether; 858 Ctlr *ctlr; 859 MiiPhy *phy; 860 ulong gfmr; 861 862 ether = t->ta; 863 ctlr = ether->ctlr; 864 if(ctlr->mii == nil || ctlr->mii->curphy == nil) 865 return; 866 phy = ctlr->mii->curphy; 867 if(miistatus(ctlr->mii) < 0){ 868 print("miistatus failed\n"); 869 return; 870 } 871 if(phy->link == 0){ 872 print("link lost\n"); 873 return; 874 } 875 ether->mbps = phy->speed; 876 877 if(phy->fd != ctlr->duplex) 878 print("set duplex\n"); 879 ilock(ctlr); 880 gfmr = ctlr->fcc->gfmr; 881 if(phy->fd != ctlr->duplex){ 882 ctlr->fcc->gfmr &= ~(ENR|ENT); 883 if(phy->fd) 884 ctlr->fcc->fpsmr |= FDE | LPB; /* full duplex operation */ 885 else 886 ctlr->fcc->fpsmr &= ~(FDE | LPB); /* half duplex operation */ 887 ctlr->duplex = phy->fd; 888 } 889 ctlr->fcc->gfmr = gfmr; 890 iunlock(ctlr); 891 } 892