Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * National Semiconductor DP83820
3
 * 10/100/1000 Mb/s Ethernet Network Interface Controller
4
 * (Gig-NIC).
5
 * Driver assumes little-endian and 32-bit host throughout.
6
 */
7
#include "u.h"
8
#include "../port/lib.h"
9
#include "mem.h"
10
#include "dat.h"
11
#include "fns.h"
12
#include "io.h"
13
#include "../port/error.h"
14
#include "../port/netif.h"
15
 
16
#include "etherif.h"
17
#include "ethermii.h"
18
 
19
enum {					/* Registers */
20
	Cr		= 0x00,		/* Command */
21
	Cfg		= 0x04,		/* Configuration and Media Status */
22
	Mear		= 0x08,		/* MII/EEPROM Access */
23
	Ptscr		= 0x0C,		/* PCI Test Control */
24
	Isr		= 0x10,		/* Interrupt Status */
25
	Imr		= 0x14,		/* Interrupt Mask */
26
	Ier		= 0x18,		/* Interrupt Enable */
27
	Ihr		= 0x1C,		/* Interrupt Holdoff */
28
	Txdp		= 0x20,		/* Transmit Descriptor Pointer */
29
	Txdphi		= 0x24,		/* Transmit Descriptor Pointer Hi */
30
	Txcfg		= 0x28,		/* Transmit Configuration */
31
	Gpior		= 0x2C,		/* General Purpose I/O Control */
32
	Rxdp		= 0x30,		/* Receive Descriptor Pointer */
33
	Rxdphi		= 0x34,		/* Receive Descriptor Pointer Hi */
34
	Rxcfg		= 0x38,		/* Receive Configuration */
35
	Pqcr		= 0x3C,		/* Priority Queueing Control */
36
	Wcsr		= 0x40,		/* Wake on LAN Control/Status */
37
	Pcr		= 0x44,		/* Pause Control/Status */
38
	Rfcr		= 0x48,		/* Receive Filter/Match Control */
39
	Rfdr		= 0x4C,		/* Receive Filter/Match Data */
40
	Brar		= 0x50,		/* Boot ROM Address */
41
	Brdr		= 0x54,		/* Boot ROM Data */
42
	Srr		= 0x58,		/* Silicon Revision */
43
	Mibc		= 0x5C,		/* MIB Control */
44
	Mibd		= 0x60,		/* MIB Data */
45
	Txdp1		= 0xA0,		/* Txdp Priority 1 */
46
	Txdp2		= 0xA4,		/* Txdp Priority 2 */
47
	Txdp3		= 0xA8,		/* Txdp Priority 3 */
48
	Rxdp1		= 0xB0,		/* Rxdp Priority 1 */
49
	Rxdp2		= 0xB4,		/* Rxdp Priority 2 */
50
	Rxdp3		= 0xB8,		/* Rxdp Priority 3 */
51
	Vrcr		= 0xBC,		/* VLAN/IP Receive Control */
52
	Vtcr		= 0xC0,		/* VLAN/IP Transmit Control */
53
	Vdr		= 0xC4,		/* VLAN Data */
54
	Ccsr		= 0xCC,		/* Clockrun Control/Status */
55
	Tbicr		= 0xE0,		/* TBI Control */
56
	Tbisr		= 0xE4,		/* TBI Status */
57
	Tanar		= 0xE8,		/* TBI ANAR */
58
	Tanlpar		= 0xEC,		/* TBI ANLPAR */
59
	Taner		= 0xF0,		/* TBI ANER */
60
	Tesr		= 0xF4,		/* TBI ESR */
61
};
62
 
63
enum {					/* Cr */
64
	Txe		= 0x00000001,	/* Transmit Enable */
65
	Txd		= 0x00000002,	/* Transmit Disable */
66
	Rxe		= 0x00000004,	/* Receiver Enable */
67
	Rxd		= 0x00000008,	/* Receiver Disable */
68
	Txr		= 0x00000010,	/* Transmitter Reset */
69
	Rxr		= 0x00000020,	/* Receiver Reset */
70
	Swien		= 0x00000080,	/* Software Interrupt Enable */
71
	Rst		= 0x00000100,	/* Reset */
72
	TxpriSHFT	= 9,		/* Tx Priority Queue Select */
73
	TxpriMASK	= 0x00001E00,
74
	RxpriSHFT	= 13,		/* Rx Priority Queue Select */
75
	RxpriMASK	= 0x0001E000,
76
};
77
 
78
enum {					/* Configuration and Media Status */
79
	Bem		= 0x00000001,	/* Big Endian Mode */
80
	Ext125		= 0x00000002,	/* External 125MHz reference Select */
81
	Bromdis		= 0x00000004,	/* Disable Boot ROM interface */
82
	Pesel		= 0x00000008,	/* Parity Error Detection Action */
83
	Exd		= 0x00000010,	/* Excessive Deferral Abort */
84
	Pow		= 0x00000020,	/* Program Out of Window Timer */
85
	Sb		= 0x00000040,	/* Single Back-off */
86
	Reqalg		= 0x00000080,	/* PCI Bus Request Algorithm */
87
	Extstsen	= 0x00000100,	/* Extended Status Enable */
88
	Phydis		= 0x00000200,	/* Disable PHY */
89
	Phyrst		= 0x00000400,	/* Reset PHY */
90
	M64addren	= 0x00000800,	/* Master 64-bit Addressing Enable */
91
	Data64en	= 0x00001000,	/* 64-bit Data Enable */
92
	Pci64det	= 0x00002000,	/* PCI 64-bit Bus Detected */
93
	T64addren	= 0x00004000,	/* Target 64-bit Addressing Enable */
94
	Mwidis		= 0x00008000,	/* MWI Disable */
95
	Mrmdis		= 0x00010000,	/* MRM Disable */
96
	Tmrtest		= 0x00020000,	/* Timer Test Mode */
97
	Spdstsien	= 0x00040000,	/* PHY Spdsts Interrupt Enable */
98
	Lnkstsien	= 0x00080000,	/* PHY Lnksts Interrupt Enable */
99
	Dupstsien	= 0x00100000,	/* PHY Dupsts Interrupt Enable */
100
	Mode1000	= 0x00400000,	/* 1000Mb/s Mode Control */
101
	Tbien		= 0x01000000,	/* Ten-Bit Interface Enable */
102
	Dupsts		= 0x10000000,	/* Full Duplex Status */
103
	Spdsts100	= 0x20000000,	/* SPEED100 Input Pin Status */
104
	Spdsts1000	= 0x40000000,	/* SPEED1000 Input Pin Status */
105
	Lnksts		= 0x80000000,	/* Link Status */
106
};
107
 
108
enum {					/* MII/EEPROM Access */
109
	Eedi		= 0x00000001,	/* EEPROM Data In */
110
	Eedo		= 0x00000002,	/* EEPROM Data Out */
111
	Eeclk		= 0x00000004,	/* EEPROM Serial Clock */
112
	Eesel		= 0x00000008,	/* EEPROM Chip Select */
113
	Mdio		= 0x00000010,	/* MII Management Data */
114
	Mddir		= 0x00000020,	/* MII Management Direction */
115
	Mdc		= 0x00000040,	/* MII Management Clock */
116
};
117
 
118
enum {					/* Interrupts */
119
	Rxok		= 0x00000001,	/* Rx OK */
120
	Rxdesc		= 0x00000002,	/* Rx Descriptor */
121
	Rxerr		= 0x00000004,	/* Rx Packet Error */
122
	Rxearly		= 0x00000008,	/* Rx Early Threshold */
123
	Rxidle		= 0x00000010,	/* Rx Idle */
124
	Rxorn		= 0x00000020,	/* Rx Overrun */
125
	Txok		= 0x00000040,	/* Tx Packet OK */
126
	Txdesc		= 0x00000080,	/* Tx Descriptor */
127
	Txerr		= 0x00000100,	/* Tx Packet Error */
128
	Txidle		= 0x00000200,	/* Tx Idle */
129
	Txurn		= 0x00000400,	/* Tx Underrun */
130
	Mib		= 0x00000800,	/* MIB Service */
131
	Swi		= 0x00001000,	/* Software Interrupt */
132
	Pme		= 0x00002000,	/* Power Management Event */
133
	Phy		= 0x00004000,	/* PHY Interrupt */
134
	Hibint		= 0x00008000,	/* High Bits Interrupt Set */
135
	Rxsovr		= 0x00010000,	/* Rx Status FIFO Overrun */
136
	Rtabt		= 0x00020000,	/* Received Target Abort */
137
	Rmabt		= 0x00040000,	/* Received Master Abort */
138
	Sserr		= 0x00080000,	/* Signalled System Error */
139
	Dperr		= 0x00100000,	/* Detected Parity Error */
140
	Rxrcmp		= 0x00200000,	/* Receive Reset Complete */
141
	Txrcmp		= 0x00400000,	/* Transmit Reset Complete */
142
	Rxdesc0		= 0x00800000,	/* Rx Descriptor for Priority Queue 0 */
143
	Rxdesc1		= 0x01000000,	/* Rx Descriptor for Priority Queue 1 */
144
	Rxdesc2		= 0x02000000,	/* Rx Descriptor for Priority Queue 2 */
145
	Rxdesc3		= 0x04000000,	/* Rx Descriptor for Priority Queue 3 */
146
	Txdesc0		= 0x08000000,	/* Tx Descriptor for Priority Queue 0 */
147
	Txdesc1		= 0x10000000,	/* Tx Descriptor for Priority Queue 1 */
148
	Txdesc2		= 0x20000000,	/* Tx Descriptor for Priority Queue 2 */
149
	Txdesc3		= 0x40000000,	/* Tx Descriptor for Priority Queue 3 */
150
};
151
 
152
enum {					/* Interrupt Enable */
153
	Ien		= 0x00000001,	/* Interrupt Enable */
154
};
155
 
156
enum {					/* Interrupt Holdoff */
157
	IhSHFT		= 0,		/* Interrupt Holdoff */
158
	IhMASK		= 0x000000FF,
159
	Ihctl		= 0x00000100,	/* Interrupt Holdoff Control */
160
};
161
 
162
enum {					/* Transmit Configuration */
163
	TxdrthSHFT	= 0,		/* Tx Drain Threshold */
164
	TxdrthMASK	= 0x000000FF,
165
	FlthSHFT	= 16,		/* Tx Fill Threshold */
166
	FlthMASK	= 0x0000FF00,
167
	Brstdis		= 0x00080000,	/* 1000Mb/s Burst Disable */
168
	MxdmaSHFT	= 20,		/* Max Size per Tx DMA Burst */
169
	MxdmaMASK	= 0x00700000,
170
	Ecretryen	= 0x00800000,	/* Excessive Collision Retry Enable */
171
	Atp		= 0x10000000,	/* Automatic Transmit Padding */
172
	Mlb		= 0x20000000,	/* MAC Loopback */
173
	Hbi		= 0x40000000,	/* Heartbeat Ignore */
174
	Csi		= 0x80000000,	/* Carrier Sense Ignore */
175
};
176
 
177
enum {					/* Receive Configuration */
178
	RxdrthSHFT	= 1,		/* Rx Drain Threshold */
179
	RxdrthMASK	= 0x0000003E,
180
	Airl		= 0x04000000,	/* Accept In-Range Length Errored */
181
	Alp		= 0x08000000,	/* Accept Long Packets */
182
	Rxfd		= 0x10000000,	/* Receive Full Duplex */
183
	Stripcrc	= 0x20000000,	/* Strip CRC */
184
	Arp		= 0x40000000,	/* Accept Runt Packets */
185
	Aep		= 0x80000000,	/* Accept Errored Packets */
186
};
187
 
188
enum {					/* Priority Queueing Control */
189
	Txpqen		= 0x00000001,	/* Transmit Priority Queuing Enable */
190
	Txfairen	= 0x00000002,	/* Transmit Fairness Enable */
191
	RxpqenSHFT	= 2,		/* Receive Priority Queue Enable */
192
	RxpqenMASK	= 0x0000000C,
193
};
194
 
195
enum {					/* Pause Control/Status */
196
	PscntSHFT	= 0,		/* Pause Counter Value */
197
	PscntMASK	= 0x0000FFFF,
198
	Pstx		= 0x00020000,	/* Transmit Pause Frame */
199
	PsffloSHFT	= 18,		/* Rx Data FIFO Lo Threshold */
200
	PsffloMASK	= 0x000C0000,
201
	PsffhiSHFT	= 20,		/* Rx Data FIFO Hi Threshold */
202
	PsffhiMASK	= 0x00300000,
203
	PsstloSHFT	= 22,		/* Rx Stat FIFO Hi Threshold */
204
	PsstloMASK	= 0x00C00000,
205
	PssthiSHFT	= 24,		/* Rx Stat FIFO Hi Threshold */
206
	PssthiMASK	= 0x03000000,
207
	Psrcvd		= 0x08000000,	/* Pause Frame Received */
208
	Psact		= 0x10000000,	/* Pause Active */
209
	Psda		= 0x20000000,	/* Pause on Destination Address */
210
	Psmcast		= 0x40000000,	/* Pause on Multicast */
211
	Psen		= 0x80000000,	/* Pause Enable */
212
};
213
 
214
enum {					/* Receive Filter/Match Control */
215
	RfaddrSHFT	= 0,		/* Extended Register Address */
216
	RfaddrMASK	= 0x000003FF,
217
	Ulm		= 0x00080000,	/* U/L bit mask */
218
	Uhen		= 0x00100000,	/* Unicast Hash Enable */
219
	Mhen		= 0x00200000,	/* Multicast Hash Enable */
220
	Aarp		= 0x00400000,	/* Accept ARP Packets */
221
	ApatSHFT	= 23,		/* Accept on Pattern Match */
222
	ApatMASK	= 0x07800000,
223
	Apm		= 0x08000000,	/* Accept on Perfect Match */
224
	Aau		= 0x10000000,	/* Accept All Unicast */
225
	Aam		= 0x20000000,	/* Accept All Multicast */
226
	Aab		= 0x40000000,	/* Accept All Broadcast */
227
	Rfen		= 0x80000000,	/* Rx Filter Enable */
228
};
229
 
230
enum {					/* Receive Filter/Match Data */
231
	RfdataSHFT	= 0,		/* Receive Filter Data */
232
	RfdataMASK	= 0x0000FFFF,
233
	BmaskSHFT	= 16,		/* Byte Mask */
234
	BmaskMASK	= 0x00030000,
235
};
236
 
237
enum {					/* MIB Control */
238
	Wrn		= 0x00000001,	/* Warning Test Indicator */
239
	Frz		= 0x00000002,	/* Freeze All Counters */
240
	Aclr		= 0x00000004,	/* Clear All Counters */
241
	Mibs		= 0x00000008,	/* MIB Counter Strobe */
242
};
243
 
244
enum {					/* MIB Data */
245
	Nmibd		= 11,		/* Number of MIB Data Registers */
246
};
247
 
248
enum {					/* VLAN/IP Receive Control */
249
	Vtden		= 0x00000001,	/* VLAN Tag Detection Enable */
250
	Vtren		= 0x00000002,	/* VLAN Tag Removal Enable */
251
	Dvtf		= 0x00000004,	/* Discard VLAN Tagged Frames */
252
	Dutf		= 0x00000008,	/* Discard Untagged Frames */
253
	Ipen		= 0x00000010,	/* IP Checksum Enable */
254
	Ripe		= 0x00000020,	/* Reject IP Checksum Errors */
255
	Rtcpe		= 0x00000040,	/* Reject TCP Checksum Errors */
256
	Rudpe		= 0x00000080,	/* Reject UDP Checksum Errors */
257
};
258
 
259
enum {					/* VLAN/IP Transmit Control */
260
	Vgti		= 0x00000001,	/* VLAN Global Tag Insertion */
261
	Vppti		= 0x00000002,	/* VLAN Per-Packet Tag Insertion */
262
	Gchk		= 0x00000004,	/* Global Checksum Generation */
263
	Ppchk		= 0x00000008,	/* Per-Packet Checksum Generation */
264
};
265
 
266
enum {					/* VLAN Data */
267
	VtypeSHFT	= 0,		/* VLAN Type Field */
268
	VtypeMASK	= 0x0000FFFF,
269
	VtciSHFT	= 16,		/* VLAN Tag Control Information */
270
	VtciMASK	= 0xFFFF0000,
271
};
272
 
273
enum {					/* Clockrun Control/Status */
274
	Clkrunen	= 0x00000001,	/* CLKRUN Enable */
275
	Pmeen		= 0x00000100,	/* PME Enable */
276
	Pmests		= 0x00008000,	/* PME Status */
277
};
278
 
279
typedef struct {
280
	u32int	link;			/* Link to the next descriptor */
281
	u32int	bufptr;			/* pointer to data Buffer */
282
	int	cmdsts;			/* Command/Status */
283
	int	extsts;			/* optional Extended Status */
284
 
285
	Block*	bp;			/* Block containing bufptr */
286
	u32int	unused;			/* pad to 64-bit */
287
} Desc;
288
 
289
enum {					/* Common cmdsts bits */
290
	SizeMASK	= 0x0000FFFF,	/* Descriptor Byte Count */
291
	SizeSHFT	= 0,
292
	Ok		= 0x08000000,	/* Packet OK */
293
	Crc		= 0x10000000,	/* Suppress/Include CRC */
294
	Intr		= 0x20000000,	/* Interrupt on ownership transfer */
295
	More		= 0x40000000,	/* not last descriptor in a packet */
296
	Own		= 0x80000000,	/* Descriptor Ownership */
297
};
298
 
299
enum {					/* Transmit cmdsts bits */
300
	CcntMASK	= 0x000F0000,	/* Collision Count */
301
	CcntSHFT	= 16,
302
	Ec		= 0x00100000,	/* Excessive Collisions */
303
	Owc		= 0x00200000,	/* Out of Window Collision */
304
	Ed		= 0x00400000,	/* Excessive Deferral */
305
	Td		= 0x00800000,	/* Transmit Deferred */
306
	Crs		= 0x01000000,	/* Carrier Sense Lost */
307
	Tfu		= 0x02000000,	/* Transmit FIFO Underrun */
308
	Txa		= 0x04000000,	/* Transmit Abort */
309
};
310
 
311
enum {					/* Receive cmdsts bits */
312
	Irl		= 0x00010000,	/* In-Range Length Error */
313
	Lbp		= 0x00020000,	/* Loopback Packet */
314
	Fae		= 0x00040000,	/* Frame Alignment Error */
315
	Crce		= 0x00080000,	/* CRC Error */
316
	Ise		= 0x00100000,	/* Invalid Symbol Error */
317
	Runt		= 0x00200000,	/* Runt Packet Received */
318
	Long		= 0x00400000,	/* Too Long Packet Received */
319
	DestMASK	= 0x01800000,	/* Destination Class */
320
	DestSHFT	= 23,
321
	Rxo		= 0x02000000,	/* Receive Overrun */
322
	Rxa		= 0x04000000,	/* Receive Aborted */
323
};
324
 
325
enum {					/* extsts bits */
326
	EvtciMASK	= 0x0000FFFF,	/* VLAN Tag Control Information */
327
	EvtciSHFT	= 0,
328
	Vpkt		= 0x00010000,	/* VLAN Packet */
329
	Ippkt		= 0x00020000,	/* IP Packet */
330
	Iperr		= 0x00040000,	/* IP Checksum Error */
331
	Tcppkt		= 0x00080000,	/* TCP Packet */
332
	Tcperr		= 0x00100000,	/* TCP Checksum Error */
333
	Udppkt		= 0x00200000,	/* UDP Packet */
334
	Udperr		= 0x00400000,	/* UDP Checksum Error */
335
};
336
 
337
enum {
338
	Rbsz		= ROUNDUP(sizeof(Etherpkt)+8, 8),
339
	/* were 256, 4*Nrd & 64, but 52, 253 and 9 are ample. */
340
	Nrd		= 128,
341
	Nrb		= 512,
342
	Ntd		= 32,
343
};
344
 
345
typedef struct Ctlr Ctlr;
346
typedef struct Ctlr {
347
	int	port;
348
	Pcidev*	pcidev;
349
	Ctlr*	next;
350
	int	active;
351
	int	id;
352
 
353
	int	eepromsz;		/* address size in bits */
354
	ushort*	eeprom;
355
 
356
	int*	nic;
357
	int	cfg;
358
	int	imr;
359
 
360
	QLock	alock;			/* attach */
361
	Lock	ilock;			/* init */
362
	void*	alloc;			/* base of per-Ctlr allocated data */
363
 
364
	Mii*	mii;
365
 
366
	Lock	rdlock;			/* receive */
367
	Desc*	rd;
368
	int	nrd;
369
	int	nrb;
370
	int	rdx;
371
	int	rxcfg;
372
 
373
	Lock	tlock;			/* transmit */
374
	Desc*	td;
375
	int	ntd;
376
	int	tdh;
377
	int	tdt;
378
	int	ntq;
379
	int	txcfg;
380
 
381
	int	rxidle;
382
 
383
	uint	mibd[Nmibd];
384
 
385
	int	ec;
386
	int	owc;
387
	int	ed;
388
	int	crs;
389
	int	tfu;
390
	int	txa;
391
} Ctlr;
392
 
393
#define csr32r(c, r)	(*((c)->nic+((r)/4)))
394
#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
395
 
396
static Ctlr* dp83820ctlrhead;
397
static Ctlr* dp83820ctlrtail;
398
 
399
static Lock dp83820rblock;		/* free receive Blocks */
400
static Block* dp83820rbpool;
401
 
402
static char* dp83820mibs[Nmibd] = {
403
	"RXErroredPkts",
404
	"RXFCSErrors",
405
	"RXMsdPktErrors",
406
	"RXFAErrors",
407
	"RXSymbolErrors",
408
	"RXFrameToLong",
409
	"RXIRLErrors",
410
	"RXBadOpcodes",
411
	"RXPauseFrames",
412
	"TXPauseFrames",
413
	"TXSQEErrors",
414
};
415
 
416
static int
417
mdior(Ctlr* ctlr, int n)
418
{
419
	int data, i, mear, r;
420
 
421
	mear = csr32r(ctlr, Mear);
422
	r = ~(Mdc|Mddir) & mear;
423
	data = 0;
424
	for(i = n-1; i >= 0; i--){
425
		if(csr32r(ctlr, Mear) & Mdio)
426
			data |= (1<<i);
427
		csr32w(ctlr, Mear, Mdc|r);
428
		csr32w(ctlr, Mear, r);
429
	}
430
	csr32w(ctlr, Mear, mear);
431
 
432
	return data;
433
}
434
 
435
static void
436
mdiow(Ctlr* ctlr, int bits, int n)
437
{
438
	int i, mear, r;
439
 
440
	mear = csr32r(ctlr, Mear);
441
	r = Mddir|(~Mdc & mear);
442
	for(i = n-1; i >= 0; i--){
443
		if(bits & (1<<i))
444
			r |= Mdio;
445
		else
446
			r &= ~Mdio;
447
		csr32w(ctlr, Mear, r);
448
		csr32w(ctlr, Mear, Mdc|r);
449
	}
450
	csr32w(ctlr, Mear, mear);
451
}
452
 
453
static int
454
dp83820miimir(Mii* mii, int pa, int ra)
455
{
456
	int data;
457
	Ctlr *ctlr;
458
 
459
	ctlr = mii->ctlr;
460
 
461
	/*
462
	 * MII Management Interface Read.
463
	 *
464
	 * Preamble;
465
	 * ST+OP+PA+RA;
466
	 * LT + 16 data bits.
467
	 */
468
	mdiow(ctlr, 0xFFFFFFFF, 32);
469
	mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
470
	data = mdior(ctlr, 18);
471
 
472
	if(data & 0x10000)
473
		return -1;
474
 
475
	return data & 0xFFFF;
476
}
477
 
478
static int
479
dp83820miimiw(Mii* mii, int pa, int ra, int data)
480
{
481
	Ctlr *ctlr;
482
 
483
	ctlr = mii->ctlr;
484
 
485
	/*
486
	 * MII Management Interface Write.
487
	 *
488
	 * Preamble;
489
	 * ST+OP+PA+RA+LT + 16 data bits;
490
	 * Z.
491
	 */
492
	mdiow(ctlr, 0xFFFFFFFF, 32);
493
	data &= 0xFFFF;
494
	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
495
	mdiow(ctlr, data, 32);
496
 
497
	return 0;
498
}
499
 
500
static Block *
501
dp83820rballoc(Desc* desc)
502
{
503
	Block *bp;
504
 
505
	if(desc->bp == nil){
506
		ilock(&dp83820rblock);
507
		if((bp = dp83820rbpool) == nil){
508
			iunlock(&dp83820rblock);
509
			desc->bp = nil;
510
			desc->cmdsts = Own;
511
			return nil;
512
		}
513
		dp83820rbpool = bp->next;
514
		bp->next = nil;
515
		_xinc(&bp->ref);	/* prevent bp from being freed */
516
		iunlock(&dp83820rblock);
517
 
518
		desc->bufptr = PCIWADDR(bp->rp);
519
		desc->bp = bp;
520
	}
521
	else{
522
		bp = desc->bp;
523
		bp->rp = bp->lim - Rbsz;
524
		bp->wp = bp->rp;
525
	}
526
 
527
	coherence();
528
	desc->cmdsts = Intr|Rbsz;
529
 
530
	return bp;
531
}
532
 
533
static void
534
dp83820rbfree(Block *bp)
535
{
536
	bp->rp = bp->lim - Rbsz;
537
	bp->wp = bp->rp;
538
 
539
	ilock(&dp83820rblock);
540
	bp->next = dp83820rbpool;
541
	dp83820rbpool = bp;
542
	iunlock(&dp83820rblock);
543
}
544
 
545
static void
546
dp83820halt(Ctlr* ctlr)
547
{
548
	int i, timeo;
549
 
550
	ilock(&ctlr->ilock);
551
	csr32w(ctlr, Imr, 0);
552
	csr32w(ctlr, Ier, 0);
553
	csr32w(ctlr, Cr, Rxd|Txd);
554
	for(timeo = 0; timeo < 1000; timeo++){
555
		if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
556
			break;
557
		microdelay(1);
558
	}
559
	csr32w(ctlr, Mibc, Frz);
560
	iunlock(&ctlr->ilock);
561
 
562
	if(ctlr->rd != nil){
563
		for(i = 0; i < ctlr->nrd; i++){
564
			if(ctlr->rd[i].bp == nil)
565
				continue;
566
			freeb(ctlr->rd[i].bp);
567
			ctlr->rd[i].bp = nil;
568
		}
569
	}
570
	if(ctlr->td != nil){
571
		for(i = 0; i < ctlr->ntd; i++){
572
			if(ctlr->td[i].bp == nil)
573
				continue;
574
			freeb(ctlr->td[i].bp);
575
			ctlr->td[i].bp = nil;
576
		}
577
	}
578
}
579
 
580
static void
581
dp83820cfg(Ctlr* ctlr)
582
{
583
	int cfg;
584
 
585
	/*
586
	 * Don't know how to deal with a TBI yet.
587
	 */
588
	if(ctlr->mii == nil)
589
		return;
590
 
591
	/*
592
	 * The polarity of these bits is at the mercy
593
	 * of the board designer.
594
	 * The correct answer for all speed and duplex questions
595
	 * should be to query the phy.
596
	 */
597
	cfg = csr32r(ctlr, Cfg);
598
	if(!(cfg & Dupsts)){
599
		ctlr->rxcfg |= Rxfd;
600
		ctlr->txcfg |= Csi|Hbi;
601
		iprint("83820: full duplex, ");
602
	}
603
	else{
604
		ctlr->rxcfg &= ~Rxfd;
605
		ctlr->txcfg &= ~(Csi|Hbi);
606
		iprint("83820: half duplex, ");
607
	}
608
	csr32w(ctlr, Rxcfg, ctlr->rxcfg);
609
	csr32w(ctlr, Txcfg, ctlr->txcfg);
610
 
611
	switch(cfg & (Spdsts1000|Spdsts100)){
612
	case Spdsts1000:		/* 100Mbps */
613
	default:			/* 10Mbps */
614
		ctlr->cfg &= ~Mode1000;
615
		if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
616
			iprint("100Mb/s\n");
617
		else
618
			iprint("10Mb/s\n");
619
		break;
620
	case Spdsts100:			/* 1Gbps */
621
		ctlr->cfg |= Mode1000;
622
		iprint("1Gb/s\n");
623
		break;
624
	}
625
	csr32w(ctlr, Cfg, ctlr->cfg);
626
}
627
 
628
static void
629
dp83820init(Ether* edev)
630
{
631
	int i;
632
	Ctlr *ctlr;
633
	Desc *desc;
634
	uchar *alloc;
635
 
636
	ctlr = edev->ctlr;
637
 
638
	dp83820halt(ctlr);
639
 
640
	/*
641
	 * Receiver
642
	 */
643
	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
644
	ctlr->rd = (Desc*)alloc;
645
	alloc += ctlr->nrd*sizeof(Desc);
646
	memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
647
	ctlr->rdx = 0;
648
	for(i = 0; i < ctlr->nrd; i++){
649
		desc = &ctlr->rd[i];
650
		desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
651
		if(dp83820rballoc(desc) == nil)
652
			continue;
653
	}
654
	csr32w(ctlr, Rxdphi, 0);
655
	csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
656
 
657
	for(i = 0; i < Eaddrlen; i += 2){
658
		csr32w(ctlr, Rfcr, i);
659
		csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
660
	}
661
	csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
662
 
663
	ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
664
	ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
665
 
666
	/*
667
	 * Transmitter.
668
	 */
669
	ctlr->td = (Desc*)alloc;
670
	memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
671
	ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
672
	for(i = 0; i < ctlr->ntd; i++){
673
		desc = &ctlr->td[i];
674
		desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
675
	}
676
	csr32w(ctlr, Txdphi, 0);
677
	csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
678
 
679
	ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
680
	ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
681
 
682
	ilock(&ctlr->ilock);
683
 
684
	dp83820cfg(ctlr);
685
 
686
	csr32w(ctlr, Mibc, Aclr);
687
	ctlr->imr |= Mib;
688
 
689
	csr32w(ctlr, Imr, ctlr->imr);
690
 
691
	/* try coalescing adjacent interrupts; use hold-off interval of 100µs */
692
	csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
693
 
694
	csr32w(ctlr, Ier, Ien);
695
	csr32w(ctlr, Cr, Rxe|Txe);
696
 
697
	iunlock(&ctlr->ilock);
698
}
699
 
700
static void
701
dp83820attach(Ether* edev)
702
{
703
	Block *bp;
704
	Ctlr *ctlr;
705
 
706
	ctlr = edev->ctlr;
707
	qlock(&ctlr->alock);
708
	if(ctlr->alloc != nil){
709
		qunlock(&ctlr->alock);
710
		return;
711
	}
712
 
713
	if(waserror()){
714
		if(ctlr->mii != nil){
715
			free(ctlr->mii);
716
			ctlr->mii = nil;
717
		}
718
		if(ctlr->alloc != nil){
719
			free(ctlr->alloc);
720
			ctlr->alloc = nil;
721
		}
722
		qunlock(&ctlr->alock);
723
		nexterror();
724
	}
725
 
726
	if(!(ctlr->cfg & Tbien)){
727
		if((ctlr->mii = malloc(sizeof(Mii))) == nil)
728
			error(Enomem);
729
		ctlr->mii->ctlr = ctlr;
730
		ctlr->mii->mir = dp83820miimir;
731
		ctlr->mii->miw = dp83820miimiw;
732
		if(mii(ctlr->mii, ~0) == 0)
733
			error("no PHY");
734
		ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
735
		ctlr->imr |= Phy;
736
	}
737
 
738
	ctlr->nrd = Nrd;
739
	ctlr->nrb = Nrb;
740
	ctlr->ntd = Ntd;
741
	ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
742
	if(ctlr->alloc == nil)
743
		error(Enomem);
744
 
745
	for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
746
		if((bp = allocb(Rbsz)) == nil)
747
			break;
748
		bp->free = dp83820rbfree;
749
		dp83820rbfree(bp);
750
	}
751
 
752
	dp83820init(edev);
753
 
754
	qunlock(&ctlr->alock);
755
	poperror();
756
}
757
 
758
static void
759
dp83820transmit(Ether* edev)
760
{
761
	Block *bp;
762
	Ctlr *ctlr;
763
	Desc *desc;
764
	int cmdsts, r, x;
765
 
766
	ctlr = edev->ctlr;
767
 
768
	ilock(&ctlr->tlock);
769
 
770
	bp = nil;
771
	for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
772
		desc = &ctlr->td[x];
773
		if((cmdsts = desc->cmdsts) & Own)
774
			break;
775
		if(!(cmdsts & Ok)){
776
			if(cmdsts & Ec)
777
				ctlr->ec++;
778
			if(cmdsts & Owc)
779
				ctlr->owc++;
780
			if(cmdsts & Ed)
781
				ctlr->ed++;
782
			if(cmdsts & Crs)
783
				ctlr->crs++;
784
			if(cmdsts & Tfu)
785
				ctlr->tfu++;
786
			if(cmdsts & Txa)
787
				ctlr->txa++;
788
			edev->oerrs++;
789
		}
790
		desc->bp->next = bp;
791
		bp = desc->bp;
792
		desc->bp = nil;
793
 
794
		ctlr->ntq--;
795
	}
796
	ctlr->tdh = x;
797
	if(bp != nil)
798
		freeblist(bp);
799
 
800
	x = ctlr->tdt;
801
	while(ctlr->ntq < (ctlr->ntd-1)){
802
		if((bp = qget(edev->oq)) == nil)
803
			break;
804
 
805
		desc = &ctlr->td[x];
806
		desc->bufptr = PCIWADDR(bp->rp);
807
		desc->bp = bp;
808
		ctlr->ntq++;
809
		coherence();
810
		desc->cmdsts = Own|Intr|BLEN(bp);
811
 
812
		x = NEXT(x, ctlr->ntd);
813
	}
814
	if(x != ctlr->tdt){
815
		ctlr->tdt = x;
816
		r = csr32r(ctlr, Cr);
817
		csr32w(ctlr, Cr, Txe|r);
818
	}
819
 
820
	iunlock(&ctlr->tlock);
821
}
822
 
823
static void
824
dp83820interrupt(Ureg*, void* arg)
825
{
826
	Block *bp;
827
	Ctlr *ctlr;
828
	Desc *desc;
829
	Ether *edev;
830
	int cmdsts, i, isr, r, x;
831
 
832
	edev = arg;
833
	ctlr = edev->ctlr;
834
 
835
	for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
836
		if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
837
			x = ctlr->rdx;
838
			desc = &ctlr->rd[x];
839
			while((cmdsts = desc->cmdsts) & Own){
840
				if((cmdsts & Ok) && desc->bp != nil){
841
					bp = desc->bp;
842
					desc->bp = nil;
843
					bp->wp += cmdsts & SizeMASK;
844
					etheriq(edev, bp, 1);
845
				}
846
				else if(0 && !(cmdsts & Ok)){
847
					iprint("dp83820: rx %8.8uX:", cmdsts);
848
					bp = desc->bp;
849
					for(i = 0; i < 20; i++)
850
						iprint(" %2.2uX", bp->rp[i]);
851
					iprint("\n");
852
				}
853
				dp83820rballoc(desc);
854
 
855
				x = NEXT(x, ctlr->nrd);
856
				desc = &ctlr->rd[x];
857
			}
858
			ctlr->rdx = x;
859
 
860
			if(isr & Rxidle){
861
				r = csr32r(ctlr, Cr);
862
				csr32w(ctlr, Cr, Rxe|r);
863
				ctlr->rxidle++;
864
			}
865
 
866
			isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
867
		}
868
 
869
		if(isr & Txurn){
870
			x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
871
			r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
872
			if(x < ((TxdrthMASK)>>TxdrthSHFT)
873
			&& x < (2048/32 - r)){
874
				ctlr->txcfg &= ~TxdrthMASK;
875
				x++;
876
				ctlr->txcfg |= x<<TxdrthSHFT;
877
				csr32w(ctlr, Txcfg, ctlr->txcfg);
878
			}
879
		}
880
 
881
		if(isr & (Txurn|Txidle|Txdesc|Txok)){
882
			dp83820transmit(edev);
883
			isr &= ~(Txurn|Txidle|Txdesc|Txok);
884
		}
885
 
886
		if(isr & Mib){
887
			for(i = 0; i < Nmibd; i++){
888
				r = csr32r(ctlr, Mibd+(i*sizeof(int)));
889
				ctlr->mibd[i] += r & 0xFFFF;
890
			}
891
			isr &= ~Mib;
892
		}
893
 
894
		if((isr & Phy) && ctlr->mii != nil){
895
			ctlr->mii->mir(ctlr->mii, 1, Bmsr);
896
			print("phy: cfg %8.8uX bmsr %4.4uX\n",
897
				csr32r(ctlr, Cfg),
898
				ctlr->mii->mir(ctlr->mii, 1, Bmsr));
899
			dp83820cfg(ctlr);
900
			isr &= ~Phy;
901
		}
902
		if(isr)
903
			iprint("dp83820: isr %8.8uX\n", isr);
904
	}
905
}
906
 
907
static long
908
dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
909
{
910
	char *p;
911
	Ctlr *ctlr;
912
	int i, l, r;
913
 
914
	ctlr = edev->ctlr;
915
 
916
	edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
917
	edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
918
	edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
919
	edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
920
 
921
	if(n == 0)
922
		return 0;
923
 
924
	p = malloc(READSTR);
925
	if(p == nil)
926
		error(Enomem);
927
	l = 0;
928
	for(i = 0; i < Nmibd; i++){
929
		r = csr32r(ctlr, Mibd+(i*sizeof(int)));
930
		ctlr->mibd[i] += r & 0xFFFF;
931
		if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
932
			l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
933
				dp83820mibs[i], ctlr->mibd[i], r);
934
	}
935
	l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
936
	l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
937
	l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
938
	l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
939
	l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
940
	l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
941
	l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
942
 
943
	l += snprint(p+l, READSTR, "rom:");
944
	for(i = 0; i < 0x10; i++){
945
		if(i && ((i & 0x07) == 0))
946
			l += snprint(p+l, READSTR-l, "\n    ");
947
		l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
948
	}
949
	l += snprint(p+l, READSTR-l, "\n");
950
 
951
	if(ctlr->mii != nil && ctlr->mii->curphy != nil){
952
		l += snprint(p+l, READSTR, "phy:");
953
		for(i = 0; i < NMiiPhyr; i++){
954
			if(i && ((i & 0x07) == 0))
955
				l += snprint(p+l, READSTR-l, "\n    ");
956
			r = miimir(ctlr->mii, i);
957
			l += snprint(p+l, READSTR-l, " %4.4uX", r);
958
		}
959
		snprint(p+l, READSTR-l, "\n");
960
	}
961
 
962
	n = readstr(offset, a, n, p);
963
	free(p);
964
 
965
	return n;
966
}
967
 
968
static void
969
dp83820promiscuous(void* arg, int on)
970
{
971
	USED(arg, on);
972
}
973
 
974
/* multicast already on, don't need to do anything */
975
static void
976
dp83820multicast(void*, uchar*, int)
977
{
978
}
979
 
980
static int
981
dp83820detach(Ctlr* ctlr)
982
{
983
	/*
984
	 * Soft reset the controller.
985
	 */
986
	csr32w(ctlr, Cr, Rst);
987
	delay(1);
988
	while(csr32r(ctlr, Cr) & Rst)
989
		delay(1);
990
	return 0;
991
}
992
 
993
static void
994
dp83820shutdown(Ether* ether)
995
{
996
print("dp83820shutdown\n");
997
	dp83820detach(ether->ctlr);
998
}
999
 
1000
static int
1001
atc93c46r(Ctlr* ctlr, int address)
1002
{
1003
	int data, i, mear, r, size;
1004
 
1005
	/*
1006
	 * Analog Technology, Inc. ATC93C46
1007
	 * or equivalent serial EEPROM.
1008
	 */
1009
	mear = csr32r(ctlr, Mear);
1010
	mear &= ~(Eesel|Eeclk|Eedo|Eedi);
1011
	r = Eesel|mear;
1012
 
1013
reread:
1014
	csr32w(ctlr, Mear, r);
1015
	data = 0x06;
1016
	for(i = 3-1; i >= 0; i--){
1017
		if(data & (1<<i))
1018
			r |= Eedi;
1019
		else
1020
			r &= ~Eedi;
1021
		csr32w(ctlr, Mear, r);
1022
		csr32w(ctlr, Mear, Eeclk|r);
1023
		microdelay(1);
1024
		csr32w(ctlr, Mear, r);
1025
		microdelay(1);
1026
	}
1027
 
1028
	/*
1029
	 * First time through must work out the EEPROM size.
1030
	 */
1031
	if((size = ctlr->eepromsz) == 0)
1032
		size = 8;
1033
 
1034
	for(size = size-1; size >= 0; size--){
1035
		if(address & (1<<size))
1036
			r |= Eedi;
1037
		else
1038
			r &= ~Eedi;
1039
		csr32w(ctlr, Mear, r);
1040
		microdelay(1);
1041
		csr32w(ctlr, Mear, Eeclk|r);
1042
		microdelay(1);
1043
		csr32w(ctlr, Mear, r);
1044
		microdelay(1);
1045
		if(!(csr32r(ctlr, Mear) & Eedo))
1046
			break;
1047
	}
1048
	r &= ~Eedi;
1049
 
1050
	data = 0;
1051
	for(i = 16-1; i >= 0; i--){
1052
		csr32w(ctlr, Mear, Eeclk|r);
1053
		microdelay(1);
1054
		if(csr32r(ctlr, Mear) & Eedo)
1055
			data |= (1<<i);
1056
		csr32w(ctlr, Mear, r);
1057
		microdelay(1);
1058
	}
1059
 
1060
	csr32w(ctlr, Mear, mear);
1061
 
1062
	if(ctlr->eepromsz == 0){
1063
		ctlr->eepromsz = 8-size;
1064
		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
1065
		if(ctlr->eeprom == nil)
1066
			error(Enomem);
1067
		goto reread;
1068
	}
1069
 
1070
	return data;
1071
}
1072
 
1073
static int
1074
dp83820reset(Ctlr* ctlr)
1075
{
1076
	int i, r;
1077
	unsigned char sum;
1078
 
1079
	/*
1080
	 * Soft reset the controller;
1081
	 * read the EEPROM to get the initial settings
1082
	 * of the Cfg and Gpior bits which should be cleared by
1083
	 * the reset.
1084
	 */
1085
	dp83820detach(ctlr);
1086
 
1087
	atc93c46r(ctlr, 0);
1088
	if(ctlr->eeprom == nil) {
1089
		print("dp83820reset: no eeprom\n");
1090
		return -1;
1091
	}
1092
	sum = 0;
1093
	for(i = 0; i < 0x0E; i++){
1094
		r = atc93c46r(ctlr, i);
1095
		ctlr->eeprom[i] = r;
1096
		sum += r;
1097
		sum += r>>8;
1098
	}
1099
 
1100
	if(sum != 0){
1101
		print("dp83820reset: bad EEPROM checksum\n");
1102
		return -1;
1103
	}
1104
 
1105
#ifdef notdef
1106
	csr32w(ctlr, Gpior, ctlr->eeprom[4]);
1107
 
1108
	cfg = Extstsen|Exd;
1109
	r = csr32r(ctlr, Cfg);
1110
	if(ctlr->eeprom[5] & 0x0001)
1111
		cfg |= Ext125;
1112
	if(ctlr->eeprom[5] & 0x0002)
1113
		cfg |= M64addren;
1114
	if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
1115
		cfg |= Data64en;
1116
	if(ctlr->eeprom[5] & 0x0008)
1117
		cfg |= T64addren;
1118
	if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
1119
		cfg |= Mwidis;
1120
	if(ctlr->eeprom[5] & 0x0020)
1121
		cfg |= Mrmdis;
1122
	if(ctlr->eeprom[5] & 0x0080)
1123
		cfg |= Mode1000;
1124
	if(ctlr->eeprom[5] & 0x0200)
1125
		cfg |= Tbien|Mode1000;
1126
	/*
1127
	 * What about RO bits we might have destroyed with Rst?
1128
	 * What about Exd, Tmrtest, Extstsen, Pintctl?
1129
	 * Why does it think it has detected a 64-bit bus when
1130
	 * it hasn't?
1131
	 */
1132
#else
1133
	// r = csr32r(ctlr, Cfg);
1134
	// r &= ~(Mode1000|T64addren|Data64en|M64addren);
1135
	// csr32w(ctlr, Cfg, r);
1136
	// csr32w(ctlr, Cfg, 0x2000);
1137
#endif						/* notdef */
1138
	ctlr->cfg = csr32r(ctlr, Cfg);
1139
print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
1140
	ctlr->cfg &= ~(T64addren|Data64en|M64addren);
1141
	csr32w(ctlr, Cfg, ctlr->cfg);
1142
	csr32w(ctlr, Mibc, Aclr|Frz);
1143
 
1144
	return 0;
1145
}
1146
 
1147
static void
1148
dp83820pci(void)
1149
{
1150
	void *mem;
1151
	Pcidev *p;
1152
	Ctlr *ctlr;
1153
 
1154
	p = nil;
1155
	while(p = pcimatch(p, 0, 0)){
1156
		if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
1157
			continue;
1158
 
1159
		switch((p->did<<16)|p->vid){
1160
		default:
1161
			continue;
1162
		case (0x0022<<16)|0x100B:	/* DP83820 (Gig-NIC) */
1163
			break;
1164
		}
1165
 
1166
		mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
1167
		if(mem == 0){
1168
			print("DP83820: can't map %8.8luX\n", p->mem[1].bar);
1169
			continue;
1170
		}
1171
 
1172
		ctlr = malloc(sizeof(Ctlr));
1173
		if(ctlr == nil) {
1174
			vunmap(mem, p->mem[1].size);
1175
			error(Enomem);
1176
		}
1177
		ctlr->port = p->mem[1].bar & ~0x0F;
1178
		ctlr->pcidev = p;
1179
		ctlr->id = (p->did<<16)|p->vid;
1180
 
1181
		ctlr->nic = mem;
1182
		if(dp83820reset(ctlr)){
1183
			free(ctlr);
1184
			vunmap(mem, p->mem[1].size);
1185
			continue;
1186
		}
1187
		pcisetbme(p);
1188
 
1189
		if(dp83820ctlrhead != nil)
1190
			dp83820ctlrtail->next = ctlr;
1191
		else
1192
			dp83820ctlrhead = ctlr;
1193
		dp83820ctlrtail = ctlr;
1194
	}
1195
}
1196
 
1197
static int
1198
dp83820pnp(Ether* edev)
1199
{
1200
	int i;
1201
	Ctlr *ctlr;
1202
	uchar ea[Eaddrlen];
1203
 
1204
	if(dp83820ctlrhead == nil)
1205
		dp83820pci();
1206
 
1207
	/*
1208
	 * Any adapter matches if no edev->port is supplied,
1209
	 * otherwise the ports must match.
1210
	 */
1211
	for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
1212
		if(ctlr->active)
1213
			continue;
1214
		if(edev->port == 0 || edev->port == ctlr->port){
1215
			ctlr->active = 1;
1216
			break;
1217
		}
1218
	}
1219
	if(ctlr == nil)
1220
		return -1;
1221
 
1222
	edev->ctlr = ctlr;
1223
	edev->port = ctlr->port;
1224
	edev->irq = ctlr->pcidev->intl;
1225
	edev->tbdf = ctlr->pcidev->tbdf;
1226
	edev->mbps = 1000;
1227
 
1228
	/*
1229
	 * Check if the adapter's station address is to be overridden.
1230
	 * If not, read it from the EEPROM and set in ether->ea prior to
1231
	 * loading the station address in the hardware.
1232
	 */
1233
	memset(ea, 0, Eaddrlen);
1234
	if(memcmp(ea, edev->ea, Eaddrlen) == 0)
1235
		for(i = 0; i < Eaddrlen/2; i++){
1236
			edev->ea[2*i] = ctlr->eeprom[0x0C-i];
1237
			edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
1238
		}
1239
 
1240
	edev->attach = dp83820attach;
1241
	edev->transmit = dp83820transmit;
1242
	edev->interrupt = dp83820interrupt;
1243
	edev->ifstat = dp83820ifstat;
1244
 
1245
	edev->arg = edev;
1246
	edev->promiscuous = dp83820promiscuous;
1247
	edev->multicast = dp83820multicast;
1248
	edev->shutdown = dp83820shutdown;
1249
 
1250
	return 0;
1251
}
1252
 
1253
void
1254
etherdp83820link(void)
1255
{
1256
	addethercard("DP83820", dp83820pnp);
1257
}