2 * SMSC 9221 Ethernet driver
3 * specifically for the ISEE IGEPv2 board,
4 * where it is assigned to Chip Select 5,
5 * its registers are at 0x2c000000 (inherited from u-boot),
6 * and irq is 34 from gpio pin 176, thus gpio module 6.
8 * it's slow due to the use of fifos instead of buffer rings.
9 * the slow system dma just makes it worse.
11 * igepv2 u-boot uses pin 64 on gpio 3 as an output pin to reset the 9221.
14 #include "../port/lib.h"
19 #include "../port/error.h"
20 #include "../port/netif.h"
21 #include "../port/etherif.h"
23 /* currently using kprocs is a lot slower than not (87 s. to boot vs 60) */
28 Slop = 4, /* beyond ETHERMAXTU */
31 typedef struct Regs Regs;
35 uchar _pad0[0x20 - 4];
37 uchar _pad1[0x40 - 0x24];
43 /* control & status */
44 ushort rev; /* chip revision */
45 ushort id; /* chip id, 0x9221 */
51 ulong fifoint; /* fifo level interrupts */
55 ulong rxdpctl; /* rx data path control */
58 ulong pmtctl; /* power mgmt. control */
60 ulong gptcfg; /* timer */
64 ulong freerun; /* counters */
68 * mac registers are accessed indirectly via the mac csr registers.
69 * phy registers are doubly indirect, via the mac csr mii_acc &
70 * mii_data mac csr registers.
72 ulong maccsrcmd; /* mac csr synchronizer */
74 ulong afccfg; /* automatic flow control cfg. */
75 ulong eepcmd; /* eeprom */
87 Bufendalign = 3<<24, /* mask */
88 Datastoff = 037<<16, /* mask */
94 Pkttag = MASK(16) << 16,
98 Pktlen = (1<<1) - 1, /* mask */
101 Txsdump = 1<<15, /* flush tx status fifo */
102 Txddump = 1<<14, /* flush tx data fifo */
107 Mbo = 1<<20, /* must be one */
108 Srstto = 1<<1, /* soft reset time-out */
112 Rxdmacntshift = 16, /* ulong count, 12 bits wide */
113 Rxdmacntmask = MASK(12) << Rxdmacntshift,
114 Rxdump = 1<<15, /* flush rx fifos */
117 Rxpktlenshift = 16, /* byte count */
118 Rxpktlenmask = MASK(14) << Rxpktlenshift,
122 Rxstsusedshift = 16, /* ulong count */
123 Rxstsusedmask = MASK(8) << Rxstsusedshift,
124 Rxdatausedmask = MASK(16), /* byte count */
127 Txstsusedshift = 16, /* ulong count */
128 Txstsusedmask = MASK(8) << Txstsusedshift,
129 Txdatafreemask = MASK(16), /* byte count */
136 Csrread = 1<<30, /* not write */
138 Csraddrmask = MASK(8) - 1,
140 /* mac registers' indices */
146 Macmiiacc, /* for doubly-indirect phy access */
157 Rcvown = 1<<23, /* don't receive own transmissions */
158 Fdpx = 1<<20, /* full duplex */
159 Mcpas = 1<<19, /* pass all multicast */
160 Prms = 1<<18, /* promiscuous */
161 Ho = 1<<15, /* hash-only filtering */
162 Hpfilt = 1<<13, /* hash/perfect filtering */
163 Padstr = 1<<8, /* strip padding & fcs (crc) */
168 Irqdeasclr = 1<<14, /* deassertion intv'l clear */
169 Irqdeassts = 1<<13, /* deassertion intv'l status */
170 Irqint = 1<<12, /* intr being asserted? (ro) */
172 Irqpol = 1<<4, /* irq output is active high */
173 Irqpushpull = 1<<0, /* irq output is push/pull driver */
175 /* intsts/inten bits */
176 Swint = 1<<31, /* generate an interrupt */
183 Rxe = 1<<14, /* errors */
185 Tdfo = 1<<10, /* tx data fifo overrun */
186 Tdfa = 1<<9, /* tx data fifo available */
187 Tsff = 1<<8, /* tx status fifo full */
188 Tsfl = 1<<7, /* tx status fifo level */
189 Rsff = 1<<4, /* rx status fifo full */
190 Rsfl = 1<<3, /* rx status fifo level */
194 Epccmdshift = 28, /* interesting one is Reload (7) */
201 Rxintrs = Rsff | Rsfl | Rxe,
202 Txintrs = Tsff | Tsfl | Txe | Txioc,
205 /* wake-up frame filter */
207 ulong bytemask[4]; /* index is filter # */
208 uchar filt0cmd; /* filter 0 command */
216 uchar offset[4]; /* index is filter # */
217 ushort crc16[4]; /* " */
220 typedef struct Ctlr Ctlr;
233 QLock alock; /* attach */
234 int nrb; /* how many this Ctlr has in the pool */
238 int im; /* interrupt mask */
247 uint statistics[Nstatistics];
255 uchar ra[Eaddrlen]; /* receive address */
256 ulong mta[128]; /* multicast table array */
269 #define csr32r(c, r) (*((c)->nic+((r)/4)))
270 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
272 static Ctlr *smcctlrhead, *smcctlrtail;
274 static char* statistics[Nstatistics] = { "dummy", };
276 static uchar mymac[] = { 0xb0, 0x0f, 0xba, 0xbe, 0x00, 0x00, };
278 static void etherclock(void);
279 static void smcreceive(Ether *edev);
280 static void smcinterrupt(Ureg*, void* arg);
282 static Ether *thisether;
292 if (!beenhere && edev != nil) {
294 /* simulate interrupts if we don't know the irq */
295 if (edev->irq < 0) { /* poll as backup */
297 addclock0link(etherclock, 1000/HZ);
305 * indirect (mac) register access
313 for (bound = 400*Mhz; regs->maccsrcmd & Csrbusy && bound > 0; bound--)
316 iprint("smc: mac registers didn't come ready\n");
320 macrd(Regs *regs, uchar index)
323 regs->maccsrcmd = Csrbusy | Csrread | index;
324 coherence(); /* back-to-back write/read delay per §6.2.1 */
326 return regs->maccsrdata;
330 macwr(Regs *regs, uchar index, ulong val)
333 regs->maccsrdata = val;
334 regs->maccsrcmd = Csrbusy | index; /* fire */
340 smcifstat(Ether* edev, void* a, long n, ulong offset)
350 for(i = 0; i < Nstatistics; i++){
351 // read regs->rxdrop TODO
353 if((s = statistics[i]) == nil)
357 ctlr->statistics[i] += r;
358 if(ctlr->statistics[i] == 0)
360 l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
361 s, ctlr->statistics[i], r);
366 l += snprint(p+l, READSTR-l, "lintr: %ud %ud\n",
367 ctlr->lintr, ctlr->lsleep);
368 l += snprint(p+l, READSTR-l, "rintr: %ud %ud\n",
369 ctlr->rintr, ctlr->rsleep);
370 l += snprint(p+l, READSTR-l, "tintr: %ud %ud\n",
371 ctlr->tintr, ctlr->tsleep);
373 l += snprint(p+l, READSTR-l, "eeprom:");
374 for(i = 0; i < 0x40; i++){
375 if(i && ((i & 0x07) == 0))
376 l += snprint(p+l, READSTR-l, "\n ");
377 l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
379 l += snprint(p+l, READSTR-l, "\n");
382 n = readstr(offset, a, n, p);
384 qunlock(&ctlr->slock);
390 smcpromiscuous(void* arg, int on)
400 rctl = macrd(regs, Maccr);
405 macwr(regs, Maccr, rctl);
409 smcmulticast(void*, uchar*, int)
411 /* nothing to do, we allow all multicast packets in */
415 iswrcpydone(void *arg)
417 return ((Ctlr *)arg)->wrcpydone;
421 smctxstart(Ctlr *ctlr, uchar *ubuf, uint len)
426 static ulong buf[ROUNDUP(ETHERMAXTU, sizeof(ulong)) / sizeof(ulong)];
429 iprint("smctxstart: too soon to send\n");
430 return -1; /* toss it */
434 /* is there room for a packet in the tx data fifo? */
435 if (len < ETHERMINTU)
436 iprint("sending too-short (%d) pkt\n", len);
437 else if (len > ETHERMAXTU)
438 iprint("sending jumbo (%d) pkt\n", len);
440 ruplen = ROUNDUP(len, sizeof(ulong));
441 coherence(); /* back-to-back read/read delay per §6.2.2 */
442 if ((regs->txfifoinf & Txdatafreemask) < ruplen + 2*sizeof(ulong))
443 return -1; /* not enough room for data + command words */
445 if ((uintptr)ubuf & MASK(2)) { /* ensure word alignment */
446 memmove(buf, ubuf, len);
450 /* tx cmd a: length is bytes in this buffer */
451 txdp = ®s->txdata;
452 *txdp = Intcompl | Firstseg | Lastseg | len;
453 /* tx cmd b: length is bytes in this packet (could be multiple buf.s) */
456 /* shovel pkt into tx fifo, which triggers transmission due to Txon */
458 for (wds = ruplen / sizeof(ulong) + 1; --wds > 0; )
461 regs->intsts = Txintrs; /* dismiss intr */
463 regs->inten |= Txintrs;
464 coherence(); /* back-to-back write/read delay per §6.2.1 */
469 smctransmit(Ether* edev)
476 panic("smctransmit: nil ctlr");
479 * Try to fill the chip's buffers back up, via the tx fifo.
481 while ((bp = qget(edev->oq)) != nil)
482 if (smctxstart(ctlr, bp->rp, BLEN(bp)) < 0) {
483 qputback(edev->oq, bp); /* retry the block later */
484 iprint("smctransmit: tx data fifo full\n");
488 iunlock(&ctlr->tlock);
492 smctransmitcall(Ether *edev) /* called from devether.c */
499 wakeup(&ctlr->trendez);
508 return ((Ctlr*)ctlr)->gotinput;
521 sleep(&ctlr->rrendez, smcrim, ctlr);
523 /* process any newly-arrived packets and pass to etheriq */
530 smcgotout(void* ctlr)
532 return ((Ctlr*)ctlr)->gotoutput;
545 sleep(&ctlr->trendez, smcgotout, ctlr);
547 /* process any newly-arrived packets and pass to etheriq */
553 void gpioirqclr(void);
556 smcattach(Ether* edev)
566 qunlock(&ctlr->alock);
572 snprint(name, KNAMELEN, "#l%drproc", edev->ctlrno);
573 kproc(name, smcrproc, edev);
575 snprint(name, KNAMELEN, "#l%dtproc", edev->ctlrno);
576 kproc(name, smctproc, edev);
579 iprint("smcattach:");
581 iprint(" with kprocs");
583 iprint(" no kprocs");
586 /* can now accept real or simulated interrupts */
592 qunlock(&ctlr->alock);
597 isrdcpydone(void *arg)
599 return ((Ctlr *)arg)->rdcpydone;
603 smcreceive(Ether *edev)
613 coherence(); /* back-to-back read/read delay per §6.2.2 */
615 * is there a full packet in the rx data fifo?
617 while (((regs->rxfifoinf & Rxstsusedmask) >> Rxstsusedshift) != 0) {
619 sts = regs->rxsts; /* pop rx status */
621 iprint("smcreceive: rx error\n");
622 len = (sts & Rxpktlenmask) >> Rxpktlenshift;
623 if (len > ETHERMAXTU + Slop)
624 iprint("smcreceive: oversized rx pkt (%d)\n", len);
625 else if (len < ETHERMINTU)
626 iprint("smcreceive: too-short (%d) pkt\n", len);
627 wds = ROUNDUP(len, sizeof(ulong)) / sizeof(ulong);
629 /* copy aligned words from rx fifo into a Block */
630 bp = iallocb(len + sizeof(ulong) /* - 1 */);
632 panic("smcreceive: nil Block*");
634 /* bp->rp should be 32-byte aligned, more than we need */
635 assert(((uintptr)bp->rp & (sizeof(ulong) - 1)) == 0);
636 wdp = (ulong *)bp->rp;
637 rxdp = ®s->rxdata;
638 wds = ROUNDUP(len, sizeof(ulong)) / sizeof(ulong) + 1;
641 bp->wp = bp->rp + len;
643 /* and push the Block upstream */
649 regs->intsts = Rxintrs; /* dismiss intr */
651 regs->inten |= Rxintrs;
655 regs->inten |= Rxintrs;
660 * disable the stsclr bits in inten and write them to intsts to ack and dismiss
661 * the interrupt source.
664 ackintr(Regs *regs, ulong stsclr)
669 regs->inten &= ~stsclr;
672 // regs->intsts = stsclr; /* acknowledge & clear intr(s) */
677 smcinterrupt(Ureg*, void* arg)
680 unsigned intsts, intr;
687 ilock(&ctlr->imlock);
692 coherence(); /* back-to-back read/read delay per §6.2.2 */
693 intsts = regs->intsts;
696 intsts &= ~MASK(3); /* ignore gpio bits */
697 if (0 && intsts == 0) {
699 iprint("smc: interrupt without a cause; insts %#ux (vs inten %#lux)\n",
700 intsts, regs->inten);
703 intr = intsts & Rxintrs;
705 /* disable interrupt sources; kproc/smcreceive will reenable */
711 wakeup(&ctlr->rrendez);
717 while(((regs->txfifoinf & Txstsusedmask) >> Txstsusedshift) != 0) {
718 /* probably indicates tx completion, just toss it */
719 junk = regs->txsts; /* pop tx sts */
724 intr = intsts & Txintrs;
725 if (ctlr->gotoutput || intr) {
726 /* disable interrupt sources; kproc/smctransmit will reenable */
732 wakeup(&ctlr->trendez);
738 iunlock(&ctlr->imlock);
744 smcinterrupt(nil, thisether);
754 smcdetach(Ctlr* ctlr)
758 if (ctlr == nil || ctlr->regs == nil)
761 /* verify that it's real by reading a few registers */
766 print("smc: unknown chip id %#ux\n", regs->id);
769 regs->inten = 0; /* no interrupts */
770 regs->intsts = ~0; /* clear any pending */
773 regs->rxcfg = Rxdump;
774 regs->txcfg = Txsdump | Txddump;
775 regs->irqcfg &= ~Irqen;
781 smcshutdown(Ether* ether)
783 smcdetach(ether->ctlr);
787 powerwait(Regs *regs)
791 regs->bytetest = 0; /* bring power on */
792 for (bound = 400*Mhz; !(regs->pmtctl & Dready) && bound > 0; bound--)
795 iprint("smc: pmtctl didn't come ready\n");
803 static char zea[Eaddrlen];
811 /* verify that it's real by reading a few registers */
816 print("smc: unknown chip id %#ux\n", regs->id);
819 if (regs->bytetest != 0x87654321) {
820 print("smc: bytetest reg %#p (%#lux) != 0x87654321\n",
821 ®s->bytetest, regs->bytetest);
825 #ifdef TODO /* read MAC from EEPROM */
826 // int ctrl, i, pause, swdpio, txcw;
828 * Snarf and set up the receive addresses.
829 * There are 16 addresses. The first should be the MAC address.
830 * The others are cleared and not marked valid (MS bit of Rah).
832 for(i = Ea; i < Eaddrlen/2; i++){
833 ctlr->ra[2*i] = ctlr->eeprom[i];
834 ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
838 * Clear the Multicast Table Array.
839 * It's a 4096 bit vector accessed as 128 32-bit registers.
841 memset(ctlr->mta, 0, sizeof(ctlr->mta));
842 for(i = 0; i < 128; i++)
843 csr32w(ctlr, Mta+i*4, 0);
847 /* don't overwrite existing ea */
848 // if (memcmp(edev->ea, zea, Eaddrlen) == 0)
849 // memmove(edev->ea, ctlr->ra, Eaddrlen);
851 r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
852 macwr(regs, Macaddrl, r);
853 macwr(regs, Macaddrh, ctlr->ra[5]<<8 | ctlr->ra[4]);
855 /* turn on the controller */
856 macwr(regs, Maccoe, 0);
857 regs->inten = 0; /* no interrupts yet */
858 regs->intsts = ~0; /* clear any pending */
861 regs->rxcfg = Rxdump;
862 regs->txcfg = Txsdump | Txddump | Txon;
863 regs->fifoint = 72<<24; /* default values */
864 macwr(regs, Maccr, Rxall | Rcvown | Fdpx | Mcpas | Txen | Rxen);
865 coherence(); /* back-to-back write/read delay per §6.2.1 */
866 regs->irqcfg = 1<<24 | Irqen | Irqpushpull; /* deas for 10µs (linux) */
867 coherence(); /* back-to-back write/read delay per §6.2.1 */
868 regs->inten = Rxintrs | Txintrs;
886 if (probeaddr(PHYSETHER) < 0)
888 ctlr = malloc(sizeof(Ctlr));
889 ctlr->id = Vid9221<<16 | 0x0424; /* smsc 9221 */
890 ctlr->port = PHYSETHER;
891 ctlr->nic = (int *)PHYSETHER;
892 ctlr->regs = (Regs *)PHYSETHER;
898 if(smcctlrhead != nil)
899 smcctlrtail->next = ctlr;
909 static char zea[Eaddrlen];
911 if(smcctlrhead == nil)
915 * Any adapter matches if no edev->port is supplied,
916 * otherwise the ports must match.
918 for(ctlr = smcctlrhead; ctlr != nil; ctlr = ctlr->next){
921 if(edev->port == 0 || edev->port == ctlr->port){
930 ctlr->edev = edev; /* point back to Ether* */
931 edev->port = ctlr->port;
933 // TODO: verify speed (100Mb/s) and duplicity (full-duplex)
936 /* don't overwrite existing ea */
937 if (memcmp(edev->ea, zea, Eaddrlen) == 0)
938 memmove(edev->ea, ctlr->ra, Eaddrlen);
941 * Linkage to the generic ethernet driver.
943 edev->attach = smcattach;
944 edev->transmit = smctransmitcall;
945 edev->ifstat = smcifstat;
946 /* edev->ctl = smcctl; /* no ctl msgs supported */
949 edev->promiscuous = smcpromiscuous;
950 edev->multicast = smcmulticast;
951 edev->shutdown = smcshutdown;
953 intrenable(edev->irq, smcinterrupt, edev, 0, edev->name);
961 addethercard("9221", smcpnp);