xref: /inferno-os/os/cerf405/etheremac.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 /*
2  * ethernet
3  */
4 
5 #include "u.h"
6 #include "lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 #include "../port/error.h"
12 #include "../port/netif.h"
13 
14 #include "ethermii.h"
15 #include "etherif.h"
16 #include "ureg.h"
17 
18 /*
19  * TO DO:
20  *	- test EMAC1
21  */
22 
23 #define	DBG	if(0)iprint
24 #define	MIIDBG	if(0)iprint
25 
26 enum {
27 	Nrdre		= 64,	/* receive descriptor ring entries */
28 	Ntdre		= 32,	/* transmit descriptor ring entries */
29 	Nrxchan		= 2,
30 	Ntxchan		= 2,	/* there are actually 4 but we only use 2 now */
31 
32 	Rbsize		= ETHERMAXTU,		/* ring buffer size */
33 	Bufsize		= (Rbsize+CACHELINESZ-1)&~(CACHELINESZ-1),	/* aligned */
34 };
35 
36 enum {
37 	/* emac-specific Rx BD bits */
38 	RxOverrun=	1<<9,	/* not enough empty space in FIFO */
39 	RxPause=		1<<8,	/* control pause packet */
40 	RxBad=		1<<7,	/* packet error */
41 	RxRunt=		1<<6,
42 	RxShort=		1<<5,
43 	RxAlign=		1<<4,
44 	RxFCS=		1<<3,
45 	RxLong=		1<<2,
46 	RxRange=		1<<1,	/* out of range error */
47 	RxInRange=	1<<0,	/* in range error */
48 	RxError=		(0x3FF & ~RxPause),	/* error flags */
49 
50 	/* emac-specific Tx BD bits */
51 	/* write access */
52 	TxFCS=		1<<9,	/* generate FCS */
53 	TxPad=		1<<8,	/* pad short frames */
54 	TxInsSA=		1<<7,	/* insert source address */
55 	TxRepSA=		1<<6,	/* replace source address */
56 	TxInsVLAN=	1<<5,	/* insert VLAN tag */
57 	TxRepVLAN=	1<<4,	/* replace VLAN tag */
58 
59 	/* read access (status) */
60 	TxBadFCS=	1<<9,
61 	TxBadPrev=	1<<8,	/* bad previous packet in dependent mode */
62 	TxLostCarrier=	1<<7,
63 	TxEDef=		1<<6,	/* excessive deferral */
64 	TxECol=		1<<5,	/* excessive collisions */
65 	TxLateCol=	1<<4,	/* late collision (half-duplex only) */
66 	TxManyCol=	1<<3,	/* more than 1 but less than 16 collisions */
67 	TxCollision=	1<<2,	/* single collision */
68 	TxUnderrun=	1<<1,	/* didn't fill FIFO in time */
69 	TxSQE=		1<<0,	/* signal quality test failed (10mbit half-duplex only) */
70 	TxError=		0x3FF,	/* error flags */
71 };
72 
73 typedef struct Emac Emac;
74 struct Emac {
75 	ulong	mr0;		/* mode register 0 [see 19-48] */
76 	ulong	mr1;		/* mode register 1 [Reset] */
77 	ulong	tmr0;	/* transmit mode register 0 [see 19-28] */
78 	ulong	tmr1;	/* transmit mode register 1 [see 19-28] */
79 	ulong	rmr;		/* receive mode register [Reset] */
80 	ulong	isr;		/* interrupt status register [Always] */
81 	ulong	iser;		/* interrupt status enable register [Reset] */
82 	ulong	iahr;		/* individual address high [Reset, R, T]*/
83 	ulong	ialr;		/* individual address low [Reset, R, T] */
84 	ulong	vtpid;	/* VLAN Tag Protocol Identifier [Reset, R, T] */
85 	ulong	vtci;		/* VLAN Tag Control Information [Reset, R, T] */
86 	ulong	ptr;		/* pause timer [Reset, T] */
87 	ulong	iaht[4];	/* individual address hash table [Reset, R] */
88 	ulong	gaht[4];	/* group address hash table [Reset, R] */
89 	ulong	lsah;		/* last source address high */
90 	ulong	lsal;		/* last source address low */
91 	ulong	ipgvr;	/* inter-packet gap value [Reset, T] */
92 	ulong	stacr;	/* STA control register [see 19-41] */
93 	ulong	trtr;		/* transmit request threshold register [see 19-42] */
94 	ulong	rwmr;	/* receive low/high water mark [Reset] */
95 	ulong	octx;		/* bytes transmitted */
96 	ulong	ocrx;	/* bytes received */
97 };
98 
99 enum {
100 	/* mode register 0 */
101 	Mr0Rxi=	1<<31,	/* receive MAC idle */
102 	Mr0Txi=	1<<30,	/* transmit MAC idle */
103 	Mr0Srst=	1<<29,	/* soft reset; soft reset in progress */
104 	Mr0Txe=	1<<28,	/* tx MAC enable */
105 	Mr0Rxe=	1<<27,	/* rx MAC enable */
106 	Mr0Wke=	1<<26,	/* enable wake-up packets */
107 
108 	/* mode register 1 */
109 	Mr1Fde=	1<<31,	/* full-duplex enable */
110 	Mr1Ile=	1<<30,	/* internal loop-back enable */
111 	Mr1Vle=	1<<29,	/* VLAN enable */
112 	Mr1Eifc=	1<<28,	/* enable integrated flow control */
113 	Mr1App=	1<<27,	/* allow pause packets */
114 	Mr1Ist=	1<<24,	/* ignore sqe test (all but half-duplex 10m/bit) */
115 	Mr1Mf10=	0<<22,	/* medium [MII] frequency is 10 mbps */
116 	Mr1Mf100=	1<<22,	/* medium frequency is 100 mbps */
117 	Mr1Rfs512=	0<<20,	/* RX FIFO size (512 bytes) */
118 	Mr1Rfs1024=	1<<20,
119 	Mr1Rfs2048=	2<<20,
120 	Mr1Rfs4096=	3<<20,
121 	Mr1Tfs1024=	1<<18,	/* TX FIFO size (1024 bytes) */
122 	Mr1Tfs2048=	2<<18,
123 	Mr1Tr0sp=	0<<15,	/* transmit request 0: single packet */
124 	Mr1Tr0mp=	1<<15,	/* multiple packets */
125 	Mr1Tr0dm=	2<<15,	/* dependent mode */
126 	Mr1Tr1sp=	0<<13,	/* transmit request 1: single packet */
127 	Mr1Tr1mp=	1<<13,	/* multiple packets */
128 	Mr1Tr1dm=	2<<13,	/* dependent mode */
129 
130 	/* transmit mode register 0 */
131 	Tmr0Gnp0=	1<<31,	/* get new packet channel 0 */
132 	Tmr0Gnp1=	1<<30,	/* get new packet channel 1 */
133 	Tmr0Gnpd=	1<<29,	/* get new packet dependent mode */
134 	Tmr0Fc=		1<<28,	/* first channel (dependent mode) */
135 
136 	/* transmit mode register 1 */
137 	Tmr1Trl_s=	27,		/* transmit low request (shift) */
138 	Tmr1Tur_s=	16,		/* transmit urgent request (shift) */
139 
140 	/* receive mode register */
141 	RmrSp=		1<<31,	/* strip pad/FCS bytes */
142 	RmrSfcs=		1<<30,	/* strip FCS */
143 	RmrRrp=		1<<29,	/* receive runt packets */
144 	RmrRfp=		1<<28,	/* receive packets with FCS error */
145 	RmrRop=		1<<27,	/* receive oversize packets */
146 	RmrRpir=		1<<26,	/* receive packets with in range error */
147 	RmrPpp=		1<<25,	/* propagate pause packet */
148 	RmrPme=		1<<24,	/* promiscuous mode enable */
149 	RmrPmme=	1<<23,	/* promiscuous mode multicast enable */
150 	RmrIae=		1<<22,	/* individual address enable */
151 	RmrMiae=		1<<21,	/* multiple individual address enable */
152 	RmrBae=		1<<20,	/* broadcast address enable */
153 	RmrMae=		1<<19,	/* multicast address enable */
154 
155 	/* interrupt status register */
156 	IsrOvr=		1<<25,	/* overrun error */
157 	IsrPp=		1<<24,	/* pause packet */
158 	IsrBp=		1<<23,	/* bad packet */
159 	IsrRp=		1<<22,	/* runt packet */
160 	IsrSe=		1<<21,	/* short event */
161 	IsrAle=		1<<20,	/* alignment error */
162 	IsrBfcs=		1<<19,	/* bad FCS */
163 	IsrPtle=		1<<18,	/* packet too long error */
164 	IsrOre=		1<<17,	/* out of range error */
165 	IsrIre=		1<<16,	/* in range error */
166 	IsrDbdm=		1<<9,	/* dead bit dependent mode */
167 	IsrDb0=		1<<8,	/* dead bit 0 */
168 	IsrSe0=		1<<7,	/* sqe 0 */
169 	IsrTe0=		1<<6,	/* tx error 0 */
170 	IsrDb1=		1<<5,	/* dead bit 1 */
171 	IsrSe1=		1<<4,	/* sqe 1 */
172 	IsrTe1=		1<<3,	/* tx error 1 */
173 	IsrMos=		1<<1,	/* MMA operation succeeded */
174 	IsrMof=		1<<0,	/* MMA operation failed */
175 
176 	/* STA control register */
177 	StaOc=		1<<15,	/* operation complete */
178 	StaPhye=		1<<14,	/* PHY error */
179 	StaRead=		1<<12,	/* STA read */
180 	StaWrite=		2<<12,	/* STA write */
181 	StaOpb50=	0<<10,	/* OPB frequency */
182 	StaOpb66=	1<<10,
183 	StaOpb83=	2<<10,
184 	StaOpb100=	3<<10,
185 
186 	/* transmit request threshold */
187 	TrtrTrt_s=		27,	/* threshold (shift) -- and the value is (threshold/64)-1 */
188 
189 	/* receive low/high water mark register */
190 	RwmrRlwm_s=	23,	/* low water mark (shift) */
191 	RwmrRhwm_s=	7,	/* high water mark (shift) */
192 };
193 
194 typedef struct {
195 	Lock;
196 	int	port;
197 	int	init;
198 	int	active;
199 	Emac	*regs;
200 	Emac	*miiregs;
201 	Mal*	rx;
202 	Mal*	tx;
203 
204 	Mii	*mii;
205 
206 	Ring;
207 
208 	ulong	interrupts;			/* statistics */
209 	ulong	deferred;
210 	ulong	heartbeat;
211 	ulong	latecoll;
212 	ulong	retrylim;
213 	ulong	underrun;
214 	ulong	overrun;
215 	ulong	carrierlost;
216 	ulong	retrycount;
217 } Ctlr;
218 
219 static void dumpemac(Emac*);
220 
221 static void
attach(Ether * ether)222 attach(Ether *ether)
223 {
224 	Ctlr *ctlr;
225 
226 	ctlr = ether->ctlr;
227 	ilock(ctlr);
228 	if(!ctlr->active){
229 		malrxenable(ctlr->rx);
230 		maltxenable(ctlr->tx);
231 		eieio();
232 		ctlr->regs->mr0 = Mr0Txe | Mr0Rxe;
233 		eieio();
234 		ctlr->active = 1;
235 	}
236 	iunlock(ctlr);
237 }
238 
239 static void
closed(Ether * ether)240 closed(Ether *ether)
241 {
242 	Ctlr *ctlr;
243 
244 	ctlr = ether->ctlr;
245 	if(ctlr->active){
246 		ilock(ctlr);
247 iprint("ether closed\n");
248 		ctlr->regs->mr0 &= ~(Mr0Txe | Mr0Rxe);	/* reset enable bits */
249 		/* TO DO: reset ring */
250 		/* TO DO: could wait */
251 		ctlr->active = 0;
252 		iunlock(ctlr);
253 	}
254 }
255 
256 static void
promiscuous(void * arg,int on)257 promiscuous(void* arg, int on)
258 {
259 	Ether *ether;
260 	Ctlr *ctlr;
261 
262 	ether = (Ether*)arg;
263 	ctlr = ether->ctlr;
264 
265 	ilock(ctlr);
266 	if(on || ether->nmaddr)
267 		ctlr->regs->rmr |= RmrPme | RmrPmme;
268 	else
269 		ctlr->regs->rmr &= ~(RmrPme | RmrPmme);
270 	iunlock(ctlr);
271 }
272 
273 static void
multicast(void * arg,uchar * addr,int on)274 multicast(void* arg, uchar *addr, int on)
275 {
276 	Ether *ether;
277 	Ctlr *ctlr;
278 
279 	USED(addr, on);	/* if on, could SetGroupAddress; if !on, it's hard */
280 
281 	ether = (Ether*)arg;
282 	ctlr = ether->ctlr;
283 
284 	ilock(ctlr);
285 	if(ether->prom || ether->nmaddr)
286 		ctlr->regs->rmr |= RmrPmme;
287 	else
288 		ctlr->regs->rmr &= ~RmrPmme;
289 	iunlock(ctlr);
290 }
291 
292 static void
txstart(Ether * ether)293 txstart(Ether *ether)
294 {
295 	int len;
296 	Ctlr *ctlr;
297 	Block *b;
298 	BD *dre;
299 
300 	ctlr = ether->ctlr;
301 	while(ctlr->ntq < ctlr->ntdre-1){
302 		b = qget(ether->oq);
303 		if(b == 0)
304 			break;
305 
306 		dre = &ctlr->tdr[ctlr->tdrh];
307 		if(dre->status & BDReady)
308 			panic("ether: txstart");
309 
310 		/*
311 		 * Give ownership of the descriptor to the chip, increment the
312 		 * software ring descriptor pointer and tell the chip to poll.
313 		 */
314 		len = BLEN(b);
315 		if(ctlr->txb[ctlr->tdrh] != nil)
316 			panic("etheremac: txstart");
317 		ctlr->txb[ctlr->tdrh] = b;
318 		dre->addr = PADDR(b->rp);
319 		dre->length = len;
320 		dcflush(b->rp, len);
321 		eieio();
322 		dre->status = (dre->status & BDWrap) | BDReady|BDInt|BDLast|TxFCS|TxPad;
323 		eieio();
324 		ctlr->regs->tmr0 = Tmr0Gnp0;	/* TO DO: several channels */
325 		eieio();
326 		ctlr->ntq++;
327 		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdre);
328 	}
329 }
330 
331 static void
transmit(Ether * ether)332 transmit(Ether* ether)
333 {
334 	Ctlr *ctlr;
335 
336 	ctlr = ether->ctlr;
337 	ilock(ctlr);
338 	txstart(ether);
339 	iunlock(ctlr);
340 }
341 
342 /*
343  * allocate receive buffer space on cache-line boundaries
344  */
345 static Block*
clallocb(void)346 clallocb(void)
347 {
348 	Block *b;
349 
350 	b = iallocb(Bufsize+CACHELINESZ-1);
351 	if(b == nil)
352 		return b;
353 	dcflush(b->base, BALLOC(b));
354 	b->wp = b->rp = (uchar*)(((ulong)b->base + CACHELINESZ - 1) & ~(CACHELINESZ-1));
355 	return b;
356 }
357 
358 
359 static void
rxring(Ureg *,void * arg)360 rxring(Ureg*, void *arg)
361 {
362 	Ether *ether;
363 	ulong status;
364 	Ctlr *ctlr;
365 	BD *dre;
366 	Block *b, *rb;
367 
368 	ether = arg;
369 	ctlr = ether->ctlr;
370 	ctlr->interrupts++;
371 
372 	/*
373 	 * Receiver interrupt: run round the descriptor ring logging
374 	 * errors and passing valid receive data up to the higher levels
375 	 * until we encounter a descriptor still owned by the chip.
376 	 * We rely on the descriptor accesses being uncached.
377 	 */
378 	dre = &ctlr->rdr[ctlr->rdrx];
379 	while(((status = dre->status) & BDEmpty) == 0){
380 		if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
381 			if(status & (RxShort|RxLong))
382 				ether->buffs++;
383 			if(status & (RxBad|RxAlign|RxRange|RxInRange))
384 				ether->frames++;
385 			if(status & RxFCS)
386 				ether->crcs++;
387 			if(status & RxOverrun)
388 				ether->overflows++;
389 			iprint("eth rx: %lux\n", status);
390 		}else if((status & RxPause) == 0){
391 			/*
392 			 * We have a packet. Read it in.
393 			 */
394 			b = clallocb();
395 			if(b != nil){
396 				rb = ctlr->rxb[ctlr->rdrx];
397 				rb->wp += dre->length;
398 				ctlr->rxb[ctlr->rdrx] = b;
399 				ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp);
400 				etheriq(ether, rb, 1);
401 			}else
402 				ether->soverflows++;
403 		}
404 
405 		/*
406 		 * Finished with this descriptor, reinitialise it,
407 		 * give it back to the chip, then on to the next...
408 		 */
409 		dre->status = (status & BDWrap) | BDEmpty | BDInt;
410 		eieio();
411 
412 		ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdre);
413 		dre = &ctlr->rdr[ctlr->rdrx];
414 	}
415 }
416 
417 static void
txring(Ureg *,void * arg)418 txring(Ureg*, void *arg)
419 {
420 	Ether *ether;
421 	ulong status;
422 	Ctlr *ctlr;
423 	BD *dre;
424 	Block *b;
425 
426 	ether = arg;
427 	ctlr = ether->ctlr;
428 	ctlr->interrupts++;
429 
430 	/*
431 	 * Transmitter interrupt: handle anything queued for a free descriptor.
432 	 */
433 	lock(ctlr);
434 	while(ctlr->ntq){
435 		dre = &ctlr->tdr[ctlr->tdri];
436 		status = dre->status;
437 		if(status & BDReady)
438 			break;
439 		if(status & TxEDef)
440 			ctlr->deferred++;
441 		if(status & TxLateCol)
442 			ctlr->latecoll++;
443 		if(status & TxECol)
444 			ctlr->retrylim++;
445 		if(status & TxUnderrun)
446 			ctlr->underrun++;
447 		if(status & (TxManyCol|TxCollision))
448 			ctlr->retrycount++;
449 		b = ctlr->txb[ctlr->tdri];
450 		if(b == nil)
451 			panic("etheremac: bufp");
452 		ctlr->txb[ctlr->tdri] = nil;
453 		freeb(b);
454 		ctlr->ntq--;
455 		ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdre);
456 	}
457 	txstart(ether);
458 	unlock(ctlr);
459 }
460 
461 static void
interrupt(Ureg *,void * arg)462 interrupt(Ureg*, void *arg)
463 {
464 	Ether *ether;
465 	ulong events;
466 	Ctlr *ctlr;
467 
468 	ether = arg;
469 	ctlr = ether->ctlr;
470 
471 	events = ctlr->regs->isr;
472 	eieio();
473 	ctlr->regs->isr = events;
474 	eieio();
475 	ctlr->interrupts++;
476 //iprint("eth: %8.8lux\n", events);
477 	if(!ctlr->active || events == 0)
478 		return;
479 
480 	if(events & IsrOvr)
481 		ctlr->overrun++;
482 	if(events & (IsrTe0|IsrTe1))
483 		ether->oerrs++;
484 
485 	rxring(nil, arg);
486 	txring(nil, arg);
487 	ctlr->interrupts -= 2;
488 
489 	/* TO DO: restart tx/rx on error */
490 }
491 
492 static long
ifstat(Ether * ether,void * a,long n,ulong offset)493 ifstat(Ether* ether, void* a, long n, ulong offset)
494 {
495 	char *p;
496 	int len;
497 	Ctlr *ctlr;
498 
499 	if(n == 0)
500 		return 0;
501 
502 	ctlr = ether->ctlr;
503 
504 	p = malloc(READSTR);
505 	len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
506 	len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost);
507 	len += snprint(p+len, READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat);
508 	len += snprint(p+len, READSTR-len, "retrylimit: %lud\n", ctlr->retrylim);
509 	len += snprint(p+len, READSTR-len, "retrycount: %lud\n", ctlr->retrycount);
510 	len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", ctlr->latecoll);
511 	len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", ctlr->overrun);
512 	len += snprint(p+len, READSTR-len, "txunderruns: %lud\n", ctlr->underrun);
513 	snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->deferred);
514 	n = readstr(offset, a, n, p);
515 	free(p);
516 
517 	return n;
518 }
519 
520 static QLock miilock;	/* the PHY are both on EMAC0's MII bus */
521 
522 static int
miird(Mii * mii,int pa,int ra)523 miird(Mii *mii, int pa, int ra)
524 {
525 	Ctlr *ctlr;
526 	Emac *em;
527 	ulong r;
528 	int i;
529 
530 	if(up)
531 		qlock(&miilock);
532 	ctlr = mii->ctlr;
533 	em = ctlr->miiregs;
534 	MIIDBG("r: %x.%x:", pa, ra);
535 	if((em->stacr & StaOc) == 0)
536 		iprint("mii-not oc\n");
537 	em->stacr = StaRead | StaOpb66 | (pa<<5) | ra;
538 	for(i=0; i<100 && (em->stacr & StaOc) == 0; i++)
539 		microdelay(1);
540 	r = em->stacr;
541 	if(up)
542 		qunlock(&miilock);
543 	if((r & StaOc) == 0)
544 		iprint("mii'-not oc\n");
545 	if(r & StaPhye)
546 		return -1;
547 	MIIDBG(" %8.8lux\n", r);
548 	return r >> 16;
549 }
550 
551 static int
miiwr(Mii * mii,int pa,int ra,int v)552 miiwr(Mii *mii, int pa, int ra, int v)
553 {
554 	Ctlr *ctlr;
555 	Emac *em;
556 	ulong r;
557 	int i;
558 
559 	if(up)
560 		qlock(&miilock);
561 	ctlr = mii->ctlr;
562 	em = ctlr->miiregs;
563 	if((em->stacr & StaOc) == 0)
564 		iprint("miiw-not oc\n");
565 	em->stacr = (v<<16) | StaWrite | StaOpb66 | (pa<<5) | ra;
566 	for(i=0; i<100 && (em->stacr & StaOc) == 0; i++)
567 		microdelay(1);
568 	r = em->stacr;
569 	if(up)
570 		qunlock(&miilock);
571 	if((r & StaOc) == 0)
572 		iprint("miiw'-not oc\n");
573 	if(r & StaPhye)
574 		return -1;
575 	MIIDBG("w: %x.%x: %8.8lux\n", pa, ra, r);
576 	return 0;
577 }
578 
579 static int
emacmii(Ctlr * ctlr)580 emacmii(Ctlr *ctlr)
581 {
582 	MiiPhy *phy;
583 	int i;
584 
585 	MIIDBG("mii\n");
586 	if((ctlr->mii = malloc(sizeof(Mii))) == nil)
587 		return -1;
588 	ctlr->mii->ctlr = ctlr;
589 	ctlr->mii->mir = miird;
590 	ctlr->mii->miw = miiwr;
591 
592 	if(mii(ctlr->mii, 1<<(ctlr->port+1)) == 0 || (phy = ctlr->mii->curphy) == nil){
593 		free(ctlr->mii);
594 		ctlr->mii = nil;
595 		return -1;
596 	}
597 
598 	iprint("oui %X phyno %d\n", phy->oui, phy->phyno);
599 	if(miistatus(ctlr->mii) < 0){
600 
601 		miireset(ctlr->mii);
602 		MIIDBG("miireset\n");
603 		if(miiane(ctlr->mii, ~0, 0, ~0) < 0){
604 			iprint("miiane failed\n");
605 			return -1;
606 		}
607 		MIIDBG("miistatus...\n");
608 		miistatus(ctlr->mii);
609 		if(miird(ctlr->mii, phy->phyno, Bmsr) & BmsrLs){
610 			for(i=0;; i++){
611 				if(i > 600){
612 					iprint("emac%d: autonegotiation failed\n", ctlr->port);
613 					break;
614 				}
615 				if(miird(ctlr->mii, phy->phyno, Bmsr) & BmsrAnc)
616 					break;
617 				delay(10);
618 			}
619 			if(miistatus(ctlr->mii) < 0)
620 				iprint("miistatus failed\n");
621 		}else{
622 			iprint("emac%d: no link\n", ctlr->port);
623 			phy->speed = 10;	/* simple default */
624 		}
625 	}
626 
627 	iprint("emac%d mii: fd=%d speed=%d tfc=%d rfc=%d\n", ctlr->port, phy->fd, phy->speed, phy->tfc, phy->rfc);
628 
629 	MIIDBG("mii done\n");
630 
631 	return 0;
632 }
633 
634 static void
emacsetup(Ctlr * ctlr,Ether * ether)635 emacsetup(Ctlr *ctlr, Ether *ether)
636 {
637 	int i;
638 	Emac *em;
639 	ulong mode;
640 	MiiPhy *phy;
641 
642 	/* apparently don't need to set any Alt1 in GPIO */
643 
644 	em = ctlr->regs;
645 
646 	/* errata emac_8 */
647 	if(em->mr0 & Mr0Rxe){	/* probably never happens in our config */
648 		em->mr0 &= ~Mr0Rxe;
649 		eieio();
650 		for(i=0; (em->mr0 & Mr0Rxi) == 0; i++){
651 			if(i > 100){
652 				iprint("ethermac: Rxe->Rxi timed out\n");
653 				break;	/* we'll try soft reset anyway */
654 			}
655 			microdelay(100);
656 		}
657 	}
658 
659 	/* soft reset */
660 	em->mr0 = Mr0Srst;
661 	eieio();
662 	for(i=0; em->mr0 & Mr0Srst; i++){
663 		if(i > 20){
664 			iprint("ethermac: reset (PHY clocks not running?)");
665 			i=0;
666 		}
667 		microdelay(100);
668 	}
669 iprint("%d: rx=%8.8lux tx=%8.8lux\n", ctlr->port, PADDR(ctlr->rdr), PADDR(ctlr->tdr));
670 //if(ctlr->port)return;
671 
672 	malrxinit(ctlr->rx, ctlr, Bufsize/16);
673 	maltxinit(ctlr->tx, ctlr);
674 	malrxreset(ctlr->rx);
675 	maltxreset(ctlr->tx);
676 
677 	em->mr0 = 0;
678 	mode = Mr1Rfs4096 | Mr1Tfs2048 | Mr1Tr0mp;
679 	if(ctlr->mii != nil && (phy = ctlr->mii->curphy) != nil){
680 		if(phy->speed == 10){
681 			mode |= Mr1Mf10;
682 			if(phy->fd)
683 				mode |= Mr1Ist;
684 		}else
685 			mode |= Mr1Mf100 | Mr1Ist;
686 		if(phy->fd)
687 			mode |= Mr1Fde;
688 		/* errata emac_9 suggests not using integrated flow control (it's broken); so don't negotiate it */
689 		if(0 && (phy->rfc || phy->tfc))
690 			mode |= Mr1App | Mr1Eifc;
691 		ether->mbps = phy->speed;
692 		ether->fullduplex = phy->fd;
693 	}else{
694 		iprint("mii: didn't work: default 100FD\n");
695 		mode |= Mr1Mf100 | Mr1Ist | Mr1Fde;
696 		ether->mbps = 100;
697 		ether->fullduplex = 1;
698 	}
699 
700 	em->mr1 = mode;
701 	em->tmr1 = (9<<Tmr1Trl_s) | (256<<Tmr1Tur_s);	/* TO DO: validate these sizes */
702 	em->rmr = RmrSp | RmrSfcs | RmrIae | RmrBae;
703 	em->iahr = (ether->ea[0]<<8) | ether->ea[1];
704 	em->ialr = (ether->ea[2]<<24) | (ether->ea[3]<<16) | (ether->ea[4]<<8) | ether->ea[5];
705 	em->vtpid = 0;
706 	em->vtci = 0;
707 	em->ptr = 1;		/* pause timer [Reset, T] */
708 	for(i=0; i<4; i++){
709 		em->iaht[i] = 0;	/* individual address hash table */
710 		em->gaht[i] = 0;	/* group address hash table */
711 	}
712 	em->ipgvr = (96/8)/3;	/* minimise bit times between packets */
713 	em->trtr = ((256/64)-1)<<TrtrTrt_s;		/* transmission threshold (probably could be smaller) */
714 	em->rwmr = (32<<RwmrRlwm_s) | (128<<RwmrRhwm_s);	/* receive low/high water mark (TO DO: check) */
715 	/* 0x0f002000? */
716 	//dumpemac(em);
717 	//dumpmal();
718 	eieio();
719 	em->isr = em->isr;		/* clear all events */
720 	eieio();
721 	em->iser = IsrOvr | IsrBp | IsrSe | IsrSe0 | IsrTe0 | IsrSe1 | IsrTe1;	/* enable various error interrupts */
722 	/* packet tx/rx interrupts come from MAL */
723 	eieio();
724 
725 	/* tx/rx enable is deferred until attach */
726 }
727 
728 static int
reset(Ether * ether)729 reset(Ether* ether)
730 {
731 	uchar ea[Eaddrlen];
732 	Ctlr *ctlr;
733 	int i;
734 
735 	ioringreserve(Nrxchan, Nrdre, Ntxchan, Ntdre);
736 
737 	/*
738 	 * Insist that the platform-specific code provide the Ethernet address
739 	 */
740 	memset(ea, 0, Eaddrlen);
741 	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
742 		print("no ether address");
743 		return -1;
744 	}
745 
746 	ctlr = malloc(sizeof(*ctlr));
747 	ctlr->port = ether->port;
748 
749 	switch(ether->port){
750 	case 0:
751 		ctlr->regs = KADDR(PHYSEMAC0);
752 		ctlr->miiregs = ctlr->regs;
753 		ctlr->rx = malchannel(0, 0, rxring, ether);
754 		ctlr->tx = malchannel(0, 1, txring, ether);
755 		ether->irq = VectorEMAC0;
756 		break;
757 	case 1:
758 		ctlr->regs = KADDR(PHYSEMAC1);
759 		ctlr->miiregs = KADDR(PHYSEMAC0);	/* p. 19-41: ``only the MDIO interface for EMAC0 is pinned out'' */
760 		ctlr->rx = malchannel(1, 0, rxring, ether);
761 		ctlr->tx = malchannel(2, 1, txring, ether);
762 		ether->irq = VectorEMAC1;
763 		break;
764 	default:
765 		print("%s ether: no port %lud\n", ether->type, ether->port);
766 		free(ctlr);
767 		return -1;
768 	}
769 
770 	if(emacmii(ctlr) < 0){
771 		free(ctlr);
772 		return -1;
773 	}
774 
775 	ether->ctlr = ctlr;
776 
777 	if(ioringinit(ctlr, Nrdre, Ntdre) < 0)	/* TO DO: there are two transmit rings*/
778 		panic("etheremac initring");
779 
780 	for(i = 0; i < ctlr->nrdre; i++){
781 		ctlr->rxb[i] = clallocb();
782 		ctlr->rdr[i].addr = PADDR(ctlr->rxb[i]->wp);
783 	}
784 
785 	emacsetup(ctlr, ether);
786 
787 	ether->attach = attach;
788 	ether->closed = closed;
789 	ether->transmit = transmit;
790 	ether->interrupt = interrupt;	/* oddly, it's only error interrupts; see malchannel call above for tx/rx */
791 	ether->ifstat = ifstat;
792 
793 	ether->arg = ether;
794 	ether->promiscuous = promiscuous;
795 	ether->multicast = multicast;
796 
797 	return 0;
798 }
799 
800 void
etheremaclink(void)801 etheremaclink(void)
802 {
803 	addethercard("EMAC", reset);
804 }
805 
806 static void
dumpemac(Emac * r)807 dumpemac(Emac *r)
808 {
809 	iprint("mr0=%8.8lux\n", r->mr0);		/* mode register 0 [see 19-48] */
810 	iprint("mr1=%8.8lux\n", r->mr1);		/* mode register 1 [Reset] */
811 	iprint("tmr0=%8.8lux\n", r->tmr0);	/* transmit mode register 0 [see 19-28] */
812 	iprint("tmr1=%8.8lux\n", r->tmr1);	/* transmit mode register 1 [see 19-28] */
813 	iprint("rmr=%8.8lux\n", r->rmr);		/* receive mode register [Reset] */
814 	iprint("isr=%8.8lux\n", r->isr);		/* interrupt status register [Always] */
815 	iprint("iser=%8.8lux\n", r->iser);		/* interrupt status enable register [Reset] */
816 	iprint("iahr=%8.8lux\n", r->iahr);		/* individual address high [Reset, R, T]*/
817 	iprint("ialr=%8.8lux\n", r->ialr);		/* individual address low [Reset, R, T] */
818 	iprint("vtpid=%8.8lux\n", r->vtpid);	/* VLAN Tag Protocol Identifier [Reset, R, T] */
819 	iprint("vtci=%8.8lux\n", r->vtci);		/* VLAN Tag Control Information [Reset, R, T] */
820 	iprint("ptr=%8.8lux\n", r->ptr);		/* pause timer [Reset, T] */
821 	iprint("lsah=%8.8lux\n", r->lsah);		/* last source address high */
822 	iprint("lsal=%8.8lux\n", r->lsal);		/* last source address low */
823 	iprint("ipgvr=%8.8lux\n", r->ipgvr);	/* inter-packet gap value [Reset, T] */
824 	iprint("stacr=%8.8lux\n", r->stacr);	/* STA control register [see 19-41] */
825 	iprint("trtr=%8.8lux\n", r->trtr);		/* transmit request threshold register [see 19-42] */
826 	iprint("rwmr=%8.8lux\n", r->rwmr);	/* receive low/high water mark [Reset] */
827 	iprint("octx=%8.8lux\n", r->octx);		/* bytes transmitted */
828 	iprint("ocrx=%8.8lux\n", r->ocrx);	/* bytes received */
829 }
830