xref: /plan9/sys/src/9/omap/ether9221.c (revision df2dbabf397493e64ca7440c63ccb06027111868)
1 /*
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.
7  *
8  * it's slow due to the use of fifos instead of buffer rings.
9  * the slow system dma just makes it worse.
10  *
11  * igepv2 u-boot uses pin 64 on gpio 3 as an output pin to reset the 9221.
12  */
13 #include "u.h"
14 #include "../port/lib.h"
15 #include "mem.h"
16 #include "dat.h"
17 #include "fns.h"
18 #include "io.h"
19 #include "../port/error.h"
20 #include "../port/netif.h"
21 
22 #include "etherif.h"
23 
24 /* currently using kprocs is a lot slower than not (87 s. to boot vs 60) */
25 #undef USE_KPROCS
26 
27 enum {
28 	Vid9221	= 0x9221,
29 	Slop	= 4,			/* beyond ETHERMAXTU */
30 };
31 
32 typedef struct Regs Regs;
33 struct Regs {
34 	/* fifo ports */
35 	ulong	rxdata;
36 	uchar	_pad0[0x20 - 4];
37 	ulong	txdata;
38 	uchar	_pad1[0x40 - 0x24];
39 	ulong	rxsts;
40 	ulong	rxstspeek;
41 	ulong	txsts;
42 	ulong	txstspeek;
43 
44 	/* control & status */
45 	ushort	rev;			/* chip revision */
46 	ushort	id;			/* chip id, 0x9221 */
47 	ulong	irqcfg;
48 	ulong	intsts;
49 	ulong	inten;
50 	ulong	_pad2;
51 	ulong	bytetest;
52 	ulong	fifoint;		/* fifo level interrupts */
53 	ulong	rxcfg;
54 	ulong	txcfg;
55 	ulong	hwcfg;
56 	ulong	rxdpctl;		/* rx data path control */
57 	ulong	rxfifoinf;
58 	ulong	txfifoinf;
59 	ulong	pmtctl;			/* power mgmt. control */
60 	ulong	gpiocfg;
61 	ulong	gptcfg;			/* timer */
62 	ulong	gptcnt;
63 	ulong	_pad3;
64 	ulong	wordswap;
65 	ulong	freerun; 		/* counters */
66 	ulong	rxdrop;
67 
68 	/*
69 	 * mac registers are accessed indirectly via the mac csr registers.
70 	 * phy registers are doubly indirect, via the mac csr mii_acc &
71 	 * mii_data mac csr registers.
72 	 */
73 	ulong	maccsrcmd;		/* mac csr synchronizer */
74 	ulong	maccsrdata;
75 	ulong	afccfg;			/* automatic flow control cfg. */
76 	ulong	eepcmd;			/* eeprom */
77 	ulong	eepdata;
78 	/* 0xb8 */
79 };
80 
81 enum {
82 	Nstatistics	= 128,
83 };
84 
85 enum {
86 	/* txcmda bits */
87 	Intcompl	= 1<<31,
88 	Bufendalign	= 3<<24,	/* mask */
89 	Datastoff	= 037<<16,	/* mask */
90 	Firstseg	= 1<<13,
91 	Lastseg		= 1<<12,
92 	Bufsize		= MASK(11),
93 
94 	/* txcmdb bits */
95 	Pkttag		= MASK(16) << 16,
96 	Txcksumen	= 1<<14,
97 	Addcrcdis	= 1<<13,
98 	Framepaddis	= 1<<12,
99 	Pktlen		= (1<<1) - 1,	/* mask */
100 
101 	/* txcfg bits */
102 	Txsdump		= 1<<15,	/* flush tx status fifo */
103 	Txddump		= 1<<14,	/* flush tx data fifo */
104 	Txon		= 1<<1,
105 	Stoptx		= 1<<0,
106 
107 	/* hwcfg bits */
108 	Mbo		= 1<<20,	/* must be one */
109 	Srstto		= 1<<1,		/* soft reset time-out */
110 	Srst		= 1<<0,
111 
112 	/* rxcfg bits */
113 	Rxdmacntshift	= 16,		/* ulong count, 12 bits wide */
114 	Rxdmacntmask	= MASK(12) << Rxdmacntshift,
115 	Rxdump		= 1<<15,	/* flush rx fifos */
116 
117 	/* rxsts bits */
118 	Rxpktlenshift	= 16,		/* byte count */
119 	Rxpktlenmask	= MASK(14) << Rxpktlenshift,
120 	Rxerr		= 1<<15,
121 
122 	/* rxfifoinf bits */
123 	Rxstsusedshift	= 16,		/* ulong count */
124 	Rxstsusedmask	= MASK(8) << Rxstsusedshift,
125 	Rxdatausedmask	= MASK(16),	/* byte count */
126 
127 	/* txfifoinf bits */
128 	Txstsusedshift	= 16,		/* ulong count */
129 	Txstsusedmask	= MASK(8) << Txstsusedshift,
130 	Txdatafreemask	= MASK(16),	/* byte count */
131 
132 	/* pmtctl bits */
133 	Dready		= 1<<0,
134 
135 	/* maccsrcmd bits */
136 	Csrbusy		= 1<<31,
137 	Csrread		= 1<<30,	/* not write */
138 	Csraddrshift	= 0,
139 	Csraddrmask	= MASK(8) - 1,
140 
141 	/* mac registers' indices */
142 	Maccr		= 1,
143 	Macaddrh,
144 	Macaddrl,
145 	Machashh,
146 	Machashl,
147 	Macmiiacc,			/* for doubly-indirect phy access */
148 	Macmiidata,
149 	Macflow,
150 	Macvlan1,
151 	Macvlan2,
152 	Macwuff,
153 	Macwucsr,
154 	Maccoe,
155 
156 	/* Maccr bits */
157 	Rxall		= 1<<31,
158 	Rcvown		= 1<<23,	/* don't receive own transmissions */
159 	Fdpx		= 1<<20,	/* full duplex */
160 	Mcpas		= 1<<19,	/* pass all multicast */
161 	Prms		= 1<<18,	/* promiscuous */
162 	Ho		= 1<<15,	/* hash-only filtering */
163 	Hpfilt		= 1<<13,	/* hash/perfect filtering */
164 	Padstr		= 1<<8,		/* strip padding & fcs (crc) */
165 	Txen		= 1<<3,
166 	Rxen		= 1<<2,
167 
168 	/* irqcfg bits */
169 	Irqdeasclr	= 1<<14,	/* deassertion intv'l clear */
170 	Irqdeassts	= 1<<13,	/* deassertion intv'l status */
171 	Irqint		= 1<<12,	/* intr being asserted? (ro) */
172 	Irqen		= 1<<8,
173 	Irqpol		= 1<<4,		/* irq output is active high */
174 	Irqpushpull	= 1<<0,		/* irq output is push/pull driver */
175 
176 	/* intsts/inten bits */
177 	Swint		= 1<<31,	/* generate an interrupt */
178 	Txstop		= 1<<25,
179 	Rxstop		= 1<<24,
180 	Txioc		= 1<<21,
181 	Rxdma		= 1<<20,
182 	Gptimer		= 1<<19,
183 	Phy		= 1<<18,
184 	Rxe		= 1<<14,	/* errors */
185 	Txe		= 1<<13,
186 	Tdfo		= 1<<10,	/* tx data fifo overrun */
187 	Tdfa		= 1<<9,		/* tx data fifo available */
188 	Tsff		= 1<<8,		/* tx status fifo full */
189 	Tsfl		= 1<<7,		/* tx status fifo level */
190 	Rsff		= 1<<4,		/* rx status fifo full */
191 	Rsfl		= 1<<3,		/* rx status fifo level */
192 
193 	/* eepcmd bits */
194 	Epcbusy		= 1<<31,
195 	Epccmdshift	= 28,		/* interesting one is Reload (7) */
196 	Epctimeout	= 1<<9,
197 	Epcmacloaded	= 1<<8,
198 	Epcaddrshift	= 0,
199 };
200 
201 enum {
202 	Rxintrs		= Rsff | Rsfl | Rxe,
203 	Txintrs		= Tsff | Tsfl | Txe | Txioc,
204 };
205 
206 /* wake-up frame filter */
207 struct Wakeup {
208 	ulong	bytemask[4];		/* index is filter # */
209 	uchar	filt0cmd;		/* filter 0 command */
210 	uchar	_pad0;
211 	uchar	filt1cmd;
212 	uchar	_pad1;
213 	uchar	filt2cmd;
214 	uchar	_pad2;
215 	uchar	filt3cmd;
216 	uchar	_pad3;
217 	uchar	offset[4];		/* index is filter # */
218 	ushort	crc16[4];		/* " */
219 };
220 
221 typedef struct Ctlr Ctlr;
222 struct Ctlr {
223 	int	port;
224 	Ctlr*	next;
225 	Ether*	edev;
226 	Regs*	regs;
227 	int	active;
228 	int	started;
229 	int	inited;
230 	int	id;
231 	int	cls;
232 	ushort	eeprom[0x40];
233 
234 	QLock	alock;			/* attach */
235 	int	nrb;			/* how many this Ctlr has in the pool */
236 
237 	int*	nic;
238 	Lock	imlock;
239 	int	im;			/* interrupt mask */
240 
241 //	Mii*	mii;
242 //	Rendez	lrendez;
243 	int	lim;
244 
245 	int	link;
246 
247 	QLock	slock;
248 	uint	statistics[Nstatistics];
249 	uint	lsleep;
250 	uint	lintr;
251 	uint	rsleep;
252 	uint	rintr;
253 	int	tsleep;
254 	uint	tintr;
255 
256 	uchar	ra[Eaddrlen];		/* receive address */
257 	ulong	mta[128];		/* multicast table array */
258 
259 	Rendez	rrendez;
260 	int	gotinput;
261 	int	rdcpydone;
262 
263 	Rendez	trendez;
264 	int	gotoutput;
265 	int	wrcpydone;
266 
267 	Lock	tlock;
268 };
269 
270 #define csr32r(c, r)	(*((c)->nic+((r)/4)))
271 #define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
272 
273 static Ctlr *smcctlrhead, *smcctlrtail;
274 
275 static char* statistics[Nstatistics] = { "dummy", };
276 
277 static uchar mymac[] = { 0xb0, 0x0f, 0xba, 0xbe, 0x00, 0x00, };
278 
279 static void etherclock(void);
280 static void smcreceive(Ether *edev);
281 static void smcinterrupt(Ureg*, void* arg);
282 
283 static Ether *thisether;
284 static int attached;
285 
286 static void
smconce(Ether * edev)287 smconce(Ether *edev)
288 {
289 	static int beenhere;
290 	static Lock l;
291 
292 	ilock(&l);
293 	if (!beenhere && edev != nil) {
294 		beenhere = 1;
295 		/* simulate interrupts if we don't know the irq */
296 		if (edev->irq < 0) {		/* poll as backup */
297 			thisether = edev;
298 			addclock0link(etherclock, 1000/HZ);
299 			iprint(" polling");
300 		}
301 	}
302 	iunlock(&l);
303 }
304 
305 /*
306  * indirect (mac) register access
307  */
308 
309 static void
macwait(Regs * regs)310 macwait(Regs *regs)
311 {
312 	long bound;
313 
314 	for (bound = 400*Mhz; regs->maccsrcmd & Csrbusy && bound > 0; bound--)
315 		;
316 	if (bound <= 0)
317 		iprint("smc: mac registers didn't come ready\n");
318 }
319 
320 static ulong
macrd(Regs * regs,uchar index)321 macrd(Regs *regs, uchar index)
322 {
323 	macwait(regs);
324 	regs->maccsrcmd = Csrbusy | Csrread | index;
325 	coherence();		/* back-to-back write/read delay per §6.2.1 */
326 	macwait(regs);
327 	return regs->maccsrdata;
328 }
329 
330 static void
macwr(Regs * regs,uchar index,ulong val)331 macwr(Regs *regs, uchar index, ulong val)
332 {
333 	macwait(regs);
334 	regs->maccsrdata = val;
335 	regs->maccsrcmd = Csrbusy | index;	/* fire */
336 	macwait(regs);
337 }
338 
339 
340 static long
smcifstat(Ether * edev,void * a,long n,ulong offset)341 smcifstat(Ether* edev, void* a, long n, ulong offset)
342 {
343 	Ctlr *ctlr;
344 	char *p, *s;
345 	int i, l, r;
346 
347 	ctlr = edev->ctlr;
348 	qlock(&ctlr->slock);
349 	p = malloc(READSTR);
350 	l = 0;
351 	for(i = 0; i < Nstatistics; i++){
352 		// read regs->rxdrop TODO
353 		r = 0;
354 		if((s = statistics[i]) == nil)
355 			continue;
356 		switch(i){
357 		default:
358 			ctlr->statistics[i] += r;
359 			if(ctlr->statistics[i] == 0)
360 				continue;
361 			l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
362 				s, ctlr->statistics[i], r);
363 			break;
364 		}
365 	}
366 
367 	l += snprint(p+l, READSTR-l, "lintr: %ud %ud\n",
368 		ctlr->lintr, ctlr->lsleep);
369 	l += snprint(p+l, READSTR-l, "rintr: %ud %ud\n",
370 		ctlr->rintr, ctlr->rsleep);
371 	l += snprint(p+l, READSTR-l, "tintr: %ud %ud\n",
372 		ctlr->tintr, ctlr->tsleep);
373 
374 	l += snprint(p+l, READSTR-l, "eeprom:");
375 	for(i = 0; i < 0x40; i++){
376 		if(i && ((i & 0x07) == 0))
377 			l += snprint(p+l, READSTR-l, "\n       ");
378 		l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
379 	}
380 	l += snprint(p+l, READSTR-l, "\n");
381 	USED(l);
382 
383 	n = readstr(offset, a, n, p);
384 	free(p);
385 	qunlock(&ctlr->slock);
386 
387 	return n;
388 }
389 
390 static void
smcpromiscuous(void * arg,int on)391 smcpromiscuous(void* arg, int on)
392 {
393 	int rctl;
394 	Ctlr *ctlr;
395 	Ether *edev;
396 	Regs *regs;
397 
398 	edev = arg;
399 	ctlr = edev->ctlr;
400 	regs = ctlr->regs;
401 	rctl = macrd(regs, Maccr);
402 	if(on)
403 		rctl |= Prms;
404 	else
405 		rctl &= ~Prms;
406 	macwr(regs, Maccr, rctl);
407 }
408 
409 static void
smcmulticast(void *,uchar *,int)410 smcmulticast(void*, uchar*, int)
411 {
412 	/* nothing to do, we allow all multicast packets in */
413 }
414 
415 static int
iswrcpydone(void * arg)416 iswrcpydone(void *arg)
417 {
418 	return ((Ctlr *)arg)->wrcpydone;
419 }
420 
421 static int
smctxstart(Ctlr * ctlr,uchar * ubuf,uint len)422 smctxstart(Ctlr *ctlr, uchar *ubuf, uint len)
423 {
424 	uint wds, ruplen;
425 	ulong *wdp, *txdp;
426 	Regs *regs;
427 	static ulong buf[ROUNDUP(ETHERMAXTU, sizeof(ulong)) / sizeof(ulong)];
428 
429 	if (!ctlr->inited) {
430 		iprint("smctxstart: too soon to send\n");
431 		return -1;		/* toss it */
432 	}
433 	regs = ctlr->regs;
434 
435 	/* is there room for a packet in the tx data fifo? */
436 	if (len < ETHERMINTU)
437 		iprint("sending too-short (%d) pkt\n", len);
438 	else if (len > ETHERMAXTU)
439 		iprint("sending jumbo (%d) pkt\n", len);
440 
441 	ruplen = ROUNDUP(len, sizeof(ulong));
442 	coherence();	/* back-to-back read/read delay per §6.2.2 */
443 	if ((regs->txfifoinf & Txdatafreemask) < ruplen + 2*sizeof(ulong))
444 		return -1;	/* not enough room for data + command words */
445 
446 	if ((uintptr)ubuf & MASK(2)) {		/* ensure word alignment */
447 		memmove(buf, ubuf, len);
448 		ubuf = (uchar *)buf;
449 	}
450 
451 	/* tx cmd a: length is bytes in this buffer */
452 	txdp = &regs->txdata;
453 	*txdp = Intcompl | Firstseg | Lastseg | len;
454 	/* tx cmd b: length is bytes in this packet (could be multiple buf.s) */
455 	*txdp = len;
456 
457 	/* shovel pkt into tx fifo, which triggers transmission due to Txon */
458 	wdp = (ulong *)ubuf;
459 	for (wds = ruplen / sizeof(ulong) + 1; --wds > 0; )
460 		*txdp = *wdp++;
461 
462 	regs->intsts = Txintrs;		/* dismiss intr */
463 	coherence();
464 	regs->inten |= Txintrs;
465 	coherence();		/* back-to-back write/read delay per §6.2.1 */
466 	return 0;
467 }
468 
469 static void
smctransmit(Ether * edev)470 smctransmit(Ether* edev)
471 {
472 	Block *bp;
473 	Ctlr *ctlr;
474 
475 	ctlr = edev->ctlr;
476 	if (ctlr == nil)
477 		panic("smctransmit: nil ctlr");
478 	ilock(&ctlr->tlock);
479 	/*
480 	 * Try to fill the chip's buffers back up, via the tx fifo.
481 	 */
482 	while ((bp = qget(edev->oq)) != nil)
483 		if (smctxstart(ctlr, bp->rp, BLEN(bp)) < 0) {
484 			qputback(edev->oq, bp);	/* retry the block later */
485 			iprint("smctransmit: tx data fifo full\n");
486 			break;
487 		} else
488 			freeb(bp);
489 	iunlock(&ctlr->tlock);
490 }
491 
492 static void
smctransmitcall(Ether * edev)493 smctransmitcall(Ether *edev)		/* called from devether.c */
494 {
495 	Ctlr *ctlr;
496 
497 	ctlr = edev->ctlr;
498 	ctlr->gotoutput = 1;
499 #ifdef USE_KPROCS
500 	wakeup(&ctlr->trendez);
501 #else
502 	smctransmit(edev);
503 #endif
504 }
505 
506 static int
smcrim(void * ctlr)507 smcrim(void* ctlr)
508 {
509 	return ((Ctlr*)ctlr)->gotinput;
510 }
511 
512 static void
smcrproc(void * arg)513 smcrproc(void* arg)
514 {
515 	Ctlr *ctlr;
516 	Ether *edev;
517 
518 	edev = arg;
519 	ctlr = edev->ctlr;
520 	for(;;){
521 		ctlr->rsleep++;
522 		sleep(&ctlr->rrendez, smcrim, ctlr);
523 
524 		/* process any newly-arrived packets and pass to etheriq */
525 		ctlr->gotinput = 0;
526 		smcreceive(edev);
527 	}
528 }
529 
530 static int
smcgotout(void * ctlr)531 smcgotout(void* ctlr)
532 {
533 	return ((Ctlr*)ctlr)->gotoutput;
534 }
535 
536 static void
smctproc(void * arg)537 smctproc(void* arg)
538 {
539 	Ctlr *ctlr;
540 	Ether *edev;
541 
542 	edev = arg;
543 	ctlr = edev->ctlr;
544 	for(;;){
545 		ctlr->tsleep++;
546 		sleep(&ctlr->trendez, smcgotout, ctlr);
547 
548 		/* process any newly-arrived packets and pass to etheriq */
549 		ctlr->gotoutput = 0;
550 		smctransmit(edev);
551 	}
552 }
553 
554 void	gpioirqclr(void);
555 
556 static void
smcattach(Ether * edev)557 smcattach(Ether* edev)
558 {
559 #ifdef USE_KPROCS
560 	char name[KNAMELEN];
561 #endif
562 	Ctlr *ctlr;
563 
564 	ctlr = edev->ctlr;
565 	qlock(&ctlr->alock);
566 	if(waserror()){
567 		qunlock(&ctlr->alock);
568 		nexterror();
569 	}
570 	if (!ctlr->inited) {
571 		ctlr->inited = 1;
572 #ifdef USE_KPROCS
573 		snprint(name, KNAMELEN, "#l%drproc", edev->ctlrno);
574 		kproc(name, smcrproc, edev);
575 
576 		snprint(name, KNAMELEN, "#l%dtproc", edev->ctlrno);
577 		kproc(name, smctproc, edev);
578 #endif
579 
580 iprint("smcattach:");
581 #ifdef USE_KPROCS
582 iprint(" with kprocs");
583 #else
584 iprint(" no kprocs");
585 #endif
586 iprint(", no dma");
587 		/* can now accept real or simulated interrupts */
588 
589 		smconce(edev);
590 		attached = 1;
591 iprint("\n");
592 	}
593 	qunlock(&ctlr->alock);
594 	poperror();
595 }
596 
597 static int
isrdcpydone(void * arg)598 isrdcpydone(void *arg)
599 {
600 	return ((Ctlr *)arg)->rdcpydone;
601 }
602 
603 static void
smcreceive(Ether * edev)604 smcreceive(Ether *edev)
605 {
606 	uint wds, len, sts;
607 	ulong *wdp, *rxdp;
608 	Block *bp;
609 	Ctlr *ctlr;
610 	Regs *regs;
611 
612 	ctlr = edev->ctlr;
613 	regs = ctlr->regs;
614 	coherence();		/* back-to-back read/read delay per §6.2.2 */
615 	/*
616 	 * is there a full packet in the rx data fifo?
617 	 */
618 	while (((regs->rxfifoinf & Rxstsusedmask) >> Rxstsusedshift) != 0) {
619 		coherence();
620 		sts = regs->rxsts;		/* pop rx status */
621 		if(sts & Rxerr)
622 			iprint("smcreceive: rx error\n");
623 		len = (sts & Rxpktlenmask) >> Rxpktlenshift;
624 		if (len > ETHERMAXTU + Slop)
625 			iprint("smcreceive: oversized rx pkt (%d)\n", len);
626 		else if (len < ETHERMINTU)
627 			iprint("smcreceive: too-short (%d) pkt\n", len);
628 		wds = ROUNDUP(len, sizeof(ulong)) / sizeof(ulong);
629 		if (wds > 0) {
630 			/* copy aligned words from rx fifo into a Block */
631 			bp = iallocb(len + sizeof(ulong) /* - 1 */);
632 			if (bp == nil)
633 				panic("smcreceive: nil Block*");
634 
635 			/* bp->rp should be 32-byte aligned, more than we need */
636 			assert(((uintptr)bp->rp & (sizeof(ulong) - 1)) == 0);
637 			wdp = (ulong *)bp->rp;
638 			rxdp = &regs->rxdata;
639 			wds = ROUNDUP(len, sizeof(ulong)) / sizeof(ulong) + 1;
640 			while (--wds > 0)
641 				*wdp++ = *rxdp;
642 			bp->wp = bp->rp + len;
643 
644 			/* and push the Block upstream */
645 			if (ctlr->inited)
646 				etheriq(edev, bp, 1);
647 			else
648 				freeb(bp);
649 
650 			regs->intsts = Rxintrs;		/* dismiss intr */
651 			coherence();
652 			regs->inten |= Rxintrs;
653 		}
654 		coherence();
655 	}
656 	regs->inten |= Rxintrs;
657 	coherence();
658 }
659 
660 /*
661  * disable the stsclr bits in inten and write them to intsts to ack and dismiss
662  * the interrupt source.
663  */
664 void
ackintr(Regs * regs,ulong stsclr)665 ackintr(Regs *regs, ulong stsclr)
666 {
667 	if (stsclr == 0)
668 		return;
669 
670 	regs->inten &= ~stsclr;
671 	coherence();
672 
673 //	regs->intsts = stsclr;		/* acknowledge & clear intr(s) */
674 //	coherence();
675 }
676 
677 static void
smcinterrupt(Ureg *,void * arg)678 smcinterrupt(Ureg*, void* arg)
679 {
680 	int junk;
681 	unsigned intsts, intr;
682 	Ctlr *ctlr;
683 	Ether *edev;
684 	Regs *regs;
685 
686 	edev = arg;
687 	ctlr = edev->ctlr;
688 	ilock(&ctlr->imlock);
689 	regs = ctlr->regs;
690 
691 	gpioirqclr();
692 
693 	coherence();		/* back-to-back read/read delay per §6.2.2 */
694 	intsts = regs->intsts;
695 	coherence();
696 
697 	intsts &= ~MASK(3);		/* ignore gpio bits */
698 	if (0 && intsts == 0) {
699 		coherence();
700 		iprint("smc: interrupt without a cause; insts %#ux (vs inten %#lux)\n",
701 			intsts, regs->inten);
702 	}
703 
704 	intr = intsts & Rxintrs;
705 	if(intr) {
706 		/* disable interrupt sources; kproc/smcreceive will reenable */
707 		ackintr(regs, intr);
708 
709 		ctlr->rintr++;
710 		ctlr->gotinput = 1;
711 #ifdef USE_KPROCS
712 		wakeup(&ctlr->rrendez);
713 #else
714 		smcreceive(edev);
715 #endif
716 	}
717 
718 	while(((regs->txfifoinf & Txstsusedmask) >> Txstsusedshift) != 0) {
719 		/* probably indicates tx completion, just toss it */
720 		junk = regs->txsts;		/* pop tx sts */
721 		USED(junk);
722 		coherence();
723 	}
724 
725 	intr = intsts & Txintrs;
726 	if (ctlr->gotoutput || intr) {
727 		/* disable interrupt sources; kproc/smctransmit will reenable */
728 		ackintr(regs, intr);
729 
730 		ctlr->tintr++;
731 		ctlr->gotoutput = 1;
732 #ifdef USE_KPROCS
733 		wakeup(&ctlr->trendez);
734 #else
735 		smctransmit(edev);
736 #endif
737 	}
738 
739 	iunlock(&ctlr->imlock);
740 }
741 
742 static void
etherclock(void)743 etherclock(void)
744 {
745 	smcinterrupt(nil, thisether);
746 }
747 
748 static int
smcmii(Ctlr *)749 smcmii(Ctlr *)
750 {
751 	return 0;
752 }
753 
754 static int
smcdetach(Ctlr * ctlr)755 smcdetach(Ctlr* ctlr)
756 {
757 	Regs *regs;
758 
759 	if (ctlr == nil || ctlr->regs == nil)
760 		return -1;
761 	regs = ctlr->regs;
762 	/* verify that it's real by reading a few registers */
763 	switch (regs->id) {
764 	case Vid9221:
765 		break;
766 	default:
767 		print("smc: unknown chip id %#ux\n", regs->id);
768 		return -1;
769 	}
770 	regs->inten = 0;		/* no interrupts */
771 	regs->intsts = ~0;		/* clear any pending */
772 	regs->gptcfg = 0;
773 	coherence();
774 	regs->rxcfg = Rxdump;
775 	regs->txcfg = Txsdump | Txddump;
776 	regs->irqcfg &= ~Irqen;
777 	coherence();
778 	return 0;
779 }
780 
781 static void
smcshutdown(Ether * ether)782 smcshutdown(Ether* ether)
783 {
784 	smcdetach(ether->ctlr);
785 }
786 
787 static void
powerwait(Regs * regs)788 powerwait(Regs *regs)
789 {
790 	long bound;
791 
792 	regs->bytetest = 0;			/* bring power on */
793 	for (bound = 400*Mhz; !(regs->pmtctl & Dready) && bound > 0; bound--)
794 		;
795 	if (bound <= 0)
796 		iprint("smc: pmtctl didn't come ready\n");
797 }
798 
799 static int
smcreset(Ctlr * ctlr)800 smcreset(Ctlr* ctlr)
801 {
802 	int r;
803 	Regs *regs;
804 	static char zea[Eaddrlen];
805 
806 	regs = ctlr->regs;
807 	powerwait(regs);
808 
809 	if(smcdetach(ctlr))
810 		return -1;
811 
812 	/* verify that it's real by reading a few registers */
813 	switch (regs->id) {
814 	case Vid9221:
815 		break;
816 	default:
817 		print("smc: unknown chip id %#ux\n", regs->id);
818 		return -1;
819 	}
820 	if (regs->bytetest != 0x87654321) {
821 		print("smc: bytetest reg %#p (%#lux) != 0x87654321\n",
822 			&regs->bytetest, regs->bytetest);
823 		return -1;
824 	}
825 
826 #ifdef TODO			/* read MAC from EEPROM */
827 //	int ctrl, i, pause, swdpio, txcw;
828 	/*
829 	 * Snarf and set up the receive addresses.
830 	 * There are 16 addresses. The first should be the MAC address.
831 	 * The others are cleared and not marked valid (MS bit of Rah).
832 	 */
833 	for(i = Ea; i < Eaddrlen/2; i++){
834 		ctlr->ra[2*i] = ctlr->eeprom[i];
835 		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
836 	}
837 
838 	/*
839 	 * Clear the Multicast Table Array.
840 	 * It's a 4096 bit vector accessed as 128 32-bit registers.
841 	 */
842 	memset(ctlr->mta, 0, sizeof(ctlr->mta));
843 	for(i = 0; i < 128; i++)
844 		csr32w(ctlr, Mta+i*4, 0);
845 #endif
846 	regs->hwcfg |= Mbo;
847 
848 	/* don't overwrite existing ea */
849 //	if (memcmp(edev->ea, zea, Eaddrlen) == 0)
850 //		memmove(edev->ea, ctlr->ra, Eaddrlen);
851 
852 	r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
853 	macwr(regs, Macaddrl, r);
854 	macwr(regs, Macaddrh, ctlr->ra[5]<<8 | ctlr->ra[4]);
855 
856 	/* turn on the controller */
857 	macwr(regs, Maccoe, 0);
858 	regs->inten = 0;		/* no interrupts yet */
859 	regs->intsts = ~0;		/* clear any pending */
860 	regs->gptcfg = 0;
861 	coherence();
862 	regs->rxcfg = Rxdump;
863 	regs->txcfg = Txsdump | Txddump | Txon;
864 	regs->fifoint = 72<<24;		/* default values */
865 	macwr(regs, Maccr, Rxall | Rcvown | Fdpx | Mcpas | Txen | Rxen);
866 	coherence();		/* back-to-back write/read delay per §6.2.1 */
867 	regs->irqcfg = 1<<24 | Irqen | Irqpushpull;  /* deas for 10µs (linux) */
868 	coherence();		/* back-to-back write/read delay per §6.2.1 */
869 	regs->inten = Rxintrs | Txintrs;
870 	coherence();
871 
872 	if(smcmii(ctlr) < 0)
873 		return -1;
874 	return 0;
875 }
876 
877 static void
smcpci(void)878 smcpci(void)
879 {
880 	Ctlr *ctlr;
881 	static int beenhere;
882 
883 	if (beenhere)
884 		return;
885 	beenhere = 1;
886 
887 	if (probeaddr(PHYSETHER) < 0)
888 		return;
889 	ctlr = malloc(sizeof(Ctlr));
890 	ctlr->id = Vid9221<<16 | 0x0424;	/* smsc 9221 */
891 	ctlr->port = PHYSETHER;
892 	ctlr->nic = (int *)PHYSETHER;
893 	ctlr->regs = (Regs *)PHYSETHER;
894 
895 	if(smcreset(ctlr)){
896 		free(ctlr);
897 		return;
898 	}
899 	if(smcctlrhead != nil)
900 		smcctlrtail->next = ctlr;
901 	else
902 		smcctlrhead = ctlr;
903 	smcctlrtail = ctlr;
904 }
905 
906 static int
smcpnp(Ether * edev)907 smcpnp(Ether* edev)
908 {
909 	Ctlr *ctlr;
910 	static char zea[Eaddrlen];
911 
912 	if(smcctlrhead == nil)
913 		smcpci();
914 
915 	/*
916 	 * Any adapter matches if no edev->port is supplied,
917 	 * otherwise the ports must match.
918 	 */
919 	for(ctlr = smcctlrhead; ctlr != nil; ctlr = ctlr->next){
920 		if(ctlr->active)
921 			continue;
922 		if(edev->port == 0 || edev->port == ctlr->port){
923 			ctlr->active = 1;
924 			break;
925 		}
926 	}
927 	if(ctlr == nil)
928 		return -1;
929 
930 	edev->ctlr = ctlr;
931 	ctlr->edev = edev;			/* point back to Ether* */
932 	edev->port = ctlr->port;
933 	edev->irq = 34;
934 // TODO: verify speed (100Mb/s) and duplicity (full-duplex)
935 	edev->mbps = 100;
936 
937 	/* don't overwrite existing ea */
938 	if (memcmp(edev->ea, zea, Eaddrlen) == 0)
939 		memmove(edev->ea, ctlr->ra, Eaddrlen);
940 
941 	/*
942 	 * Linkage to the generic ethernet driver.
943 	 */
944 	edev->attach = smcattach;
945 	edev->transmit = smctransmitcall;
946 	edev->interrupt = smcinterrupt;
947 	edev->ifstat = smcifstat;
948 /*	edev->ctl = smcctl;			/* no ctl msgs supported */
949 
950 	edev->arg = edev;
951 	edev->promiscuous = smcpromiscuous;
952 	edev->multicast = smcmulticast;
953 	edev->shutdown = smcshutdown;
954 	return 0;
955 }
956 
957 void
ether9221link(void)958 ether9221link(void)
959 {
960 	addethercard("9221", smcpnp);
961 }
962