6 #include "../port/lib.h"
12 #include "../port/error.h"
13 #include "../port/netif.h"
16 #include "../ppc/ethermii.h"
21 Nrdre = 128, /* receive descriptor ring entries */
22 Ntdre = 128, /* transmit descriptor ring entries */
24 Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
25 Bufsize = Rbsize+CACHELINESZ, /* extra room for alignment */
30 /* ether-specific Rx BD bits */
38 RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
40 /* ether-specific Tx BD bits */
41 TxPad= SBIT(1), /* pad short frames */
42 TxTC= SBIT(5), /* transmit CRC */
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 */
58 ENET= 0xc, /* ethernet mode */
63 /* FCC function code register */
66 EB= 0x10, /* Motorola byte order */
71 /* FCC Event/Mask bits */
83 MDIread = 0x60020000, /* read opcode */
84 MDIwrite = 0x50020000, /* write opcode */
87 typedef struct Etherparam Etherparam;
90 /*0x3c*/ ulong stat_buf;
91 /*0x40*/ ulong cam_ptr;
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;
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;
142 typedef struct Ctlr Ctlr;
151 int duplex; /* 1 == full */
155 Block* rcvbufs[Nrdre];
159 ulong interrupts; /* statistics */
170 static int fccirq[] = {0x20, 0x21, 0x22};
171 static int fccid[] = {FCC1ID, FCC2ID, FCC3ID};
176 ulong fccrthisto[16];
177 ulong fcctrhisto[16];
181 static int fccmiimir(Mii*, int, int);
182 static int fccmiimiw(Mii*, int, int, int);
183 static void fccltimer(Ureg*, Timer*);
193 ctlr->fcc->gfmr |= ENR|ENT;
195 ctlr->tmode = Tperiodic;
196 ctlr->tf = fccltimer;
198 ctlr->tns = 5000000000LL; /* 5 seconds */
210 ctlr->fcc->gfmr &= ~(ENR|ENT);
212 print("Ether closed\n");
216 promiscuous(void* arg, int on)
225 if(on || ether->nmaddr)
226 ctlr->fcc->fpsmr |= PRO;
228 ctlr->fcc->fpsmr &= ~PRO;
233 multicast(void* arg, uchar *addr, int on)
238 USED(addr, on); /* if on, could SetGroupAddress; if !on, it's hard */
244 if(ether->prom || ether->nmaddr)
245 ctlr->fcc->fpsmr |= PRO;
247 ctlr->fcc->fpsmr &= ~PRO;
252 txstart(Ether *ether)
262 while(ctlr->ntq < Ntdre-1){
267 dre = &ctlr->tdr[ctlr->tdrh];
268 dczap(dre, sizeof(BD));
269 if(dre->status & BDReady)
270 panic("ether: txstart");
273 * Give ownership of the descriptor to the chip, increment the
274 * software ring descriptor pointer and tell the chip to poll.
277 if(ctlr->txb[ctlr->tdrh] != nil)
278 panic("fcc/ether: txstart");
279 ctlr->txb[ctlr->tdrh] = b;
281 panic("fcc/ether: txstart align"); /* TO DO: ensure alignment */
282 dre->addr = PADDR(b->rp);
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 */
290 ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
295 transmit(Ether* ether)
306 interrupt(Ureg*, void *arg)
308 int len, status, rcvd, xmtd, restart;
317 return; /* not ours */
320 * Acknowledge all interrupts and whine about those that shouldn't
323 events = ctlr->fcc->fcce;
324 ctlr->fcc->fcce = events; /* clear events */
327 ehisto[events & 0x7f]++;
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.
346 dre = &ctlr->rdr[ctlr->rdrx];
347 dczap(dre, sizeof(BD));
348 while(((status = dre->status) & BDEmpty) == 0){
350 if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
351 if(status & (RxeLG|RxeSH))
359 print("eth rx: %ux\n", status);
362 * We have a packet. Read it in.
365 b = ctlr->rcvbufs[ctlr->rdrx];
366 assert(dre->addr == PADDR(b->rp));
368 if(nb = iallocb(Bufsize)){
370 etheriq(ether, b, 1);
372 b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));
374 ctlr->rcvbufs[ctlr->rdrx] = b;
375 ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp);
381 * Finished with this descriptor, reinitialise it,
382 * give it back to the chip, then on to the next...
385 dre->status = (status & BDWrap) | BDEmpty | BDInt;
386 dcflush(dre, sizeof(BD));
388 ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
389 dre = &ctlr->rdr[ctlr->rdrx];
390 dczap(dre, sizeof(BD));
395 * Transmitter interrupt: handle anything queued for a free descriptor.
397 if(events & (TXB|TXE)){
401 dre = &ctlr->tdr[ctlr->tdri];
402 dczap(dre, sizeof(BD));
403 status = dre->status;
418 if(status & (TxeLC|TxeRL|TxeUN))
420 ctlr->retrycount += (status>>2)&0xF;
421 b = ctlr->txb[ctlr->tdri];
423 panic("fcce/interrupt: bufp");
424 ctlr->txb[ctlr->tdri] = nil;
427 ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
432 ctlr->fcc->gfmr &= ~ENT;
434 ctlr->fcc->gfmr |= ENT;
435 cpmop(RestartTx, ctlr->fccid, 0xc);
441 if(rcvd >= nelem(fccrhisto))
442 rcvd = nelem(fccrhisto) - 1;
443 if(xmtd >= nelem(fccthisto))
444 xmtd = nelem(fccthisto) - 1;
457 ifstat(Ether* ether, void* a, long n, ulong offset)
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);
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);
493 snprint(p+len, READSTR-len, "\n");
496 snprint(p+len, READSTR-len, "\n");
498 n = readstr(offset, a, n, p);
505 * This follows the MPC8260 user guide: section28.9's initialisation sequence.
508 fccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea)
514 /* Turn Ethernet off */
515 fcc->gfmr &= ~(ENR | ENT);
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);
540 /* Step 3, Serial Interface clock routing */
541 imm->cmxfcr &= ~0xff000000; /* Clock mask */
542 imm->cmxfcr |= 0x37000000; /* Clock route */
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;
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);
564 /* Step 3, Serial Interface clock routing */
565 imm->cmxfcr &= ~0x00ff0000;
566 imm->cmxfcr |= 0x00250000;
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);
585 /* Step 3, Serial Interface clock routing */
586 imm->cmxfcr &= ~0x0000ff00;
587 imm->cmxfcr |= 0x00003700;
592 p = (Etherparam*)(m->immr->prmfcc + ctlr->port);
593 memset(p, 0, sizeof(Etherparam));
599 fcc->fpsmr = CRCE | FDE | LPB; /* full duplex operation */
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;
611 p->cmask = 0xdebb20e3;
612 p->cpres = 0xffffffff;
614 p->retlim = 15; /* retry limit */
616 p->mrblr = (Rbsize+0x1f)&~0x1f; /* multiple of 32 */
618 p->minflr = ETHERMINTU;
619 p->maxd1 = (Rbsize+7) & ~7;
620 p->maxd2 = (Rbsize+7) & ~7;
622 for(i=0; i<Eaddrlen; i+=2)
623 p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];
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);
631 /* Step 8, clear out events */
634 /* Step 9, Interrupt enable */
635 fcc->fccm = TXE | RXF | TXB;
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 */
641 /* Step 13, Issue the Init Tx and Rx command, specifying 0xc for ethernet*/
642 cpmop(InitRxTx, fccid[ctlr->port], 0xc);
644 /* Step 14, Link management */
645 if((ctlr->mii = malloc(sizeof(Mii))) == nil)
647 ctlr->mii->mir = fccmiimir;
648 ctlr->mii->miw = fccmiimiw;
649 ctlr->mii->ctlr = ctlr;
651 if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
656 miiane(ctlr->mii, ~0, ~0, ~0);
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);
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);
669 /* Step 15, Enable ethernet: done at attach time */
682 if(m->cpuhz < 24000000){
683 print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type);
688 print("%s ether: no FCC port %ld\n", ether->type, ether->port);
691 ether->irq = fccirq[ether->port];
692 ether->tbdf = BusPPC;
693 fcc = imm->fcc + ether->port;
695 ctlr = malloc(sizeof(*ctlr));
697 memset(ctlr, 0, sizeof(*ctlr));
699 ctlr->port = ether->port;
700 ctlr->fccid = fccid[ether->port];
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
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));
713 ctlr->rcvbufs[i] = b;
714 ctlr->rdr[i].addr = PADDR(b->wp);
717 fccsetup(ctlr, fcc, ether->ea);
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;
726 ether->promiscuous = promiscuous;
727 ether->multicast = multicast;
730 * Until we know where to find it, insist that the plan9.ini
731 * entry holds the Ethernet address.
733 memset(ea, 0, Eaddrlen);
734 if(memcmp(ea, ether->ea, Eaddrlen) == 0){
735 print("no ether address");
745 addethercard("fcc", reset);
754 for(i = 0; i < 500; i++)
760 void miiwriteloop(Ctlr *ctlr, Port *port, int cnt, ulong cmd)
764 for(i = 0; i < cnt; i++){
765 port->pdat &= ~ctlr->pmdck;
767 port->pdat |= ctlr->pmdio;
769 port->pdat &= ~ctlr->pmdio;
771 port->pdat |= ctlr->pmdck;
777 fccmiimiw(Mii *mii, int pa, int ra, int data)
785 * MII Management Interface Write.
789 port = imm->port + 3;
790 cmd = MDIwrite | (pa<<(5+2+16))| (ra<<(2+16)) | (data & 0xffff);
794 port->pdir |= (ctlr->pmdio|ctlr->pmdck);
797 miiwriteloop(ctlr, port, 32, ~0);
798 miiwriteloop(ctlr, port, 32, cmd);
800 port->pdir |= (ctlr->pmdio|ctlr->pmdck);
803 miiwriteloop(ctlr, port, 32, ~0);
810 fccmiimir(Mii *mii, int pa, int ra)
818 port = imm->port + 3;
820 cmd = MDIread | pa<<(5+2+16) | ra<<(2+16);
823 port->pdir |= (ctlr->pmdio|ctlr->pmdck);
826 miiwriteloop(ctlr, port, 32, ~0);
828 /* Clock out the first 14 MS bits of the command */
829 miiwriteloop(ctlr, port, 14, cmd);
832 port->pdat &= ~ctlr->pmdck;
833 port->pdir &= ~ctlr->pmdio;
836 /* For read, clock in 18 bits, use 16 */
840 if(port->pdat & ctlr->pmdio)
842 port->pdat |= ctlr->pmdck;
844 port->pdat &= ~ctlr->pmdck;
847 port->pdir |= (ctlr->pmdio|ctlr->pmdck);
849 miiwriteloop(ctlr, port, 32, ~0);
851 return data & 0xffff;
855 fccltimer(Ureg*, Timer *t)
864 if(ctlr->mii == nil || ctlr->mii->curphy == nil)
866 phy = ctlr->mii->curphy;
867 if(miistatus(ctlr->mii) < 0){
868 print("miistatus failed\n");
872 print("link lost\n");
875 ether->mbps = phy->speed;
877 if(phy->fd != ctlr->duplex)
878 print("set duplex\n");
880 gfmr = ctlr->fcc->gfmr;
881 if(phy->fd != ctlr->duplex){
882 ctlr->fcc->gfmr &= ~(ENR|ENT);
884 ctlr->fcc->fpsmr |= FDE | LPB; /* full duplex operation */
886 ctlr->fcc->fpsmr &= ~(FDE | LPB); /* half duplex operation */
887 ctlr->duplex = phy->fd;
889 ctlr->fcc->gfmr = gfmr;