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
 * National Semiconductor DP83815
3
 *
4
 * Supports only internal PHY and has been tested on:
5
 *	Netgear FA311TX (using Netgear DS108 10/100 hub)
6
 *	SiS 900 within SiS 630
7
 * To do:
8
 *	check Ethernet address;
9
 *	test autonegotiation on 10 Mbit, and 100 Mbit full duplex;
10
 *	external PHY via MII (should be common code for MII);
11
 *	thresholds;
12
 *	ring sizing;
13
 *	physical link changes/disconnect;
14
 *	push initialisation back to attach.
15
 *
16
 * C H Forsyth, forsyth@vitanuova.com, 18th June 2001.
17
 */
18
 
19
#include "u.h"
20
#include "../port/lib.h"
21
#include "mem.h"
22
#include "dat.h"
23
#include "fns.h"
24
#include "io.h"
25
#include "../port/error.h"
26
#include "../port/netif.h"
27
 
28
#include "etherif.h"
29
 
30
#define DEBUG		0
31
#define debug		if(DEBUG)print
32
 
33
enum {
34
	Nrde		= 64,
35
	Ntde		= 64,
36
};
37
 
38
#define Rbsz		ROUNDUP(sizeof(Etherpkt)+4, 4)
39
 
40
typedef struct Des {
41
	ulong	next;
42
	int	cmdsts;
43
	ulong	addr;
44
	Block*	bp;
45
} Des;
46
 
47
enum {	/* cmdsts */
48
	Own	= 1<<31,	/* set by data producer to hand to consumer */
49
	More	= 1<<30,	/* more of packet in next descriptor */
50
	Intr	= 1<<29,	/* interrupt when device is done with it */
51
	Supcrc	= 1<<28,	/* suppress crc on transmit */
52
	Inccrc	= 1<<28,	/* crc included on receive (always) */
53
	Ok	= 1<<27,	/* packet ok */
54
	Size	= 0xFFF,	/* packet size in bytes */
55
 
56
	/* transmit */
57
	Txa	= 1<<26,	/* transmission aborted */
58
	Tfu	= 1<<25,	/* transmit fifo underrun */
59
	Crs	= 1<<24,	/* carrier sense lost */
60
	Td	= 1<<23,	/* transmission deferred */
61
	Ed	= 1<<22,	/* excessive deferral */
62
	Owc	= 1<<21,	/* out of window collision */
63
	Ec	= 1<<20,	/* excessive collisions */
64
	/* 19-16 collision count */
65
 
66
	/* receive */
67
	Rxa	= 1<<26,	/* receive aborted (same as Rxo) */
68
	Rxo	= 1<<25,	/* receive overrun */
69
	Dest	= 3<<23,	/* destination class */
70
	  Drej=	0<<23,		/* packet was rejected */
71
	  Duni=	1<<23,		/* unicast */
72
	  Dmulti=	2<<23,		/* multicast */
73
	  Dbroad=	3<<23,		/* broadcast */
74
	Long = 1<<22,		/* too long packet received */
75
	Runt =  1<<21,		/* packet less than 64 bytes */
76
	Ise =	1<<20,		/* invalid symbol */
77
	Crce =	1<<19,		/* invalid crc */
78
	Fae =	1<<18,		/* frame alignment error */
79
	Lbp =	1<<17,		/* loopback packet */
80
	Col =	1<<16,		/* collision during receive */
81
};
82
 
83
enum {				/* PCI vendor & device IDs */
84
	Nat83815	= (0x0020<<16)|0x100B,
85
	SiS = 	0x1039,
86
	SiS900 =	(0x0900<<16)|SiS,
87
	SiS7016 =	(0x7016<<16)|SiS,
88
 
89
	SiS630bridge	= 0x0008,
90
 
91
	/* SiS 900 PCI revision codes */
92
	SiSrev630s =	0x81,
93
	SiSrev630e =	0x82,
94
	SiSrev630ea1 =	0x83,
95
 
96
	SiSeenodeaddr =	8,		/* short addr of SiS eeprom mac addr */
97
	SiS630eenodeaddr =	9,	/* likewise for the 630 */
98
	Nseenodeaddr =	6,		/* " for NS eeprom */
99
	Nat83815avng =	0x403,
100
	Nat83816avng =	0x505,		/* 83816 acts like submodel of 83815 */
101
					/* using reg. 0x58 to disambiguate. */
102
};
103
 
104
typedef struct Ctlr Ctlr;
105
typedef struct Ctlr {
106
	int	port;
107
	Pcidev*	pcidev;
108
	Ctlr*	next;
109
	int	active;
110
	int	id;			/* (pcidev->did<<16)|pcidev->vid */
111
 
112
	ushort	srom[0xB+1];
113
	uchar	sromea[Eaddrlen];	/* MAC address */
114
 
115
	uchar	fd;			/* option or auto negotiation */
116
 
117
	int	mbps;
118
 
119
	Lock	lock;
120
 
121
	Des*	rdr;			/* receive descriptor ring */
122
	int	nrdr;			/* size of rdr */
123
	int	rdrx;			/* index into rdr */
124
 
125
	Lock	tlock;
126
	Des*	tdr;			/* transmit descriptor ring */
127
	int	ntdr;			/* size of tdr */
128
	int	tdrh;			/* host index into tdr */
129
	int	tdri;			/* interface index into tdr */
130
	int	ntq;			/* descriptors active */
131
	int	ntqmax;
132
 
133
	ulong	rxa;			/* receive statistics */
134
	ulong	rxo;
135
	ulong	rlong;
136
	ulong	runt;
137
	ulong	ise;
138
	ulong	crce;
139
	ulong	fae;
140
	ulong	lbp;
141
	ulong	col;
142
	ulong	rxsovr;
143
	ulong	rxorn;
144
 
145
	ulong	txa;			/* transmit statistics */
146
	ulong	tfu;
147
	ulong	crs;
148
	ulong	td;
149
	ulong	ed;
150
	ulong	owc;
151
	ulong	ec;
152
	ulong	txurn;
153
 
154
	ulong	dperr;			/* system errors */
155
	ulong	rmabt;
156
	ulong	rtabt;
157
	ulong	sserr;
158
	ulong	rxsover;
159
 
160
	ulong	version;		/* silicon version; register 0x58h */
161
} Ctlr;
162
 
163
static Ctlr* ctlrhead;
164
static Ctlr* ctlrtail;
165
 
166
enum {
167
	/* registers (could memory map) */
168
	Rcr=	0x00,		/* command register */
169
	  Rst=		1<<8,
170
	  Rxr=		1<<5,	/* receiver reset */
171
	  Txr=		1<<4,	/* transmitter reset */
172
	  Rxd=		1<<3,	/* receiver disable */
173
	  Rxe=		1<<2,	/* receiver enable */
174
	  Txd=		1<<1,	/* transmitter disable */
175
	  Txe=		1<<0,	/* transmitter enable */
176
	Rcfg=	0x04,		/* configuration */
177
	  Lnksts=	1<<31,	/* link good */
178
	  Speed100=	1<<30,	/* 100 Mb/s link */
179
	  Fdup=		1<<29,	/* full duplex */
180
	  Pol=		1<<28,	/* polarity reversal (10baseT) */
181
	  Aneg_dn=	1<<27,	/* autonegotiation done */
182
	  Pint_acen=	1<<17,	/* PHY interrupt auto clear enable */
183
	  Pause_adv=	1<<16,	/* advertise pause during auto neg */
184
	  Paneg_ena=	1<<13,	/* auto negotiation enable */
185
	  Paneg_all=	7<<13,	/* auto negotiation enable 10/100 half & full */
186
	  Ext_phy=	1<<12,	/* enable MII for external PHY */
187
	  Phy_rst=	1<<10,	/* reset internal PHY */
188
	  Phy_dis=	1<<9,	/* disable internal PHY (eg, low power) */
189
	  Req_alg=	1<<7,	/* PCI bus request: set means less aggressive */
190
	  Sb=		1<<6,	/* single slot back-off not random */
191
	  Pow=		1<<5,	/* out of window timer selection */
192
	  Exd=		1<<4,	/* disable excessive deferral timer */
193
	  Pesel=	1<<3,	/* parity error algorithm selection */
194
	  Brom_dis=	1<<2,	/* disable boot rom interface */
195
	  Bem=		1<<0,	/* big-endian mode */
196
	Rmear=	0x08,		/* eeprom access */
197
	  Mdc=		1<<6,	/* MII mangement check */
198
	  Mddir=	1<<5,	/* MII management direction */
199
	  Mdio=		1<<4,	/* MII mangement data */
200
	  Eesel=	1<<3,	/* EEPROM chip select */
201
	  Eeclk=	1<<2,	/* EEPROM clock */
202
	  Eedo=		1<<1,	/* EEPROM data out (from chip) */
203
	  Eedi=		1<<0,	/* EEPROM data in (to chip) */
204
	Rptscr=	0x0C,		/* pci test control */
205
	Risr=	0x10,		/* interrupt status */
206
	  Txrcmp=	1<<25,	/* transmit reset complete */
207
	  Rxrcmp=	1<<24,	/* receiver reset complete */
208
	  Dperr=	1<<23,	/* detected parity error */
209
	  Sserr=	1<<22,	/* signalled system error */
210
	  Rmabt=	1<<21,	/* received master abort */
211
	  Rtabt=	1<<20,	/* received target abort */
212
	  Rxsovr=	1<<16,	/* RX status FIFO overrun */
213
	  Hiberr=	1<<15,	/* high bits error set (OR of 25-16) */
214
	  Phy=		1<<14,	/* PHY interrupt */
215
	  Pme=		1<<13,	/* power management event (wake online) */
216
	  Swi=		1<<12,	/* software interrupt */
217
	  Mib=		1<<11,	/* MIB service */
218
	  Txurn=	1<<10,	/* TX underrun */
219
	  Txidle=	1<<9,	/* TX idle */
220
	  Txerr=	1<<8,	/* TX packet error */
221
	  Txdesc=	1<<7,	/* TX descriptor (with Intr bit done) */
222
	  Txok=		1<<6,	/* TX ok */
223
	  Rxorn=	1<<5,	/* RX overrun */
224
	  Rxidle=	1<<4,	/* RX idle */
225
	  Rxearly=	1<<3,	/* RX early threshold */
226
	  Rxerr=	1<<2,	/* RX packet error */
227
	  Rxdesc=	1<<1,	/* RX descriptor (with Intr bit done) */
228
	  Rxok=		1<<0,	/* RX ok */
229
	Rimr=	0x14,		/* interrupt mask */
230
	Rier=	0x18,		/* interrupt enable */
231
	  Ie=		1<<0,	/* interrupt enable */
232
	Rtxdp=	0x20,		/* transmit descriptor pointer */
233
	Rtxcfg=	0x24,		/* transmit configuration */
234
	  Csi=		1<<31,	/* carrier sense ignore (needed for full duplex) */
235
	  Hbi=		1<<30,	/* heartbeat ignore (needed for full duplex) */
236
	  Atp=		1<<28,	/* automatic padding of runt packets */
237
	  Mxdma=	7<<20,	/* maximum dma transfer field */
238
	  Mxdma32=	4<<20,	/* 4x32-bit words (32 bytes) */
239
	  Mxdma64=	5<<20,	/* 8x32-bit words (64 bytes) */
240
	  Flth=		0x3F<<8,/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
241
	  Drth=		0x3F<<0,/* Tx drain threshold (units of 32 bytes) */
242
	  Flth128=	4<<8,	/* fill at 128 bytes */
243
	  Drth512=	16<<0,	/* drain at 512 bytes */
244
	Rrxdp=	0x30,		/* receive descriptor pointer */
245
	Rrxcfg=	0x34,		/* receive configuration */
246
	  Atx=		1<<28,	/* accept transmit packets (needed for full duplex) */
247
	  Rdrth=	0x1F<<1,/* Rx drain threshold (units of 32 bytes) */
248
	  Rdrth64=	2<<1,	/* drain at 64 bytes */
249
	Rccsr=	0x3C,		/* CLKRUN control/status */
250
	  Pmests=	1<<15,	/* PME status */
251
	Rwcsr=	0x40,		/* wake on lan control/status */
252
	Rpcr=	0x44,		/* pause control/status */
253
	Rrfcr=	0x48,		/* receive filter/match control */
254
	  Rfen=		1<<31,	/* receive filter enable */
255
	  Aab=		1<<30,	/* accept all broadcast */
256
	  Aam=		1<<29,	/* accept all multicast */
257
	  Aau=		1<<28,	/* accept all unicast */
258
	  Apm=		1<<27,	/* accept on perfect match */
259
	  Apat=		0xF<<23,/* accept on pattern match */
260
	  Aarp=		1<<22,	/* accept ARP */
261
	  Mhen=		1<<21,	/* multicast hash enable */
262
	  Uhen=		1<<20,	/* unicast hash enable */
263
	  Ulm=		1<<19,	/* U/L bit mask */
264
				/* bits 0-9 are rfaddr */
265
	Rrfdr=	0x4C,		/* receive filter/match data */
266
	Rbrar=	0x50,		/* boot rom address */
267
	Rbrdr=	0x54,		/* boot rom data */
268
	Rsrr=	0x58,		/* silicon revision */
269
	Rmibc=	0x5C,		/* MIB control */
270
				/* 60-78 MIB data */
271
 
272
	/* PHY registers */
273
	Rbmcr=	0x80,		/* basic mode configuration */
274
	  Reset=	1<<15,
275
	  Sel100=	1<<13,	/* select 100Mb/sec if no auto neg */
276
	  Anena=	1<<12,	/* auto negotiation enable */
277
	  Anrestart=	1<<9,	/* restart auto negotiation */
278
	  Selfdx=	1<<8,	/* select full duplex if no auto neg */
279
	Rbmsr=	0x84,		/* basic mode status */
280
	  Ancomp=	1<<5,	/* autonegotiation complete */
281
	Rphyidr1= 0x88,
282
	Rphyidr2= 0x8C,
283
	Ranar=	0x90,		/* autonegotiation advertisement */
284
	Ranlpar= 0x94,		/* autonegotiation link partner ability */
285
	Raner=	0x98,		/* autonegotiation expansion */
286
	Rannptr= 0x9C,		/* autonegotiation next page TX */
287
	Rphysts= 0xC0,		/* PHY status */
288
	Rmicr=	0xC4,		/* MII control */
289
	  Inten=	1<<1,	/* PHY interrupt enable */
290
	Rmisr=	0xC8,		/* MII status */
291
	Rfcscr=	0xD0,		/* false carrier sense counter */
292
	Rrecr=	0xD4,		/* receive error counter */
293
	Rpcsr=	0xD8,		/* 100Mb config/status */
294
	Rphycr=	0xE4,		/* PHY control */
295
	Rtbscr=	0xE8,		/* 10BaseT status/control */
296
};
297
 
298
/*
299
 * eeprom addresses
300
 * 	7 to 9 (16 bit words): mac address, shifted and reversed
301
 */
302
 
303
#define csr32r(c, r)	(inl((c)->port+(r)))
304
#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))
305
#define csr16r(c, r)	(ins((c)->port+(r)))
306
#define csr16w(c, r, l)	(outs((c)->port+(r), (ulong)(l)))
307
 
308
static void
309
dumpcregs(Ctlr *ctlr)
310
{
311
	int i;
312
 
313
	for(i=0; i<=0x5C; i+=4)
314
		print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));
315
}
316
 
317
static void
318
promiscuous(void* arg, int on)
319
{
320
	Ctlr *ctlr;
321
	ulong w;
322
 
323
	ctlr = ((Ether*)arg)->ctlr;
324
	ilock(&ctlr->lock);
325
	w = csr32r(ctlr, Rrfcr);
326
	if(on != ((w&Aau)!=0)){
327
		csr32w(ctlr, Rrfcr, w & ~Rfen);
328
		csr32w(ctlr, Rrfcr, Rfen | (w ^ Aau));
329
	}
330
	iunlock(&ctlr->lock);
331
}
332
 
333
static void
334
attach(Ether* ether)
335
{
336
	Ctlr *ctlr;
337
 
338
	ctlr = ether->ctlr;
339
	ilock(&ctlr->lock);
340
	if(0)
341
		dumpcregs(ctlr);
342
	csr32w(ctlr, Rcr, Rxe);
343
	iunlock(&ctlr->lock);
344
}
345
 
346
static long
347
ifstat(Ether* ether, void* a, long n, ulong offset)
348
{
349
	Ctlr *ctlr;
350
	char *buf, *p;
351
	int i, l, len;
352
 
353
	ctlr = ether->ctlr;
354
 
355
	ether->crcs = ctlr->crce;
356
	ether->frames = ctlr->runt+ctlr->ise+ctlr->rlong+ctlr->fae;
357
	ether->buffs = ctlr->rxorn+ctlr->tfu;
358
	ether->overflows = ctlr->rxsovr;
359
 
360
	if(n == 0)
361
		return 0;
362
 
363
	p = malloc(READSTR);
364
	if(p == nil)
365
		error(Enomem);
366
	l = snprint(p, READSTR, "Rxa: %lud\n", ctlr->rxa);
367
	l += snprint(p+l, READSTR-l, "Rxo: %lud\n", ctlr->rxo);
368
	l += snprint(p+l, READSTR-l, "Rlong: %lud\n", ctlr->rlong);
369
	l += snprint(p+l, READSTR-l, "Runt: %lud\n", ctlr->runt);
370
	l += snprint(p+l, READSTR-l, "Ise: %lud\n", ctlr->ise);
371
	l += snprint(p+l, READSTR-l, "Fae: %lud\n", ctlr->fae);
372
	l += snprint(p+l, READSTR-l, "Lbp: %lud\n", ctlr->lbp);
373
	l += snprint(p+l, READSTR-l, "Tfu: %lud\n", ctlr->tfu);
374
	l += snprint(p+l, READSTR-l, "Txa: %lud\n", ctlr->txa);
375
	l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->crce);
376
	l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->col);
377
	l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->rlong);
378
	l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->runt);
379
	l += snprint(p+l, READSTR-l, "Rx Underflow Error: %lud\n", ctlr->rxorn);
380
	l += snprint(p+l, READSTR-l, "Tx Underrun: %lud\n", ctlr->txurn);
381
	l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec);
382
	l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->owc);
383
	l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->crs);
384
	l += snprint(p+l, READSTR-l, "Parity: %lud\n", ctlr->dperr);
385
	l += snprint(p+l, READSTR-l, "Aborts: %lud\n", ctlr->rmabt+ctlr->rtabt);
386
	l += snprint(p+l, READSTR-l, "RX Status overrun: %lud\n", ctlr->rxsover);
387
	snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax);
388
	ctlr->ntqmax = 0;
389
	buf = a;
390
	len = readstr(offset, buf, n, p);
391
	if(offset > l)
392
		offset -= l;
393
	else
394
		offset = 0;
395
	buf += len;
396
	n -= len;
397
 
398
	l = snprint(p, READSTR, "srom:");
399
	for(i = 0; i < nelem(ctlr->srom); i++){
400
		if(i && ((i & 0x0F) == 0))
401
			l += snprint(p+l, READSTR-l, "\n     ");
402
		l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->srom[i]);
403
	}
404
 
405
	snprint(p+l, READSTR-l, "\n");
406
	len += readstr(offset, buf, n, p);
407
	free(p);
408
 
409
	return len;
410
}
411
 
412
static void
413
txstart(Ether* ether)
414
{
415
	Ctlr *ctlr;
416
	Block *bp;
417
	Des *des;
418
	int started;
419
 
420
	ctlr = ether->ctlr;
421
	started = 0;
422
	while(ctlr->ntq < ctlr->ntdr-1){
423
		bp = qget(ether->oq);
424
		if(bp == nil)
425
			break;
426
		des = &ctlr->tdr[ctlr->tdrh];
427
		des->bp = bp;
428
		des->addr = PADDR(bp->rp);
429
		ctlr->ntq++;
430
		coherence();
431
		des->cmdsts = Own | BLEN(bp);
432
		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
433
		started = 1;
434
	}
435
	if(started){
436
		coherence();
437
		csr32w(ctlr, Rcr, Txe);	/* prompt */
438
	}
439
 
440
	if(ctlr->ntq > ctlr->ntqmax)
441
		ctlr->ntqmax = ctlr->ntq;
442
}
443
 
444
static void
445
transmit(Ether* ether)
446
{
447
	Ctlr *ctlr;
448
 
449
	ctlr = ether->ctlr;
450
	ilock(&ctlr->tlock);
451
	txstart(ether);
452
	iunlock(&ctlr->tlock);
453
}
454
 
455
static void
456
txrxcfg(Ctlr *ctlr, int txdrth)
457
{
458
	ulong rx, tx;
459
 
460
	rx = csr32r(ctlr, Rrxcfg);
461
	tx = csr32r(ctlr, Rtxcfg);
462
	if(ctlr->fd){
463
		rx |= Atx;
464
		tx |= Csi | Hbi;
465
	}else{
466
		rx &= ~Atx;
467
		tx &= ~(Csi | Hbi);
468
	}
469
	tx &= ~(Mxdma|Drth|Flth);
470
	tx |= Mxdma64 | Flth128 | txdrth;
471
	csr32w(ctlr, Rtxcfg, tx);
472
	rx &= ~(Mxdma|Rdrth);
473
	rx |= Mxdma64 | Rdrth64;
474
	csr32w(ctlr, Rrxcfg, rx);
475
}
476
 
477
static void
478
interrupt(Ureg*, void* arg)
479
{
480
	int len, status, cmdsts, n;
481
	Ctlr *ctlr;
482
	Ether *ether;
483
	Des *des;
484
	Block *bp;
485
 
486
	ether = arg;
487
	ctlr = ether->ctlr;
488
 
489
	while((status = csr32r(ctlr, Risr)) != 0){
490
 
491
		status &= ~(Pme|Mib);
492
 
493
		if(status & Hiberr){
494
			if(status & Rxsovr)
495
				ctlr->rxsover++;
496
			if(status & Sserr)
497
				ctlr->sserr++;
498
			if(status & Dperr)
499
				ctlr->dperr++;
500
			if(status & Rmabt)
501
				ctlr->rmabt++;
502
			if(status & Rtabt)
503
				ctlr->rtabt++;
504
			status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
505
		}
506
 
507
		/* update link state */
508
		if(status&Phy){
509
			status &= ~Phy;
510
			csr32r(ctlr, Rcfg);
511
			n = csr32r(ctlr, Rcfg);
512
//			iprint("83815 phy %x %x\n", n, n&Lnksts);
513
			ether->link = (n&Lnksts) != 0;
514
		}
515
 
516
		/*
517
		 * Received packets.
518
		 */
519
		if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){
520
			des = &ctlr->rdr[ctlr->rdrx];
521
			while((cmdsts = des->cmdsts) & Own){
522
				if((cmdsts&Ok) == 0){
523
					if(cmdsts & Rxa)
524
						ctlr->rxa++;
525
					if(cmdsts & Rxo)
526
						ctlr->rxo++;
527
					if(cmdsts & Long)
528
						ctlr->rlong++;
529
					if(cmdsts & Runt)
530
						ctlr->runt++;
531
					if(cmdsts & Ise)
532
						ctlr->ise++;
533
					if(cmdsts & Crce)
534
						ctlr->crce++;
535
					if(cmdsts & Fae)
536
						ctlr->fae++;
537
					if(cmdsts & Lbp)
538
						ctlr->lbp++;
539
					if(cmdsts & Col)
540
						ctlr->col++;
541
				}
542
				else if(bp = iallocb(Rbsz)){
543
					len = (cmdsts&Size)-4;
544
					if(len <= 0){
545
						debug("ns83815: packet len %d <=0\n", len);
546
						freeb(des->bp);
547
					}else{
548
						des->bp->wp = des->bp->rp+len;
549
						etheriq(ether, des->bp, 1);
550
					}
551
					des->bp = bp;
552
					des->addr = PADDR(bp->rp);
553
					coherence();
554
				}else{
555
					debug("ns83815: interrupt: iallocb for input buffer failed\n");
556
					des->bp->next = 0;
557
				}
558
 
559
				des->cmdsts = Rbsz;
560
				coherence();
561
 
562
				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
563
				des = &ctlr->rdr[ctlr->rdrx];
564
			}
565
			status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);
566
		}
567
 
568
		/*
569
		 * Check the transmit side:
570
		 *	check for Transmit Underflow and Adjust
571
		 *	the threshold upwards;
572
		 *	free any transmitted buffers and try to
573
		 *	top-up the ring.
574
		 */
575
		if(status & Txurn){
576
			ctlr->txurn++;
577
			ilock(&ctlr->lock);
578
			/* change threshold */
579
			iunlock(&ctlr->lock);
580
			status &= ~(Txurn);
581
		}
582
 
583
		ilock(&ctlr->tlock);
584
		while(ctlr->ntq){
585
			des = &ctlr->tdr[ctlr->tdri];
586
			cmdsts = des->cmdsts;
587
			if(cmdsts & Own)
588
				break;
589
 
590
			if((cmdsts & Ok) == 0){
591
				if(cmdsts & Txa)
592
					ctlr->txa++;
593
				if(cmdsts & Tfu)
594
					ctlr->tfu++;
595
				if(cmdsts & Td)
596
					ctlr->td++;
597
				if(cmdsts & Ed)
598
					ctlr->ed++;
599
				if(cmdsts & Owc)
600
					ctlr->owc++;
601
				if(cmdsts & Ec)
602
					ctlr->ec++;
603
				ether->oerrs++;
604
			}
605
 
606
			freeb(des->bp);
607
			des->bp = nil;
608
			des->cmdsts = 0;
609
 
610
			ctlr->ntq--;
611
			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
612
		}
613
		txstart(ether);
614
		iunlock(&ctlr->tlock);
615
 
616
		status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);
617
 
618
		/*
619
		 * Anything left not catered for?
620
		 */
621
		if(status)
622
			print("#l%d: status %8.8uX\n", ether->ctlrno, status);
623
	}
624
}
625
 
626
static void
627
ctlrinit(Ether* ether)
628
{
629
	Ctlr *ctlr;
630
	Des *des, *last;
631
 
632
	ctlr = ether->ctlr;
633
 
634
	/*
635
	 * Allocate suitable aligned descriptors
636
	 * for the transmit and receive rings;
637
	 * initialise the receive ring;
638
	 * initialise the transmit ring;
639
	 * unmask interrupts and start the transmit side.
640
	 */
641
	des = xspanalloc((ctlr->nrdr+ctlr->ntdr)*sizeof(Des), 32, 0);
642
	ctlr->tdr = des;
643
	ctlr->rdr = des+ctlr->ntdr;
644
 
645
	last = nil;
646
	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
647
		des->bp = iallocb(Rbsz);
648
		if(des->bp == nil)
649
			error(Enomem);
650
		des->cmdsts = Rbsz;
651
		des->addr = PADDR(des->bp->rp);
652
		if(last != nil)
653
			last->next = PADDR(des);
654
		last = des;
655
	}
656
	ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);
657
	ctlr->rdrx = 0;
658
	csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));
659
 
660
	last = nil;
661
	for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){
662
		des->cmdsts = 0;
663
		des->bp = nil;
664
		des->addr = ~0;
665
		if(last != nil)
666
			last->next = PADDR(des);
667
		last = des;
668
	}
669
	ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);
670
	ctlr->tdrh = 0;
671
	ctlr->tdri = 0;
672
	csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));
673
 
674
	txrxcfg(ctlr, Drth512);
675
 
676
	csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|
677
		Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok);	/* Phy|Pme|Mib */
678
	csr32w(ctlr, Rmicr, Inten);	/* enable phy interrupts */
679
	csr32r(ctlr, Risr);		/* clear status */
680
	csr32w(ctlr, Rier, Ie);
681
}
682
 
683
static void
684
eeclk(Ctlr *ctlr, int clk)
685
{
686
	csr32w(ctlr, Rmear, Eesel | clk);
687
	microdelay(2);
688
}
689
 
690
static void
691
eeidle(Ctlr *ctlr)
692
{
693
	int i;
694
 
695
	eeclk(ctlr, 0);
696
	eeclk(ctlr, Eeclk);
697
	for(i=0; i<25; i++){
698
		eeclk(ctlr, 0);
699
		eeclk(ctlr, Eeclk);
700
	}
701
	eeclk(ctlr, 0);
702
	csr32w(ctlr, Rmear, 0);
703
	microdelay(2);
704
}
705
 
706
static ushort
707
eegetw(Ctlr *ctlr, int a)
708
{
709
	int d, i, w;
710
 
711
	eeidle(ctlr);
712
	eeclk(ctlr, 0);
713
	eeclk(ctlr, Eeclk);
714
	d = 0x180 | a;
715
	for(i=0x400; i; i>>=1){
716
		if(d & i)
717
			csr32w(ctlr, Rmear, Eesel|Eedi);
718
		else
719
			csr32w(ctlr, Rmear, Eesel);
720
		eeclk(ctlr, Eeclk);
721
		eeclk(ctlr, 0);
722
		microdelay(2);
723
	}
724
	w = 0;
725
	for(i=0x8000; i; i >>= 1){
726
		eeclk(ctlr, Eeclk);
727
		if(csr32r(ctlr, Rmear) & Eedo)
728
			w |= i;
729
		microdelay(2);
730
		eeclk(ctlr, 0);
731
	}
732
	eeidle(ctlr);
733
	return w;
734
}
735
 
736
static int
737
resetctlr(Ctlr *ctlr)
738
{
739
	int i;
740
 
741
	/*
742
	 * Soft-reset the controller
743
	 */
744
	csr32w(ctlr, Rcr, Rst);
745
	for(i=0;; i++){
746
		if(i > 100){
747
			print("ns83815: soft reset did not complete\n");
748
			return -1;
749
		}
750
		microdelay(250);
751
		if((csr32r(ctlr, Rcr) & Rst) == 0)
752
			break;
753
		delay(1);
754
	}
755
	return 0;
756
}
757
 
758
static void
759
shutdown(Ether* ether)
760
{
761
	Ctlr *ctlr = ether->ctlr;
762
 
763
print("ether83815 shutting down\n");
764
	csr32w(ctlr, Rcr, Rxd|Txd);	/* disable transceiver */
765
	resetctlr(ctlr);
766
}
767
 
768
static int
769
softreset(Ctlr* ctlr, int resetphys)
770
{
771
	int i, w;
772
 
773
	/*
774
	 * Soft-reset the controller
775
	 */
776
	resetctlr(ctlr);
777
	csr32w(ctlr, Rccsr, Pmests);
778
	csr32w(ctlr, Rccsr, 0);
779
	csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);
780
	ctlr->version = csr32r(ctlr, Rsrr);
781
	if(resetphys){
782
		/*
783
		 * Soft-reset the PHY
784
		 */
785
		csr32w(ctlr, Rbmcr, Reset);
786
		for(i=0;; i++){
787
			if(i > 100){
788
				print("ns83815: PHY soft reset time out\n");
789
				return -1;
790
			}
791
			if((csr32r(ctlr, Rbmcr) & Reset) == 0)
792
				break;
793
			delay(1);
794
		}
795
	}
796
 
797
	/*
798
	 * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)
799
	 */
800
	csr16w(ctlr, 0xCC, 0x0001);	/* PGSEL */
801
	csr16w(ctlr, 0xE4, 0x189C);	/* PMCCSR */
802
	csr16w(ctlr, 0xFC, 0x0000);	/* TSTDAT */
803
	csr16w(ctlr, 0xF4, 0x5040);	/* DSPCFG */
804
	csr16w(ctlr, 0xF8, 0x008C);	/* SDCFG */
805
 
806
	/*
807
	 * Auto negotiate
808
	 */
809
	csr16r(ctlr, Rbmsr);		/* clear latched bits */
810
	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
811
	csr16w(ctlr, Rbmcr, Anena);
812
	if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
813
		csr16w(ctlr, Rbmcr, Anena|Anrestart);
814
		for(i=0;; i++){
815
			if(i > 3000){
816
				print("ns83815: auto neg timed out\n");
817
				return -1;
818
			}
819
			if((w = csr16r(ctlr, Rbmsr)) & Ancomp)
820
				break;
821
			delay(1);
822
		}
823
		debug("%d ms\n", i);
824
		w &= 0xFFFF;
825
		debug("bmsr: %4.4ux\n", w);
826
		USED(w);
827
	}
828
	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
829
	debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
830
	debug("aner: %4.4ux\n", csr16r(ctlr, Raner));
831
	debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));
832
	debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));
833
	return 0;
834
}
835
 
836
static int
837
media(Ether* ether)
838
{
839
	Ctlr* ctlr;
840
	ulong cfg;
841
 
842
	ctlr = ether->ctlr;
843
	cfg = csr32r(ctlr, Rcfg);
844
	ctlr->fd = (cfg & Fdup) != 0;
845
	ether->link = (cfg&Lnksts) != 0;
846
	return (cfg&(Lnksts|Speed100)) == Lnksts? 10: 100;
847
}
848
 
849
static char* mediatable[9] = {
850
	"10BASE-T",				/* TP */
851
	"10BASE-2",				/* BNC */
852
	"10BASE-5",				/* AUI */
853
	"100BASE-TX",
854
	"10BASE-TFD",
855
	"100BASE-TXFD",
856
	"100BASE-T4",
857
	"100BASE-FX",
858
	"100BASE-FXFD",
859
};
860
 
861
static int
862
is630(ulong id, Pcidev *p)
863
{
864
	if(id == SiS900)
865
		switch (p->rid) {
866
		case SiSrev630s:
867
		case SiSrev630e:
868
	  	case SiSrev630ea1:
869
			return 1;
870
		}
871
	return 0;
872
}
873
 
874
enum {
875
	MagicReg = 0x48,
876
	MagicRegSz = 1,
877
	Magicrden = 0x40,	/* read enable, apparently */
878
	Paddr=		0x70,	/* address port */
879
	Pdata=		0x71,	/* data port */
880
};
881
 
882
/* rcmos() originally from LANL's SiS 900 driver's rcmos() */
883
static int
884
sisrdcmos(Ctlr *ctlr)
885
{
886
	int i;
887
	unsigned reg;
888
	ulong port;
889
	Pcidev *p;
890
 
891
	debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid);
892
	p = pcimatch(nil, SiS, SiS630bridge);
893
	if(p == nil) {
894
		print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n",
895
			ctlr->pcidev->rid);
896
		return 0;
897
	}
898
	port = p->mem[0].bar & ~0x01;
899
	debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port);
900
 
901
	reg = pcicfgr8(p, MagicReg);
902
	pcicfgw8(p, MagicReg, reg|Magicrden);
903
 
904
	for (i = 0; i < Eaddrlen; i++) {
905
		outb(port+Paddr, SiS630eenodeaddr + i);
906
		ctlr->sromea[i] = inb(port+Pdata);
907
	}
908
 
909
	pcicfgw8(p, MagicReg, reg & ~Magicrden);
910
	return 1;
911
}
912
 
913
/*
914
 * If this is a SiS 630E chipset with an embedded SiS 900 controller,
915
 * we have to read the MAC address from the APC CMOS RAM. - sez freebsd.
916
 * However, CMOS *is* NVRAM normally.  See devrtc.c:440, memory.c:88.
917
 */
918
static void
919
sissrom(Ctlr *ctlr)
920
{
921
	union {
922
		uchar	eaddr[Eaddrlen];
923
		ushort	alignment;
924
	} ee;
925
	int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short);
926
	ushort *shp = (ushort *)ee.eaddr;
927
 
928
	if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) {
929
		for (i = 0; i < cnt; i++)
930
			*shp++ = eegetw(ctlr, off++);
931
		memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea);
932
	}
933
}
934
 
935
ushort
936
søkrisee(Ctlr *c, int n)
937
{
938
	int i;
939
	uint cmd;
940
	ushort r;
941
 
942
   	csr32w(c, Rmear, Eesel);
943
 
944
	cmd = 0x180|n;
945
	for(i = 10; i >= 0; i--){
946
		n = 1<<3;
947
		if(cmd&(1<<i))
948
			n |= 1;
949
		csr32w(c, Rmear, n);
950
		csr32r(c, Rmear);
951
		csr32w(c, Rmear, n|4);
952
		csr32r(c, Rmear);
953
	}
954
 
955
	csr32w(c, Rmear, 1<<3);
956
	csr32r(c, Rmear);
957
 
958
	r = 0;
959
	for(i = 0; i < 16; i++){
960
		csr32w(c, Rmear, 1<<3 | 1<<2);
961
		csr32r(c, Rmear);
962
		if(csr32r(c, Rmear) & 2)
963
			r |= 1<<i;
964
		csr32w(c, Rmear, 1<<3);
965
		csr32r(c, Rmear);
966
	}
967
 
968
	csr32w(c, Rmear, 1<<3);
969
	csr32w(c, Rmear, 0);
970
 
971
	return r;
972
}
973
 
974
static void
975
nsnormalea(Ctlr *ctlr)
976
{
977
	int i, j;
978
 
979
	/*
980
	 * the MAC address is reversed, straddling word boundaries
981
	 */
982
	j = Nseenodeaddr*16 + 15;
983
	for(i = 0; i < 48; i++){
984
		ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
985
		j++;
986
	}
987
}
988
 
989
static void
990
ns403ea(Ctlr *ctlr)
991
{
992
	int i;
993
	ushort s, t;
994
 
995
	s = ctlr->srom[6];
996
	for(i = 0; i < 3; i++){
997
		t = ctlr->srom[i+7];
998
		ctlr->sromea[i*2]   = t<<1 | s>>15;
999
		ctlr->sromea[i*2+1] = t>>7;
1000
		s = t;
1001
	}
1002
}
1003
 
1004
static void
1005
nssrom(Ctlr* ctlr)
1006
{
1007
	int i, ns403;
1008
	ulong vers;
1009
	ushort (*ee)(Ctlr*, int);
1010
 
1011
	vers = ctlr->version;
1012
	ns403 = vers == Nat83815avng || vers == Nat83816avng;
1013
	if(ns403){
1014
		ee = søkrisee;
1015
		print("soekris %lx\n", vers);
1016
	}else
1017
		ee = eegetw;
1018
 
1019
	for(i = 0; i < nelem(ctlr->srom); i++)
1020
		ctlr->srom[i] = ee(ctlr, i);
1021
 
1022
	if(ns403)
1023
		ns403ea(ctlr);
1024
	else
1025
		nsnormalea(ctlr);
1026
}
1027
 
1028
static void
1029
srom(Ctlr* ctlr)
1030
{
1031
	memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
1032
	switch (ctlr->id) {
1033
	case SiS900:
1034
	case SiS7016:
1035
		sissrom(ctlr);
1036
		break;
1037
	case Nat83815:
1038
		nssrom(ctlr);
1039
		break;
1040
	default:
1041
		print("ns83815: srom: unknown id 0x%ux\n", ctlr->id);
1042
		break;
1043
	}
1044
}
1045
 
1046
static void
1047
scanpci83815(void)
1048
{
1049
	Ctlr *ctlr;
1050
	Pcidev *p;
1051
	ulong id;
1052
 
1053
	p = nil;
1054
	while(p = pcimatch(p, 0, 0)){
1055
		if(p->ccrb != Pcibcnet || p->ccru != 0)
1056
			continue;
1057
		id = (p->did<<16)|p->vid;
1058
		switch(id){
1059
		default:
1060
			continue;
1061
 
1062
		case Nat83815:
1063
			break;
1064
		case SiS900:
1065
			break;
1066
		}
1067
 
1068
		/*
1069
		 * bar[0] is the I/O port register address and
1070
		 * bar[1] is the memory-mapped register address.
1071
		 */
1072
		ctlr = malloc(sizeof(Ctlr));
1073
		if(ctlr == nil)
1074
			error(Enomem);
1075
		ctlr->port = p->mem[0].bar & ~0x01;
1076
		ctlr->pcidev = p;
1077
		ctlr->id = id;
1078
 
1079
		if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){
1080
			print("ns83815: port 0x%uX in use\n", ctlr->port);
1081
			free(ctlr);
1082
			continue;
1083
		}
1084
 
1085
		if(softreset(ctlr, 0) == -1){
1086
			free(ctlr);
1087
			continue;
1088
		}
1089
		srom(ctlr);
1090
 
1091
		if(ctlrhead != nil)
1092
			ctlrtail->next = ctlr;
1093
		else
1094
			ctlrhead = ctlr;
1095
		ctlrtail = ctlr;
1096
	}
1097
}
1098
 
1099
/* multicast already on, don't need to do anything */
1100
static void
1101
multicast(void*, uchar*, int)
1102
{
1103
}
1104
 
1105
static int
1106
reset(Ether* ether)
1107
{
1108
	Ctlr *ctlr;
1109
	int i, x;
1110
	ulong ctladdr;
1111
	uchar ea[Eaddrlen];
1112
	static int scandone;
1113
 
1114
	if(scandone == 0){
1115
		scanpci83815();
1116
		scandone = 1;
1117
	}
1118
 
1119
	/*
1120
	 * Any adapter matches if no ether->port is supplied,
1121
	 * otherwise the ports must match.
1122
	 */
1123
	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
1124
		if(ctlr->active)
1125
			continue;
1126
		if(ether->port == 0 || ether->port == ctlr->port){
1127
			ctlr->active = 1;
1128
			break;
1129
		}
1130
	}
1131
	if(ctlr == nil)
1132
		return -1;
1133
 
1134
	ether->ctlr = ctlr;
1135
	ether->port = ctlr->port;
1136
	ether->irq = ctlr->pcidev->intl;
1137
	ether->tbdf = ctlr->pcidev->tbdf;
1138
 
1139
	/*
1140
	 * Check if the adapter's station address is to be overridden.
1141
	 * If not, read it from the EEPROM and set in ether->ea prior to
1142
	 * loading the station address in the hardware.
1143
	 */
1144
	memset(ea, 0, Eaddrlen);
1145
	if(memcmp(ea, ether->ea, Eaddrlen) == 0)
1146
		memmove(ether->ea, ctlr->sromea, Eaddrlen);
1147
	for(i=0; i<Eaddrlen; i+=2){
1148
		x = ether->ea[i] | (ether->ea[i+1]<<8);
1149
		ctladdr = (ctlr->id == Nat83815? i: i<<15);
1150
		csr32w(ctlr, Rrfcr, ctladdr);
1151
		csr32w(ctlr, Rrfdr, x);
1152
	}
1153
	csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
1154
 
1155
	ether->mbps = media(ether);
1156
 
1157
	/*
1158
	 * Look for a medium override in case there's no autonegotiation
1159
	 * the autonegotiation fails.
1160
	 */
1161
 
1162
	for(i = 0; i < ether->nopt; i++){
1163
		if(cistrcmp(ether->opt[i], "FD") == 0){
1164
			ctlr->fd = 1;
1165
			continue;
1166
		}
1167
		for(x = 0; x < nelem(mediatable); x++){
1168
			debug("compare <%s> <%s>\n", mediatable[x],
1169
				ether->opt[i]);
1170
			if(cistrcmp(mediatable[x], ether->opt[i]) == 0){
1171
				if(x != 4 && x >= 3)
1172
					ether->mbps = 100;
1173
				else
1174
					ether->mbps = 10;
1175
				switch(x){
1176
				default:
1177
					ctlr->fd = 0;
1178
					break;
1179
 
1180
				case 0x04:		/* 10BASE-TFD */
1181
				case 0x05:		/* 100BASE-TXFD */
1182
				case 0x08:		/* 100BASE-FXFD */
1183
					ctlr->fd = 1;
1184
					break;
1185
				}
1186
				break;
1187
			}
1188
		}
1189
	}
1190
 
1191
	/*
1192
	 * Initialise descriptor rings, ethernet address.
1193
	 */
1194
	ctlr->nrdr = Nrde;
1195
	ctlr->ntdr = Ntde;
1196
	pcisetbme(ctlr->pcidev);
1197
	ctlrinit(ether);
1198
 
1199
	/*
1200
	 * Linkage to the generic ethernet driver.
1201
	 */
1202
	ether->attach = attach;
1203
	ether->transmit = transmit;
1204
	ether->interrupt = interrupt;
1205
	ether->ifstat = ifstat;
1206
 
1207
	ether->arg = ether;
1208
	ether->promiscuous = promiscuous;
1209
	ether->multicast = multicast;
1210
	ether->shutdown = shutdown;
1211
	return 0;
1212
}
1213
 
1214
void
1215
ether83815link(void)
1216
{
1217
	addethercard("83815",  reset);
1218
}