xref: /plan9-contrib/sys/src/9/pc/etherdp83820.c (revision b94bb474148e9d24a82a427863d9c9eb4c20f4ae)
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 	Nrd		= 256,
339 	Nrb		= 4*Nrd,
340 	Rbsz		= ROUNDUP(sizeof(Etherpkt)+8, 8),
341 	Ntd		= 64,
342 };
343 
344 typedef struct Ctlr Ctlr;
345 typedef struct Ctlr {
346 	int	port;
347 	Pcidev*	pcidev;
348 	Ctlr*	next;
349 	int	active;
350 	int	id;
351 
352 	int	eepromsz;		/* address size in bits */
353 	ushort*	eeprom;
354 
355 	int*	nic;
356 	int	cfg;
357 	int	imr;
358 
359 	QLock	alock;			/* attach */
360 	Lock	ilock;			/* init */
361 	void*	alloc;			/* base of per-Ctlr allocated data */
362 
363 	Mii*	mii;
364 
365 	Lock	rdlock;			/* receive */
366 	Desc*	rd;
367 	int	nrd;
368 	int	nrb;
369 	int	rdx;
370 	int	rxcfg;
371 
372 	Lock	tlock;			/* transmit */
373 	Desc*	td;
374 	int	ntd;
375 	int	tdh;
376 	int	tdt;
377 	int	ntq;
378 	int	txcfg;
379 
380 	int	rxidle;
381 
382 	uint	mibd[Nmibd];
383 
384 	int	ec;
385 	int	owc;
386 	int	ed;
387 	int	crs;
388 	int	tfu;
389 	int	txa;
390 } Ctlr;
391 
392 #define csr32r(c, r)	(*((c)->nic+((r)/4)))
393 #define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))
394 
395 static Ctlr* dp83820ctlrhead;
396 static Ctlr* dp83820ctlrtail;
397 
398 static Lock dp83820rblock;		/* free receive Blocks */
399 static Block* dp83820rbpool;
400 
401 static char* dp83820mibs[Nmibd] = {
402 	"RXErroredPkts",
403 	"RXFCSErrors",
404 	"RXMsdPktErrors",
405 	"RXFAErrors",
406 	"RXSymbolErrors",
407 	"RXFrameToLong",
408 	"RXIRLErrors",
409 	"RXBadOpcodes",
410 	"RXPauseFrames",
411 	"TXPauseFrames",
412 	"TXSQEErrors",
413 };
414 
415 static int
416 mdior(Ctlr* ctlr, int n)
417 {
418 	int data, i, mear, r;
419 
420 	mear = csr32r(ctlr, Mear);
421 	r = ~(Mdc|Mddir) & mear;
422 	data = 0;
423 	for(i = n-1; i >= 0; i--){
424 		if(csr32r(ctlr, Mear) & Mdio)
425 			data |= (1<<i);
426 		csr32w(ctlr, Mear, Mdc|r);
427 		csr32w(ctlr, Mear, r);
428 	}
429 	csr32w(ctlr, Mear, mear);
430 
431 	return data;
432 }
433 
434 static void
435 mdiow(Ctlr* ctlr, int bits, int n)
436 {
437 	int i, mear, r;
438 
439 	mear = csr32r(ctlr, Mear);
440 	r = Mddir|(~Mdc & mear);
441 	for(i = n-1; i >= 0; i--){
442 		if(bits & (1<<i))
443 			r |= Mdio;
444 		else
445 			r &= ~Mdio;
446 		csr32w(ctlr, Mear, r);
447 		csr32w(ctlr, Mear, Mdc|r);
448 	}
449 	csr32w(ctlr, Mear, mear);
450 }
451 
452 static int
453 dp83820miimir(Mii* mii, int pa, int ra)
454 {
455 	int data;
456 	Ctlr *ctlr;
457 
458 	ctlr = mii->ctlr;
459 
460 	/*
461 	 * MII Management Interface Read.
462 	 *
463 	 * Preamble;
464 	 * ST+OP+PA+RA;
465 	 * LT + 16 data bits.
466 	 */
467 	mdiow(ctlr, 0xFFFFFFFF, 32);
468 	mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
469 	data = mdior(ctlr, 18);
470 
471 	if(data & 0x10000)
472 		return -1;
473 
474 	return data & 0xFFFF;
475 }
476 
477 static int
478 dp83820miimiw(Mii* mii, int pa, int ra, int data)
479 {
480 	Ctlr *ctlr;
481 
482 	ctlr = mii->ctlr;
483 
484 	/*
485 	 * MII Management Interface Write.
486 	 *
487 	 * Preamble;
488 	 * ST+OP+PA+RA+LT + 16 data bits;
489 	 * Z.
490 	 */
491 	mdiow(ctlr, 0xFFFFFFFF, 32);
492 	data &= 0xFFFF;
493 	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
494 	mdiow(ctlr, data, 32);
495 
496 	return 0;
497 }
498 
499 static Block *
500 dp83820rballoc(Desc* desc)
501 {
502 	Block *bp;
503 
504 	if(desc->bp == nil){
505 		ilock(&dp83820rblock);
506 		if((bp = dp83820rbpool) == nil){
507 			iunlock(&dp83820rblock);
508 			desc->bp = nil;
509 			desc->cmdsts = Own;
510 			return nil;
511 		}
512 		dp83820rbpool = bp->next;
513 		bp->next = nil;
514 		_xinc(&bp->ref);	/* prevent bp from being freed */
515 		iunlock(&dp83820rblock);
516 
517 		desc->bufptr = PCIWADDR(bp->rp);
518 		desc->bp = bp;
519 	}
520 	else{
521 		bp = desc->bp;
522 		bp->rp = bp->lim - Rbsz;
523 		bp->wp = bp->rp;
524 	}
525 
526 	coherence();
527 	desc->cmdsts = Intr|Rbsz;
528 
529 	return bp;
530 }
531 
532 static void
533 dp83820rbfree(Block *bp)
534 {
535 	bp->rp = bp->lim - Rbsz;
536 	bp->wp = bp->rp;
537 
538 	ilock(&dp83820rblock);
539 	bp->next = dp83820rbpool;
540 	dp83820rbpool = bp;
541 	iunlock(&dp83820rblock);
542 }
543 
544 static void
545 dp83820halt(Ctlr* ctlr)
546 {
547 	int i, timeo;
548 
549 	ilock(&ctlr->ilock);
550 	csr32w(ctlr, Imr, 0);
551 	csr32w(ctlr, Ier, 0);
552 	csr32w(ctlr, Cr, Rxd|Txd);
553 	for(timeo = 0; timeo < 1000; timeo++){
554 		if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
555 			break;
556 		microdelay(1);
557 	}
558 	csr32w(ctlr, Mibc, Frz);
559 	iunlock(&ctlr->ilock);
560 
561 	if(ctlr->rd != nil){
562 		for(i = 0; i < ctlr->nrd; i++){
563 			if(ctlr->rd[i].bp == nil)
564 				continue;
565 			freeb(ctlr->rd[i].bp);
566 			ctlr->rd[i].bp = nil;
567 		}
568 	}
569 	if(ctlr->td != nil){
570 		for(i = 0; i < ctlr->ntd; i++){
571 			if(ctlr->td[i].bp == nil)
572 				continue;
573 			freeb(ctlr->td[i].bp);
574 			ctlr->td[i].bp = nil;
575 		}
576 	}
577 }
578 
579 static void
580 dp83820cfg(Ctlr* ctlr)
581 {
582 	int cfg;
583 
584 	/*
585 	 * Don't know how to deal with a TBI yet.
586 	 */
587 	if(ctlr->mii == nil)
588 		return;
589 
590 	/*
591 	 * The polarity of these bits is at the mercy
592 	 * of the board designer.
593 	 * The correct answer for all speed and duplex questions
594 	 * should be to query the phy.
595 	 */
596 	cfg = csr32r(ctlr, Cfg);
597 	if(!(cfg & Dupsts)){
598 		ctlr->rxcfg |= Rxfd;
599 		ctlr->txcfg |= Csi|Hbi;
600 		iprint("83820: full duplex, ");
601 	}
602 	else{
603 		ctlr->rxcfg &= ~Rxfd;
604 		ctlr->txcfg &= ~(Csi|Hbi);
605 		iprint("83820: half duplex, ");
606 	}
607 	csr32w(ctlr, Rxcfg, ctlr->rxcfg);
608 	csr32w(ctlr, Txcfg, ctlr->txcfg);
609 
610 	switch(cfg & (Spdsts1000|Spdsts100)){
611 	case Spdsts1000:		/* 100Mbps */
612 	default:			/* 10Mbps */
613 		ctlr->cfg &= ~Mode1000;
614 		if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
615 			iprint("100Mb/s\n");
616 		else
617 			iprint("10Mb/s\n");
618 		break;
619 	case Spdsts100:			/* 1Gbps */
620 		ctlr->cfg |= Mode1000;
621 		iprint("1Gb/s\n");
622 		break;
623 	}
624 	csr32w(ctlr, Cfg, ctlr->cfg);
625 }
626 
627 static void
628 dp83820init(Ether* edev)
629 {
630 	int i;
631 	Ctlr *ctlr;
632 	Desc *desc;
633 	uchar *alloc;
634 
635 	ctlr = edev->ctlr;
636 
637 	dp83820halt(ctlr);
638 
639 	/*
640 	 * Receiver
641 	 */
642 	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
643 	ctlr->rd = (Desc*)alloc;
644 	alloc += ctlr->nrd*sizeof(Desc);
645 	memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
646 	ctlr->rdx = 0;
647 	for(i = 0; i < ctlr->nrd; i++){
648 		desc = &ctlr->rd[i];
649 		desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
650 		if(dp83820rballoc(desc) == nil)
651 			continue;
652 	}
653 	csr32w(ctlr, Rxdphi, 0);
654 	csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
655 
656 	for(i = 0; i < Eaddrlen; i += 2){
657 		csr32w(ctlr, Rfcr, i);
658 		csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
659 	}
660 	csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
661 
662 	ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
663 	ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
664 
665 	/*
666 	 * Transmitter.
667 	 */
668 	ctlr->td = (Desc*)alloc;
669 	memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
670 	ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
671 	for(i = 0; i < ctlr->ntd; i++){
672 		desc = &ctlr->td[i];
673 		desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
674 	}
675 	csr32w(ctlr, Txdphi, 0);
676 	csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
677 
678 	ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
679 	ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
680 
681 	ilock(&ctlr->ilock);
682 
683 	dp83820cfg(ctlr);
684 
685 	csr32w(ctlr, Mibc, Aclr);
686 	ctlr->imr |= Mib;
687 
688 	csr32w(ctlr, Imr, ctlr->imr);
689 
690 	/* try coalescing adjacent interrupts; use hold-off interval of 100µs */
691 	csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
692 
693 	csr32w(ctlr, Ier, Ien);
694 	csr32w(ctlr, Cr, Rxe|Txe);
695 
696 	iunlock(&ctlr->ilock);
697 }
698 
699 static void
700 dp83820attach(Ether* edev)
701 {
702 	Block *bp;
703 	Ctlr *ctlr;
704 
705 	ctlr = edev->ctlr;
706 	qlock(&ctlr->alock);
707 	if(ctlr->alloc != nil){
708 		qunlock(&ctlr->alock);
709 		return;
710 	}
711 
712 	if(waserror()){
713 		if(ctlr->mii != nil){
714 			free(ctlr->mii);
715 			ctlr->mii = nil;
716 		}
717 		if(ctlr->alloc != nil){
718 			free(ctlr->alloc);
719 			ctlr->alloc = nil;
720 		}
721 		qunlock(&ctlr->alock);
722 		nexterror();
723 	}
724 
725 	if(!(ctlr->cfg & Tbien)){
726 		if((ctlr->mii = malloc(sizeof(Mii))) == nil)
727 			error(Enomem);
728 		ctlr->mii->ctlr = ctlr;
729 		ctlr->mii->mir = dp83820miimir;
730 		ctlr->mii->miw = dp83820miimiw;
731 		if(mii(ctlr->mii, ~0) == 0)
732 			error("no PHY");
733 		ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
734 		ctlr->imr |= Phy;
735 	}
736 
737 	ctlr->nrd = Nrd;
738 	ctlr->nrb = Nrb;
739 	ctlr->ntd = Ntd;
740 	ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
741 	if(ctlr->alloc == nil)
742 		error(Enomem);
743 
744 	for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
745 		if((bp = allocb(Rbsz)) == nil)
746 			break;
747 		bp->free = dp83820rbfree;
748 		dp83820rbfree(bp);
749 	}
750 
751 	dp83820init(edev);
752 
753 	qunlock(&ctlr->alock);
754 	poperror();
755 }
756 
757 static void
758 dp83820transmit(Ether* edev)
759 {
760 	Block *bp;
761 	Ctlr *ctlr;
762 	Desc *desc;
763 	int cmdsts, r, x;
764 
765 	ctlr = edev->ctlr;
766 
767 	ilock(&ctlr->tlock);
768 
769 	bp = nil;
770 	for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
771 		desc = &ctlr->td[x];
772 		if((cmdsts = desc->cmdsts) & Own)
773 			break;
774 		if(!(cmdsts & Ok)){
775 			if(cmdsts & Ec)
776 				ctlr->ec++;
777 			if(cmdsts & Owc)
778 				ctlr->owc++;
779 			if(cmdsts & Ed)
780 				ctlr->ed++;
781 			if(cmdsts & Crs)
782 				ctlr->crs++;
783 			if(cmdsts & Tfu)
784 				ctlr->tfu++;
785 			if(cmdsts & Txa)
786 				ctlr->txa++;
787 			edev->oerrs++;
788 		}
789 		desc->bp->next = bp;
790 		bp = desc->bp;
791 		desc->bp = nil;
792 
793 		ctlr->ntq--;
794 	}
795 	ctlr->tdh = x;
796 	if(bp != nil)
797 		freeblist(bp);
798 
799 	x = ctlr->tdt;
800 	while(ctlr->ntq < (ctlr->ntd-1)){
801 		if((bp = qget(edev->oq)) == nil)
802 			break;
803 
804 		desc = &ctlr->td[x];
805 		desc->bufptr = PCIWADDR(bp->rp);
806 		desc->bp = bp;
807 		ctlr->ntq++;
808 		coherence();
809 		desc->cmdsts = Own|Intr|BLEN(bp);
810 
811 		x = NEXT(x, ctlr->ntd);
812 	}
813 	if(x != ctlr->tdt){
814 		ctlr->tdt = x;
815 		r = csr32r(ctlr, Cr);
816 		csr32w(ctlr, Cr, Txe|r);
817 	}
818 
819 	iunlock(&ctlr->tlock);
820 }
821 
822 static void
823 dp83820interrupt(Ureg*, void* arg)
824 {
825 	Block *bp;
826 	Ctlr *ctlr;
827 	Desc *desc;
828 	Ether *edev;
829 	int cmdsts, i, isr, r, x;
830 
831 	edev = arg;
832 	ctlr = edev->ctlr;
833 
834 	for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
835 		if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
836 			x = ctlr->rdx;
837 			desc = &ctlr->rd[x];
838 			while((cmdsts = desc->cmdsts) & Own){
839 				if((cmdsts & Ok) && desc->bp != nil){
840 					bp = desc->bp;
841 					desc->bp = nil;
842 					bp->wp += cmdsts & SizeMASK;
843 					etheriq(edev, bp, 1);
844 				}
845 				else if(0 && !(cmdsts & Ok)){
846 					iprint("dp83820: rx %8.8uX:", cmdsts);
847 					bp = desc->bp;
848 					for(i = 0; i < 20; i++)
849 						iprint(" %2.2uX", bp->rp[i]);
850 					iprint("\n");
851 				}
852 				dp83820rballoc(desc);
853 
854 				x = NEXT(x, ctlr->nrd);
855 				desc = &ctlr->rd[x];
856 			}
857 			ctlr->rdx = x;
858 
859 			if(isr & Rxidle){
860 				r = csr32r(ctlr, Cr);
861 				csr32w(ctlr, Cr, Rxe|r);
862 				ctlr->rxidle++;
863 			}
864 
865 			isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
866 		}
867 
868 		if(isr & Txurn){
869 			x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
870 			r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
871 			if(x < ((TxdrthMASK)>>TxdrthSHFT)
872 			&& x < (2048/32 - r)){
873 				ctlr->txcfg &= ~TxdrthMASK;
874 				x++;
875 				ctlr->txcfg |= x<<TxdrthSHFT;
876 				csr32w(ctlr, Txcfg, ctlr->txcfg);
877 			}
878 		}
879 
880 		if(isr & (Txurn|Txidle|Txdesc|Txok)){
881 			dp83820transmit(edev);
882 			isr &= ~(Txurn|Txidle|Txdesc|Txok);
883 		}
884 
885 		if(isr & Mib){
886 			for(i = 0; i < Nmibd; i++){
887 				r = csr32r(ctlr, Mibd+(i*sizeof(int)));
888 				ctlr->mibd[i] += r & 0xFFFF;
889 			}
890 			isr &= ~Mib;
891 		}
892 
893 		if((isr & Phy) && ctlr->mii != nil){
894 			ctlr->mii->mir(ctlr->mii, 1, Bmsr);
895 			print("phy: cfg %8.8uX bmsr %4.4uX\n",
896 				csr32r(ctlr, Cfg),
897 				ctlr->mii->mir(ctlr->mii, 1, Bmsr));
898 			dp83820cfg(ctlr);
899 			isr &= ~Phy;
900 		}
901 		if(isr)
902 			iprint("dp83820: isr %8.8uX\n", isr);
903 	}
904 }
905 
906 static long
907 dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
908 {
909 	char *p;
910 	Ctlr *ctlr;
911 	int i, l, r;
912 
913 	ctlr = edev->ctlr;
914 
915 	edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
916 	edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
917 	edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
918 	edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
919 
920 	if(n == 0)
921 		return 0;
922 
923 	p = malloc(READSTR);
924 	if(p == nil)
925 		error(Enomem);
926 	l = 0;
927 	for(i = 0; i < Nmibd; i++){
928 		r = csr32r(ctlr, Mibd+(i*sizeof(int)));
929 		ctlr->mibd[i] += r & 0xFFFF;
930 		if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
931 			l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
932 				dp83820mibs[i], ctlr->mibd[i], r);
933 	}
934 	l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
935 	l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
936 	l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
937 	l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
938 	l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
939 	l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
940 	l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
941 
942 	l += snprint(p+l, READSTR, "rom:");
943 	for(i = 0; i < 0x10; i++){
944 		if(i && ((i & 0x07) == 0))
945 			l += snprint(p+l, READSTR-l, "\n    ");
946 		l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
947 	}
948 	l += snprint(p+l, READSTR-l, "\n");
949 
950 	if(ctlr->mii != nil && ctlr->mii->curphy != nil){
951 		l += snprint(p+l, READSTR, "phy:");
952 		for(i = 0; i < NMiiPhyr; i++){
953 			if(i && ((i & 0x07) == 0))
954 				l += snprint(p+l, READSTR-l, "\n    ");
955 			r = miimir(ctlr->mii, i);
956 			l += snprint(p+l, READSTR-l, " %4.4uX", r);
957 		}
958 		snprint(p+l, READSTR-l, "\n");
959 	}
960 
961 	n = readstr(offset, a, n, p);
962 	free(p);
963 
964 	return n;
965 }
966 
967 static void
968 dp83820promiscuous(void* arg, int on)
969 {
970 	USED(arg, on);
971 }
972 
973 /* multicast already on, don't need to do anything */
974 static void
975 dp83820multicast(void*, uchar*, int)
976 {
977 }
978 
979 static int
980 dp83820detach(Ctlr* ctlr)
981 {
982 	/*
983 	 * Soft reset the controller.
984 	 */
985 	csr32w(ctlr, Cr, Rst);
986 	delay(1);
987 	while(csr32r(ctlr, Cr) & Rst)
988 		delay(1);
989 	return 0;
990 }
991 
992 static void
993 dp83820shutdown(Ether* ether)
994 {
995 print("dp83820shutdown\n");
996 	dp83820detach(ether->ctlr);
997 }
998 
999 static int
1000 atc93c46r(Ctlr* ctlr, int address)
1001 {
1002 	int data, i, mear, r, size;
1003 
1004 	/*
1005 	 * Analog Technology, Inc. ATC93C46
1006 	 * or equivalent serial EEPROM.
1007 	 */
1008 	mear = csr32r(ctlr, Mear);
1009 	mear &= ~(Eesel|Eeclk|Eedo|Eedi);
1010 	r = Eesel|mear;
1011 
1012 reread:
1013 	csr32w(ctlr, Mear, r);
1014 	data = 0x06;
1015 	for(i = 3-1; i >= 0; i--){
1016 		if(data & (1<<i))
1017 			r |= Eedi;
1018 		else
1019 			r &= ~Eedi;
1020 		csr32w(ctlr, Mear, r);
1021 		csr32w(ctlr, Mear, Eeclk|r);
1022 		microdelay(1);
1023 		csr32w(ctlr, Mear, r);
1024 		microdelay(1);
1025 	}
1026 
1027 	/*
1028 	 * First time through must work out the EEPROM size.
1029 	 */
1030 	if((size = ctlr->eepromsz) == 0)
1031 		size = 8;
1032 
1033 	for(size = size-1; size >= 0; size--){
1034 		if(address & (1<<size))
1035 			r |= Eedi;
1036 		else
1037 			r &= ~Eedi;
1038 		csr32w(ctlr, Mear, r);
1039 		microdelay(1);
1040 		csr32w(ctlr, Mear, Eeclk|r);
1041 		microdelay(1);
1042 		csr32w(ctlr, Mear, r);
1043 		microdelay(1);
1044 		if(!(csr32r(ctlr, Mear) & Eedo))
1045 			break;
1046 	}
1047 	r &= ~Eedi;
1048 
1049 	data = 0;
1050 	for(i = 16-1; i >= 0; i--){
1051 		csr32w(ctlr, Mear, Eeclk|r);
1052 		microdelay(1);
1053 		if(csr32r(ctlr, Mear) & Eedo)
1054 			data |= (1<<i);
1055 		csr32w(ctlr, Mear, r);
1056 		microdelay(1);
1057 	}
1058 
1059 	csr32w(ctlr, Mear, mear);
1060 
1061 	if(ctlr->eepromsz == 0){
1062 		ctlr->eepromsz = 8-size;
1063 		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
1064 		if(ctlr->eeprom == nil)
1065 			error(Enomem);
1066 		goto reread;
1067 	}
1068 
1069 	return data;
1070 }
1071 
1072 static int
1073 dp83820reset(Ctlr* ctlr)
1074 {
1075 	int i, r;
1076 	unsigned char sum;
1077 
1078 	/*
1079 	 * Soft reset the controller;
1080 	 * read the EEPROM to get the initial settings
1081 	 * of the Cfg and Gpior bits which should be cleared by
1082 	 * the reset.
1083 	 */
1084 	dp83820detach(ctlr);
1085 
1086 	atc93c46r(ctlr, 0);
1087 	if(ctlr->eeprom == nil) {
1088 		print("dp83820reset: no eeprom\n");
1089 		return -1;
1090 	}
1091 	sum = 0;
1092 	for(i = 0; i < 0x0E; i++){
1093 		r = atc93c46r(ctlr, i);
1094 		ctlr->eeprom[i] = r;
1095 		sum += r;
1096 		sum += r>>8;
1097 	}
1098 
1099 	if(sum != 0){
1100 		print("dp83820reset: bad EEPROM checksum\n");
1101 		return -1;
1102 	}
1103 
1104 #ifdef notdef
1105 	csr32w(ctlr, Gpior, ctlr->eeprom[4]);
1106 
1107 	cfg = Extstsen|Exd;
1108 	r = csr32r(ctlr, Cfg);
1109 	if(ctlr->eeprom[5] & 0x0001)
1110 		cfg |= Ext125;
1111 	if(ctlr->eeprom[5] & 0x0002)
1112 		cfg |= M64addren;
1113 	if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
1114 		cfg |= Data64en;
1115 	if(ctlr->eeprom[5] & 0x0008)
1116 		cfg |= T64addren;
1117 	if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
1118 		cfg |= Mwidis;
1119 	if(ctlr->eeprom[5] & 0x0020)
1120 		cfg |= Mrmdis;
1121 	if(ctlr->eeprom[5] & 0x0080)
1122 		cfg |= Mode1000;
1123 	if(ctlr->eeprom[5] & 0x0200)
1124 		cfg |= Tbien|Mode1000;
1125 	/*
1126 	 * What about RO bits we might have destroyed with Rst?
1127 	 * What about Exd, Tmrtest, Extstsen, Pintctl?
1128 	 * Why does it think it has detected a 64-bit bus when
1129 	 * it hasn't?
1130 	 */
1131 #else
1132 	// r = csr32r(ctlr, Cfg);
1133 	// r &= ~(Mode1000|T64addren|Data64en|M64addren);
1134 	// csr32w(ctlr, Cfg, r);
1135 	// csr32w(ctlr, Cfg, 0x2000);
1136 #endif						/* notdef */
1137 	ctlr->cfg = csr32r(ctlr, Cfg);
1138 print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
1139 	ctlr->cfg &= ~(T64addren|Data64en|M64addren);
1140 	csr32w(ctlr, Cfg, ctlr->cfg);
1141 	csr32w(ctlr, Mibc, Aclr|Frz);
1142 
1143 	return 0;
1144 }
1145 
1146 static void
1147 dp83820pci(void)
1148 {
1149 	void *mem;
1150 	Pcidev *p;
1151 	Ctlr *ctlr;
1152 
1153 	p = nil;
1154 	while(p = pcimatch(p, 0, 0)){
1155 		if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
1156 			continue;
1157 
1158 		switch((p->did<<16)|p->vid){
1159 		default:
1160 			continue;
1161 		case (0x0022<<16)|0x100B:	/* DP83820 (Gig-NIC) */
1162 			break;
1163 		}
1164 
1165 		mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
1166 		if(mem == 0){
1167 			print("DP83820: can't map %8.8luX\n", p->mem[1].bar);
1168 			continue;
1169 		}
1170 
1171 		ctlr = malloc(sizeof(Ctlr));
1172 		if(ctlr == nil) {
1173 			vunmap(mem, p->mem[1].size);
1174 			error(Enomem);
1175 		}
1176 		ctlr->port = p->mem[1].bar & ~0x0F;
1177 		ctlr->pcidev = p;
1178 		ctlr->id = (p->did<<16)|p->vid;
1179 
1180 		ctlr->nic = mem;
1181 		if(dp83820reset(ctlr)){
1182 			free(ctlr);
1183 			vunmap(mem, p->mem[1].size);
1184 			continue;
1185 		}
1186 		pcisetbme(p);
1187 
1188 		if(dp83820ctlrhead != nil)
1189 			dp83820ctlrtail->next = ctlr;
1190 		else
1191 			dp83820ctlrhead = ctlr;
1192 		dp83820ctlrtail = ctlr;
1193 	}
1194 }
1195 
1196 static int
1197 dp83820pnp(Ether* edev)
1198 {
1199 	int i;
1200 	Ctlr *ctlr;
1201 	uchar ea[Eaddrlen];
1202 
1203 	if(dp83820ctlrhead == nil)
1204 		dp83820pci();
1205 
1206 	/*
1207 	 * Any adapter matches if no edev->port is supplied,
1208 	 * otherwise the ports must match.
1209 	 */
1210 	for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
1211 		if(ctlr->active)
1212 			continue;
1213 		if(edev->port == 0 || edev->port == ctlr->port){
1214 			ctlr->active = 1;
1215 			break;
1216 		}
1217 	}
1218 	if(ctlr == nil)
1219 		return -1;
1220 
1221 	edev->ctlr = ctlr;
1222 	edev->port = ctlr->port;
1223 	edev->irq = ctlr->pcidev->intl;
1224 	edev->tbdf = ctlr->pcidev->tbdf;
1225 	edev->mbps = 1000;
1226 
1227 	/*
1228 	 * Check if the adapter's station address is to be overridden.
1229 	 * If not, read it from the EEPROM and set in ether->ea prior to
1230 	 * loading the station address in the hardware.
1231 	 */
1232 	memset(ea, 0, Eaddrlen);
1233 	if(memcmp(ea, edev->ea, Eaddrlen) == 0)
1234 		for(i = 0; i < Eaddrlen/2; i++){
1235 			edev->ea[2*i] = ctlr->eeprom[0x0C-i];
1236 			edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
1237 		}
1238 
1239 	edev->attach = dp83820attach;
1240 	edev->transmit = dp83820transmit;
1241 	edev->interrupt = dp83820interrupt;
1242 	edev->ifstat = dp83820ifstat;
1243 
1244 	edev->arg = edev;
1245 	edev->promiscuous = dp83820promiscuous;
1246 	edev->multicast = dp83820multicast;
1247 	edev->shutdown = dp83820shutdown;
1248 
1249 	return 0;
1250 }
1251 
1252 void
1253 etherdp83820link(void)
1254 {
1255 	addethercard("DP83820", dp83820pnp);
1256 }
1257