Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
410
smcmulticast(void*, uchar*, int)
411
{
412
	/* nothing to do, we allow all multicast packets in */
413
}
414
 
415
static int
416
iswrcpydone(void *arg)
417
{
418
	return ((Ctlr *)arg)->wrcpydone;
419
}
420
 
421
static int
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
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
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
507
smcrim(void* ctlr)
508
{
509
	return ((Ctlr*)ctlr)->gotinput;
510
}
511
 
512
static void
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
531
smcgotout(void* ctlr)
532
{
533
	return ((Ctlr*)ctlr)->gotoutput;
534
}
535
 
536
static void
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
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
598
isrdcpydone(void *arg)
599
{
600
	return ((Ctlr *)arg)->rdcpydone;
601
}
602
 
603
static void
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
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
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
743
etherclock(void)
744
{
745
	smcinterrupt(nil, thisether);
746
}
747
 
748
static int
749
smcmii(Ctlr *)
750
{
751
	return 0;
752
}
753
 
754
static int
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
782
smcshutdown(Ether* ether)
783
{
784
	smcdetach(ether->ctlr);
785
}
786
 
787
static void
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
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
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
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
958
ether9221link(void)
959
{
960
	addethercard("9221", smcpnp);
961
}