xref: /plan9/sys/src/9/pc/etherelnk3.c (revision aa72973a2891ccbd3fb042462446761159389e19)
1 /*
2  * Etherlink III, Fast EtherLink and Fast EtherLink XL adapters.
3  * To do:
4  *	check robustness in the face of errors (e.g. busmaster & rxUnderrun);
5  *	RxEarly and busmaster;
6  *	autoSelect;
7  *	PCI latency timer and master enable;
8  *	errata list;
9  *	rewrite all initialisation.
10  */
11 #include "u.h"
12 #include "../port/lib.h"
13 #include "mem.h"
14 #include "dat.h"
15 #include "fns.h"
16 #include "io.h"
17 #include "../port/error.h"
18 #include "../port/netif.h"
19 
20 #include "etherif.h"
21 
22 #define XCVRDEBUG		if(0)print
23 
24 enum {
25 	IDport			= 0x0110,	/* anywhere between 0x0100 and 0x01F0 */
26 };
27 
28 enum {						/* all windows */
29 	CommandR		= 0x000E,
30 	IntStatusR		= 0x000E,
31 };
32 
33 enum {						/* Commands */
34 	GlobalReset		= 0x0000,
35 	SelectRegisterWindow	= 0x0001,
36 	EnableDcConverter	= 0x0002,
37 	RxDisable		= 0x0003,
38 	RxEnable		= 0x0004,
39 	RxReset			= 0x0005,
40 	Stall			= 0x0006,	/* 3C90x */
41 	TxDone			= 0x0007,
42 	RxDiscard		= 0x0008,
43 	TxEnable		= 0x0009,
44 	TxDisable		= 0x000A,
45 	TxReset			= 0x000B,
46 	RequestInterrupt	= 0x000C,
47 	AcknowledgeInterrupt	= 0x000D,
48 	SetInterruptEnable	= 0x000E,
49 	SetIndicationEnable	= 0x000F,	/* SetReadZeroMask */
50 	SetRxFilter		= 0x0010,
51 	SetRxEarlyThresh	= 0x0011,
52 	SetTxAvailableThresh	= 0x0012,
53 	SetTxStartThresh	= 0x0013,
54 	StartDma		= 0x0014,	/* initiate busmaster operation */
55 	StatisticsEnable	= 0x0015,
56 	StatisticsDisable	= 0x0016,
57 	DisableDcConverter	= 0x0017,
58 	SetTxReclaimThresh	= 0x0018,	/* PIO-only adapters */
59 	PowerUp			= 0x001B,	/* not all adapters */
60 	PowerDownFull		= 0x001C,	/* not all adapters */
61 	PowerAuto		= 0x001D,	/* not all adapters */
62 };
63 
64 enum {						/* (Global|Rx|Tx)Reset command bits */
65 	tpAuiReset		= 0x0001,	/* 10BaseT and AUI transceivers */
66 	endecReset		= 0x0002,	/* internal Ethernet encoder/decoder */
67 	networkReset		= 0x0004,	/* network interface logic */
68 	fifoReset		= 0x0008,	/* FIFO control logic */
69 	aismReset		= 0x0010,	/* autoinitialise state-machine logic */
70 	hostReset		= 0x0020,	/* bus interface logic */
71 	dmaReset		= 0x0040,	/* bus master logic */
72 	vcoReset		= 0x0080,	/* on-board 10Mbps VCO */
73 	updnReset		= 0x0100,	/* upload/download (Rx/TX) logic */
74 
75 	resetMask		= 0x01FF,
76 };
77 
78 enum {						/* Stall command bits */
79 	upStall			= 0x0000,
80 	upUnStall		= 0x0001,
81 	dnStall			= 0x0002,
82 	dnUnStall		= 0x0003,
83 };
84 
85 enum {						/* SetRxFilter command bits */
86 	receiveIndividual	= 0x0001,	/* match station address */
87 	receiveMulticast	= 0x0002,
88 	receiveBroadcast	= 0x0004,
89 	receiveAllFrames	= 0x0008,	/* promiscuous */
90 };
91 
92 enum {						/* StartDma command bits */
93 	Upload			= 0x0000,	/* transfer data from adapter to memory */
94 	Download		= 0x0001,	/* transfer data from memory to adapter */
95 };
96 
97 enum {						/* IntStatus bits */
98 	interruptLatch		= 0x0001,
99 	hostError		= 0x0002,	/* Adapter Failure */
100 	txComplete		= 0x0004,
101 	txAvailable		= 0x0008,
102 	rxComplete		= 0x0010,
103 	rxEarly			= 0x0020,
104 	intRequested		= 0x0040,
105 	updateStats		= 0x0080,
106 	transferInt		= 0x0100,	/* Bus Master Transfer Complete */
107 	dnComplete		= 0x0200,
108 	upComplete		= 0x0400,
109 	busMasterInProgress	= 0x0800,
110 	commandInProgress	= 0x1000,
111 
112 	interruptMask		= 0x07FE,
113 };
114 
115 #define COMMAND(port, cmd, a)	outs((port)+CommandR, ((cmd)<<11)|(a))
116 #define STATUS(port)		ins((port)+IntStatusR)
117 
118 enum {						/* Window 0 - setup */
119 	Wsetup			= 0x0000,
120 						/* registers */
121 	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */
122 	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */
123 	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */
124 	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */
125 	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */
126 	EepromCommand		= 0x000A,
127 	EepromData		= 0x000C,
128 						/* AddressConfig Bits */
129 	autoSelect9		= 0x0080,
130 	xcvrMask9		= 0xC000,
131 						/* ConfigControl bits */
132 	Ena			= 0x0001,
133 	base10TAvailable9	= 0x0200,
134 	coaxAvailable9		= 0x1000,
135 	auiAvailable9		= 0x2000,
136 						/* EepromCommand bits */
137 	EepromReadRegister	= 0x0080,
138 	EepromReadOffRegister	= 0x00B0,
139 	EepromRead8bRegister	= 0x0230,
140 	EepromBusy		= 0x8000,
141 };
142 
143 #define EEPROMCMD(port, cmd, a)	outs((port)+EepromCommand, (cmd)|(a))
144 #define EEPROMBUSY(port)	(ins((port)+EepromCommand) & EepromBusy)
145 #define EEPROMDATA(port)	ins((port)+EepromData)
146 
147 enum {						/* Window 1 - operating set */
148 	Wop			= 0x0001,
149 						/* registers */
150 	Fifo			= 0x0000,
151 	RxError			= 0x0004,	/* 3C59[0257] only */
152 	RxStatus		= 0x0008,
153 	TIMER			= 0x000A,
154 	TxStatus		= 0x000B,
155 	TxFree			= 0x000C,
156 						/* RxError bits */
157 	rxOverrun		= 0x0001,
158 	runtFrame		= 0x0002,
159 	alignmentError		= 0x0004,	/* Framing */
160 	crcError		= 0x0008,
161 	oversizedFrame		= 0x0010,
162 	dribbleBits		= 0x0080,
163 						/* RxStatus bits */
164 	rxBytes			= 0x1FFF,	/* 3C59[0257] mask */
165 	rxBytes9		= 0x07FF,	/* 3C5[078]9 mask */
166 	rxError9		= 0x3800,	/* 3C5[078]9 error mask */
167 	rxOverrun9		= 0x0000,
168 	oversizedFrame9		= 0x0800,
169 	dribbleBits9		= 0x1000,
170 	runtFrame9		= 0x1800,
171 	alignmentError9		= 0x2000,	/* Framing */
172 	crcError9		= 0x2800,
173 	rxError			= 0x4000,
174 	rxIncomplete		= 0x8000,
175 						/* TxStatus Bits */
176 	txStatusOverflow	= 0x0004,
177 	maxCollisions		= 0x0008,
178 	txUnderrun		= 0x0010,
179 	txJabber		= 0x0020,
180 	interruptRequested	= 0x0040,
181 	txStatusComplete	= 0x0080,
182 };
183 
184 enum {						/* Window 2 - station address */
185 	Wstation		= 0x0002,
186 
187 	ResetOp905B		= 0x000C,
188 };
189 
190 enum {						/* Window 3 - FIFO management */
191 	Wfifo			= 0x0003,
192 						/* registers */
193 	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */
194 	OtherInt		= 0x0004,	/* 3C59[0257] */
195 	RomControl		= 0x0006,	/* 3C509B, 3C59[27] */
196 	MacControl		= 0x0006,	/* 3C59[0257] */
197 	ResetOptions		= 0x0008,	/* 3C59[0257] */
198 	MediaOptions		= 0x0008,	/* 3C905B */
199 	RxFree			= 0x000A,
200 						/* InternalConfig bits */
201 	disableBadSsdDetect	= 0x00000100,
202 	ramLocation		= 0x00000200,	/* 0 external, 1 internal */
203 	ramPartition5to3	= 0x00000000,
204 	ramPartition3to1	= 0x00010000,
205 	ramPartition1to1	= 0x00020000,
206 	ramPartition3to5	= 0x00030000,
207 	ramPartitionMask	= 0x00030000,
208 	xcvr10BaseT		= 0x00000000,
209 	xcvrAui			= 0x00100000,	/* 10BASE5 */
210 	xcvr10Base2		= 0x00300000,
211 	xcvr100BaseTX		= 0x00400000,
212 	xcvr100BaseFX		= 0x00500000,
213 	xcvrMii			= 0x00600000,
214 	xcvrMask		= 0x00700000,
215 	autoSelect		= 0x01000000,
216 						/* MacControl bits */
217 	deferExtendEnable	= 0x0001,
218 	deferTIMERSelect	= 0x001E,	/* mask */
219 	fullDuplexEnable	= 0x0020,
220 	allowLargePackets	= 0x0040,
221 	extendAfterCollision	= 0x0080,	/* 3C90xB */
222 	flowControlEnable	= 0x0100,	/* 3C90xB */
223 	vltEnable		= 0x0200,	/* 3C90xB */
224 						/* ResetOptions bits */
225 	baseT4Available		= 0x0001,
226 	baseTXAvailable		= 0x0002,
227 	baseFXAvailable		= 0x0004,
228 	base10TAvailable	= 0x0008,
229 	coaxAvailable		= 0x0010,
230 	auiAvailable		= 0x0020,
231 	miiConnector		= 0x0040,
232 };
233 
234 enum {						/* Window 4 - diagnostic */
235 	Wdiagnostic		= 0x0004,
236 						/* registers */
237 	VcoDiagnostic		= 0x0002,
238 	FifoDiagnostic		= 0x0004,
239 	NetworkDiagnostic	= 0x0006,
240 	PhysicalMgmt		= 0x0008,
241 	MediaStatus		= 0x000A,
242 	BadSSD			= 0x000C,
243 	UpperBytesOk		= 0x000D,
244 						/* FifoDiagnostic bits */
245 	txOverrun		= 0x0400,
246 	rxUnderrun		= 0x2000,
247 	receiving		= 0x8000,
248 						/* PhysicalMgmt bits */
249 	mgmtClk			= 0x0001,
250 	mgmtData		= 0x0002,
251 	mgmtDir			= 0x0004,
252 	cat5LinkTestDefeat	= 0x8000,
253 						/* MediaStatus bits */
254 	dataRate100		= 0x0002,
255 	crcStripDisable		= 0x0004,
256 	enableSqeStats		= 0x0008,
257 	collisionDetect		= 0x0010,
258 	carrierSense		= 0x0020,
259 	jabberGuardEnable	= 0x0040,
260 	linkBeatEnable		= 0x0080,
261 	jabberDetect		= 0x0200,
262 	polarityReversed	= 0x0400,
263 	linkBeatDetect		= 0x0800,
264 	txInProg		= 0x1000,
265 	dcConverterEnabled	= 0x4000,
266 	auiDisable		= 0x8000,	/* 10BaseT transceiver selected */
267 };
268 
269 enum {						/* Window 5 - internal state */
270 	Wstate			= 0x0005,
271 						/* registers */
272 	TxStartThresh		= 0x0000,
273 	TxAvailableThresh	= 0x0002,
274 	RxEarlyThresh		= 0x0006,
275 	RxFilter		= 0x0008,
276 	InterruptEnable		= 0x000A,
277 	IndicationEnable	= 0x000C,
278 };
279 
280 enum {						/* Window 6 - statistics */
281 	Wstatistics		= 0x0006,
282 						/* registers */
283 	CarrierLost		= 0x0000,
284 	SqeErrors		= 0x0001,
285 	MultipleColls		= 0x0002,
286 	SingleCollFrames	= 0x0003,
287 	LateCollisions		= 0x0004,
288 	RxOverruns		= 0x0005,
289 	FramesXmittedOk		= 0x0006,
290 	FramesRcvdOk		= 0x0007,
291 	FramesDeferred		= 0x0008,
292 	UpperFramesOk		= 0x0009,
293 	BytesRcvdOk		= 0x000A,
294 	BytesXmittedOk		= 0x000C,
295 };
296 
297 enum {						/* Window 7 - bus master operations */
298 	Wmaster			= 0x0007,
299 						/* registers */
300 	MasterAddress		= 0x0000,
301 	MasterLen		= 0x0006,
302 	MasterStatus		= 0x000C,
303 						/* MasterStatus bits */
304 	masterAbort		= 0x0001,
305 	targetAbort		= 0x0002,
306 	targetRetry		= 0x0004,
307 	targetDisc		= 0x0008,
308 	masterDownload		= 0x1000,
309 	masterUpload		= 0x4000,
310 	masterInProgress	= 0x8000,
311 
312 	masterMask		= 0xD00F,
313 };
314 
315 enum {						/* 3C90x extended register set */
316 	TIMER905		= 0x001A,	/* 8-bits */
317 	TxStatus905		= 0x001B,	/* 8-bits */
318 	PktStatus		= 0x0020,	/* 32-bits */
319 	DnListPtr		= 0x0024,	/* 32-bits, 8-byte aligned */
320 	FragAddr		= 0x0028,	/* 32-bits */
321 	FragLen			= 0x002C,	/* 16-bits */
322 	ListOffset		= 0x002E,	/* 8-bits */
323 	TxFreeThresh		= 0x002F,	/* 8-bits */
324 	UpPktStatus		= 0x0030,	/* 32-bits */
325 	FreeTIMER		= 0x0034,	/* 16-bits */
326 	UpListPtr		= 0x0038,	/* 32-bits, 8-byte aligned */
327 
328 						/* PktStatus bits */
329 	fragLast		= 0x00000001,
330 	dnCmplReq		= 0x00000002,
331 	dnStalled		= 0x00000004,
332 	upCompleteX		= 0x00000008,
333 	dnCompleteX		= 0x00000010,
334 	upRxEarlyEnable		= 0x00000020,
335 	armCountdown		= 0x00000040,
336 	dnInProg		= 0x00000080,
337 	counterSpeed		= 0x00000010,	/* 0 3.2uS, 1 320nS */
338 	countdownMode		= 0x00000020,
339 						/* UpPktStatus bits (dpd->control) */
340 	upPktLenMask		= 0x00001FFF,
341 	upStalled		= 0x00002000,
342 	upError			= 0x00004000,
343 	upPktComplete		= 0x00008000,
344 	upOverrun		= 0x00010000,	/* RxError<<16 */
345 	upRuntFrame		= 0x00020000,
346 	upAlignmentError	= 0x00040000,
347 	upCRCError		= 0x00080000,
348 	upOversizedFrame	= 0x00100000,
349 	upDribbleBits		= 0x00800000,
350 	upOverflow		= 0x01000000,
351 
352 	dnIndicate		= 0x80000000,	/* FrameStartHeader (dpd->control) */
353 
354 	updnLastFrag		= 0x80000000,	/* (dpd->len) */
355 
356 	Nup			= 32,
357 	Ndn			= 64,
358 };
359 
360 /*
361  * Up/Dn Packet Descriptors.
362  * The hardware info (np, control, addr, len) must be 8-byte aligned
363  * and this structure size must be a multiple of 8.
364  */
365 typedef struct Pd Pd;
366 typedef struct Pd {
367 	ulong	np;			/* next pointer */
368 	ulong	control;		/* FSH or UpPktStatus */
369 	ulong	addr;
370 	ulong	len;
371 
372 	Pd*	next;
373 	Block*	bp;
374 } Pd;
375 
376 typedef struct Ctlr Ctlr;
377 typedef struct Ctlr {
378 	int	port;
379 	Pcidev*	pcidev;
380 	int	irq;
381 	Ctlr*	next;
382 	int	active;
383 	int	did;
384 
385 	Lock	wlock;			/* window access */
386 
387 	int	attached;
388 	int	busmaster;
389 	Block*	rbp;			/* receive buffer */
390 
391 	Block*	txbp;			/* FIFO -based transmission */
392 	int	txthreshold;
393 	int	txbusy;
394 
395 	int	nup;			/* full-busmaster -based reception */
396 	void*	upbase;
397 	Pd*	upr;
398 	Pd*	uphead;
399 
400 	int	ndn;			/* full-busmaster -based transmission */
401 	void*	dnbase;
402 	Pd*	dnr;
403 	Pd*	dnhead;
404 	Pd*	dntail;
405 	int	dnq;
406 
407 	long	interrupts;		/* statistics */
408 	long	bogusinterrupts;
409 	long	timer[2];
410 	long	stats[BytesRcvdOk+3];
411 
412 	int	upqmax;
413 	int	upqmaxhw;
414 	ulong	upinterrupts;
415 	ulong	upqueued;
416 	ulong	upstalls;
417 	int	dnqmax;
418 	int	dnqmaxhw;
419 	ulong	dninterrupts;
420 	ulong	dnqueued;
421 
422 	int	xcvr;			/* transceiver type */
423 	int	eepromcmd;		/* EEPROM read command */
424 	int	rxstatus9;		/* old-style RxStatus register */
425 	int	rxearly;		/* RxEarlyThreshold */
426 	int	ts;			/* threshold shift */
427 	int	upenabled;
428 	int	dnenabled;
429 	ulong	cbfnpa;			/* CardBus functions */
430 	ulong*	cbfn;
431 } Ctlr;
432 
433 static Ctlr* ctlrhead;
434 static Ctlr* ctlrtail;
435 
436 static void
init905(Ctlr * ctlr)437 init905(Ctlr* ctlr)
438 {
439 	Block *bp;
440 	Pd *pd, *prev;
441 
442 	/*
443 	 * Create rings for the receive and transmit sides.
444 	 * Take care with alignment:
445 	 *	make sure ring base is 8-byte aligned;
446 	 *	make sure each entry is 8-byte aligned.
447 	 */
448 	ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
449 	if(ctlr->upbase == nil)
450 		error(Enomem);
451 	ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
452 
453 	prev = ctlr->upr;
454 	for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
455 		pd->np = PADDR(&prev->np);
456 		pd->control = 0;
457 		bp = iallocb(sizeof(Etherpkt));
458 		if(bp == nil)
459 			panic("can't allocate ethernet receive ring");
460 		pd->addr = PADDR(bp->rp);
461 		pd->len = updnLastFrag|sizeof(Etherpkt);
462 
463 		pd->next = prev;
464 		prev = pd;
465 		pd->bp = bp;
466 	}
467 	ctlr->uphead = ctlr->upr;
468 
469 	ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
470 	if(ctlr->dnbase == nil) {
471 		free(ctlr->upbase);
472 		error(Enomem);
473 	}
474 	ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
475 
476 	prev = ctlr->dnr;
477 	for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
478 		pd->next = prev;
479 		prev = pd;
480 	}
481 	ctlr->dnhead = ctlr->dnr;
482 	ctlr->dntail = ctlr->dnr;
483 	ctlr->dnq = 0;
484 }
485 
486 static Block*
rbpalloc(Block * (* f)(int))487 rbpalloc(Block* (*f)(int))
488 {
489 	Block *bp;
490 	ulong addr;
491 
492 	/*
493 	 * The receive buffers must be on a 32-byte
494 	 * boundary for EISA busmastering.
495 	 */
496 	if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
497 		addr = (ulong)bp->base;
498 		addr = ROUNDUP(addr, 32);
499 		bp->rp = (uchar*)addr;
500 	}
501 
502 	return bp;
503 }
504 
505 static uchar*
startdma(Ether * ether,ulong address)506 startdma(Ether* ether, ulong address)
507 {
508 	int port, status, w;
509 	uchar *wp;
510 
511 	port = ether->port;
512 
513 	w = (STATUS(port)>>13) & 0x07;
514 	COMMAND(port, SelectRegisterWindow, Wmaster);
515 
516 	wp = KADDR(inl(port+MasterAddress));
517 	status = ins(port+MasterStatus);
518 	if(status & (masterInProgress|targetAbort|masterAbort))
519 		print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
520 	outs(port+MasterStatus, masterMask);
521 	outl(port+MasterAddress, address);
522 	outs(port+MasterLen, sizeof(Etherpkt));
523 	COMMAND(port, StartDma, Upload);
524 
525 	COMMAND(port, SelectRegisterWindow, w);
526 	return wp;
527 }
528 
529 static void
promiscuous(void * arg,int on)530 promiscuous(void* arg, int on)
531 {
532 	int filter, port;
533 	Ether *ether;
534 
535 	ether = (Ether*)arg;
536 	port = ether->port;
537 
538 	filter = receiveBroadcast|receiveIndividual;
539 	if(ether->nmaddr)
540 		filter |= receiveMulticast;
541 	if(on)
542 		filter |= receiveAllFrames;
543 	COMMAND(port, SetRxFilter, filter);
544 }
545 
546 static void
multicast(void * arg,uchar * addr,int on)547 multicast(void* arg, uchar *addr, int on)
548 {
549 	int filter, port;
550 	Ether *ether;
551 
552 	USED(addr, on);
553 
554 	ether = (Ether*)arg;
555 	port = ether->port;
556 
557 	filter = receiveBroadcast|receiveIndividual;
558 	if(ether->nmaddr)
559 		filter |= receiveMulticast;
560 	if(ether->prom)
561 		filter |= receiveAllFrames;
562 	COMMAND(port, SetRxFilter, filter);
563 }
564 
565 /* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
566 static void
intrackcb(ulong * cbfn)567 intrackcb(ulong *cbfn)
568 {
569 	cbfn[1] = 0x8000;
570 }
571 
572 static void
attach(Ether * ether)573 attach(Ether* ether)
574 {
575 	int port, x;
576 	Ctlr *ctlr;
577 
578 	ctlr = ether->ctlr;
579 	ilock(&ctlr->wlock);
580 	if(ctlr->attached){
581 		iunlock(&ctlr->wlock);
582 		return;
583 	}
584 
585 	port = ether->port;
586 
587 	/*
588 	 * Set the receiver packet filter for this and broadcast addresses,
589 	 * set the interrupt masks for all interrupts, enable the receiver
590 	 * and transmitter.
591 	 */
592 	promiscuous(ether, ether->prom);
593 
594 	x = interruptMask;
595 	if(ctlr->busmaster == 1)
596 		x &= ~(rxEarly|rxComplete);
597 	else{
598 		if(ctlr->dnenabled)
599 			x &= ~transferInt;
600 		if(ctlr->upenabled)
601 			x &= ~(rxEarly|rxComplete);
602 	}
603 	COMMAND(port, SetIndicationEnable, x);
604 	COMMAND(port, SetInterruptEnable, x);
605 	COMMAND(port, RxEnable, 0);
606 	COMMAND(port, TxEnable, 0);
607 
608 	/*
609 	 * If this is a CardBus card, acknowledge any interrupts.
610 	 */
611 	if(ctlr->cbfn != nil)
612 		intrackcb(ctlr->cbfn);
613 
614 	/*
615 	 * Prime the busmaster channel for receiving directly into a
616 	 * receive packet buffer if necessary.
617 	 */
618 	if(ctlr->busmaster == 1)
619 		startdma(ether, PADDR(ctlr->rbp->rp));
620 	else{
621 		if(ctlr->upenabled)
622 			outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
623 	}
624 
625 	ctlr->attached = 1;
626 	iunlock(&ctlr->wlock);
627 }
628 
629 static void
statistics(Ether * ether)630 statistics(Ether* ether)
631 {
632 	int port, i, u, w;
633 	Ctlr *ctlr;
634 
635 	port = ether->port;
636 	ctlr = ether->ctlr;
637 
638 	/*
639 	 * 3C59[27] require a read between a PIO write and
640 	 * reading a statistics register.
641 	 */
642 	w = (STATUS(port)>>13) & 0x07;
643 	COMMAND(port, SelectRegisterWindow, Wstatistics);
644 	STATUS(port);
645 
646 	for(i = 0; i < UpperFramesOk; i++)
647 		ctlr->stats[i] += inb(port+i) & 0xFF;
648 	u = inb(port+UpperFramesOk) & 0xFF;
649 	ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
650 	ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
651 	ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
652 	ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
653 
654 	switch(ctlr->xcvr){
655 
656 	case xcvrMii:
657 	case xcvr100BaseTX:
658 	case xcvr100BaseFX:
659 		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
660 		STATUS(port);
661 		ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
662 		break;
663 	}
664 
665 	COMMAND(port, SelectRegisterWindow, w);
666 }
667 
668 static void
txstart(Ether * ether)669 txstart(Ether* ether)
670 {
671 	int port, len;
672 	Ctlr *ctlr;
673 	Block *bp;
674 
675 	port = ether->port;
676 	ctlr = ether->ctlr;
677 
678 	/*
679 	 * Attempt to top-up the transmit FIFO. If there's room simply
680 	 * stuff in the packet length (unpadded to a dword boundary), the
681 	 * packet data (padded) and remove the packet from the queue.
682 	 * If there's no room post an interrupt for when there is.
683 	 * This routine is called both from the top level and from interrupt
684 	 * level and expects to be called with ctlr->wlock already locked
685 	 * and the correct register window (Wop) in place.
686 	 */
687 	for(;;){
688 		if(ctlr->txbp){
689 			bp = ctlr->txbp;
690 			ctlr->txbp = 0;
691 		}
692 		else{
693 			bp = qget(ether->oq);
694 			if(bp == nil)
695 				break;
696 		}
697 
698 		len = ROUNDUP(BLEN(bp), 4);
699 		if(len+4 <= ins(port+TxFree)){
700 			outl(port+Fifo, BLEN(bp));
701 			outsl(port+Fifo, bp->rp, len/4);
702 
703 			freeb(bp);
704 
705 			ether->outpackets++;
706 		}
707 		else{
708 			ctlr->txbp = bp;
709 			if(ctlr->txbusy == 0){
710 				ctlr->txbusy = 1;
711 				COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
712 			}
713 			break;
714 		}
715 	}
716 }
717 
718 static void
txstart905(Ether * ether)719 txstart905(Ether* ether)
720 {
721 	Ctlr *ctlr;
722 	int port, stalled, timeo;
723 	Block *bp;
724 	Pd *pd;
725 
726 	ctlr = ether->ctlr;
727 	port = ether->port;
728 
729 	/*
730 	 * Free any completed packets.
731 	 */
732 	pd = ctlr->dntail;
733 	while(ctlr->dnq){
734 		if(PADDR(&pd->np) == inl(port+DnListPtr))
735 			break;
736 		if(pd->bp){
737 			freeb(pd->bp);
738 			pd->bp = nil;
739 		}
740 		ctlr->dnq--;
741 		pd = pd->next;
742 	}
743 	ctlr->dntail = pd;
744 
745 	stalled = 0;
746 	while(ctlr->dnq < (ctlr->ndn-1)){
747 		bp = qget(ether->oq);
748 		if(bp == nil)
749 			break;
750 
751 		pd = ctlr->dnhead->next;
752 		pd->np = 0;
753 		pd->control = dnIndicate|BLEN(bp);
754 		pd->addr = PADDR(bp->rp);
755 		pd->len = updnLastFrag|BLEN(bp);
756 		pd->bp = bp;
757 
758 		if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
759 			COMMAND(port, Stall, dnStall);
760 			for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
761 				;
762 			if(timeo == 0)
763 				print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
764 			stalled = 1;
765 		}
766 
767 		coherence();
768 		ctlr->dnhead->np = PADDR(&pd->np);
769 		ctlr->dnhead->control &= ~dnIndicate;
770 		ctlr->dnhead = pd;
771 		if(ctlr->dnq == 0)
772 			ctlr->dntail = pd;
773 		ctlr->dnq++;
774 
775 		ctlr->dnqueued++;
776 	}
777 
778 	if(ctlr->dnq > ctlr->dnqmax)
779 		ctlr->dnqmax = ctlr->dnq;
780 
781 	/*
782 	 * If the adapter is not currently processing anything
783 	 * and there is something on the queue, start it processing.
784 	 */
785 	if(inl(port+DnListPtr) == 0 && ctlr->dnq)
786 		outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
787 	if(stalled)
788 		COMMAND(port, Stall, dnUnStall);
789 }
790 
791 static void
transmit(Ether * ether)792 transmit(Ether* ether)
793 {
794 	Ctlr *ctlr;
795 	int port, w;
796 
797 	port = ether->port;
798 	ctlr = ether->ctlr;
799 
800 	ilock(&ctlr->wlock);
801 	if(ctlr->dnenabled)
802 		txstart905(ether);
803 	else{
804 		w = (STATUS(port)>>13) & 0x07;
805 		COMMAND(port, SelectRegisterWindow, Wop);
806 		txstart(ether);
807 		COMMAND(port, SelectRegisterWindow, w);
808 	}
809 	iunlock(&ctlr->wlock);
810 }
811 
812 static void
receive905(Ether * ether)813 receive905(Ether* ether)
814 {
815 	Ctlr *ctlr;
816 	int len, port, q;
817 	Pd *pd;
818 	Block *bp;
819 
820 	ctlr = ether->ctlr;
821 	port = ether->port;
822 
823 	if(inl(port+UpPktStatus) & upStalled)
824 		ctlr->upstalls++;
825 	q = 0;
826 	for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
827 		if(pd->control & upError){
828 			if(pd->control & upOverrun)
829 				ether->overflows++;
830 			if(pd->control & (upOversizedFrame|upRuntFrame))
831 				ether->buffs++;
832 			if(pd->control & upAlignmentError)
833 				ether->frames++;
834 			if(pd->control & upCRCError)
835 				ether->crcs++;
836 		}
837 		else if(bp = iallocb(sizeof(Etherpkt)+4)){
838 			len = pd->control & rxBytes;
839 			pd->bp->wp = pd->bp->rp+len;
840 			etheriq(ether, pd->bp, 1);
841 			pd->bp = bp;
842 			pd->addr = PADDR(bp->rp);
843 			coherence();
844 		}
845 
846 		pd->control = 0;
847 		COMMAND(port, Stall, upUnStall);
848 
849 		q++;
850 	}
851 	ctlr->uphead = pd;
852 
853 	ctlr->upqueued += q;
854 	if(q > ctlr->upqmax)
855 		ctlr->upqmax = q;
856 }
857 
858 static void
receive(Ether * ether)859 receive(Ether* ether)
860 {
861 	int len, port, rxerror, rxstatus;
862 	Ctlr *ctlr;
863 	Block *bp;
864 
865 	port = ether->port;
866 	ctlr = ether->ctlr;
867 
868 	while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
869 		if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
870 			break;
871 
872 		/*
873 		 * If there was an error, log it and continue.
874 		 * Unfortunately the 3C5[078]9 has the error info in the status register
875 		 * and the 3C59[0257] implement a separate RxError register.
876 		 */
877 		if(rxstatus & rxError){
878 			if(ctlr->rxstatus9){
879 				switch(rxstatus & rxError9){
880 
881 				case rxOverrun9:
882 					ether->overflows++;
883 					break;
884 
885 				case oversizedFrame9:
886 				case runtFrame9:
887 					ether->buffs++;
888 					break;
889 
890 				case alignmentError9:
891 					ether->frames++;
892 					break;
893 
894 				case crcError9:
895 					ether->crcs++;
896 					break;
897 
898 				}
899 			}
900 			else{
901 				rxerror = inb(port+RxError);
902 				if(rxerror & rxOverrun)
903 					ether->overflows++;
904 				if(rxerror & (oversizedFrame|runtFrame))
905 					ether->buffs++;
906 				if(rxerror & alignmentError)
907 					ether->frames++;
908 				if(rxerror & crcError)
909 					ether->crcs++;
910 			}
911 		}
912 
913 		/*
914 		 * If there was an error or a new receive buffer can't be
915 		 * allocated, discard the packet and go on to the next.
916 		 */
917 		if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){
918 			COMMAND(port, RxDiscard, 0);
919 			while(STATUS(port) & commandInProgress)
920 				;
921 
922 			if(ctlr->busmaster == 1)
923 				startdma(ether, PADDR(ctlr->rbp->rp));
924 
925 			continue;
926 		}
927 
928 		/*
929 		 * A valid receive packet awaits:
930 		 *	if using PIO, read it into the buffer;
931 		 *	discard the packet from the FIFO;
932 		 *	if using busmastering, start a new transfer for
933 		 *	  the next packet and as a side-effect get the
934 		 *	  end-pointer of the one just received;
935 		 *	pass the packet on to whoever wants it.
936 		 */
937 		if(ctlr->busmaster == 0 || ctlr->busmaster == 2){
938 			len = (rxstatus & rxBytes9);
939 			ctlr->rbp->wp = ctlr->rbp->rp + len;
940 			insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4));
941 		}
942 
943 		COMMAND(port, RxDiscard, 0);
944 		while(STATUS(port) & commandInProgress)
945 			;
946 
947 		if(ctlr->busmaster == 1)
948 			ctlr->rbp->wp = startdma(ether, PADDR(bp->rp));
949 
950 		etheriq(ether, ctlr->rbp, 1);
951 		ctlr->rbp = bp;
952 	}
953 }
954 
955 static int
ejectable(int did)956 ejectable(int did)
957 {
958 	switch (did) {
959 	case 0x5157:
960 		return 1;
961 
962 	default:
963 		return 0;
964 	}
965 }
966 
967 static void
interrupt(Ureg *,void * arg)968 interrupt(Ureg*, void* arg)
969 {
970 	Ether *ether;
971 	int port, status, s, txstatus, w, x;
972 	Ctlr *ctlr;
973 
974 	ether = arg;
975 	port = ether->port;
976 	ctlr = ether->ctlr;
977 
978 	ilock(&ctlr->wlock);
979 	status = STATUS(port);
980 	if(!(status & (interruptMask|interruptLatch))){
981 		ctlr->bogusinterrupts++;
982 		iunlock(&ctlr->wlock);
983 		return;
984 	}
985 	w = (status>>13) & 0x07;
986 	COMMAND(port, SelectRegisterWindow, Wop);
987 
988 	ctlr->interrupts++;
989 	if(ctlr->busmaster == 2)
990 		ctlr->timer[0] += inb(port+TIMER905) & 0xFF;
991 	else
992 		ctlr->timer[0] += inb(port+TIMER) & 0xFF;
993 
994 	do{
995 		if(status & hostError){
996 			/*
997 			 * Adapter failure, try to find out why, reset if
998 			 * necessary. What happens if Tx is active and a reset
999 			 * occurs, need to retransmit? This probably isn't right.
1000 			 */
1001 			COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1002 			x = ins(port+FifoDiagnostic);
1003 			COMMAND(port, SelectRegisterWindow, Wop);
1004 
1005 			if (status == 0xFFFF && x == 0xFFFF && ejectable(ctlr->did)) {
1006 				print("#l%d: Card ejected?\n", ether->ctlrno);
1007 				iunlock(&ctlr->wlock);
1008 				return;
1009 			}
1010 
1011 			print("#l%d: status 0x%uX, diag 0x%uX\n",
1012 			    ether->ctlrno, status, x);
1013 
1014 			if(x & txOverrun){
1015 				if(ctlr->busmaster == 0)
1016 					COMMAND(port, TxReset, 0);
1017 				else
1018 					COMMAND(port, TxReset, (updnReset|dmaReset));
1019 				COMMAND(port, TxEnable, 0);
1020 			}
1021 
1022 			if(x & rxUnderrun){
1023 				/*
1024 				 * This shouldn't happen...
1025 				 * Reset the receiver and restore the filter and RxEarly
1026 				 * threshold before re-enabling.
1027 				 * Need to restart any busmastering?
1028 				 */
1029 				COMMAND(port, SelectRegisterWindow, Wstate);
1030 				s = (port+RxFilter) & 0x000F;
1031 				COMMAND(port, SelectRegisterWindow, Wop);
1032 				COMMAND(port, RxReset, 0);
1033 				while(STATUS(port) & commandInProgress)
1034 					;
1035 				COMMAND(port, SetRxFilter, s);
1036 				COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
1037 				COMMAND(port, RxEnable, 0);
1038 			}
1039 
1040 			status &= ~hostError;
1041 		}
1042 
1043 		if(status & (transferInt|rxComplete)){
1044 			receive(ether);
1045 			status &= ~(transferInt|rxComplete);
1046 		}
1047 
1048 		if(status & (upComplete)){
1049 			COMMAND(port, AcknowledgeInterrupt, upComplete);
1050 			receive905(ether);
1051 			status &= ~upComplete;
1052 			ctlr->upinterrupts++;
1053 		}
1054 
1055 		if(status & txComplete){
1056 			/*
1057 			 * Pop the TxStatus stack, accumulating errors.
1058 			 * Adjust the TX start threshold if there was an underrun.
1059 			 * If there was a Jabber or Underrun error, reset
1060 			 * the transmitter, taking care not to reset the dma logic
1061 			 * as a busmaster receive may be in progress.
1062 			 * For all conditions enable the transmitter.
1063 			 */
1064 			if(ctlr->busmaster == 2)
1065 				txstatus = port+TxStatus905;
1066 			else
1067 				txstatus = port+TxStatus;
1068 			s = 0;
1069 			do{
1070 				if(x = inb(txstatus))
1071 					outb(txstatus, 0);
1072 				s |= x;
1073 			}while(STATUS(port) & txComplete);
1074 
1075 			if(s & txUnderrun){
1076 				if(ctlr->dnenabled){
1077 					while(inl(port+PktStatus) & dnInProg)
1078 						;
1079 				}
1080 				COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1081 				while(ins(port+MediaStatus) & txInProg)
1082 					;
1083 				COMMAND(port, SelectRegisterWindow, Wop);
1084 				if(ctlr->txthreshold < ETHERMAXTU)
1085 					ctlr->txthreshold += ETHERMINTU;
1086 			}
1087 
1088 			/*
1089 			 * According to the manual, maxCollisions does not require
1090 			 * a TxReset, merely a TxEnable. However, evidence points to
1091 			 * it being necessary on the 3C905. The jury is still out.
1092 			 * On busy or badly configured networks maxCollisions can
1093 			 * happen frequently enough for messages to be annoying so
1094 			 * keep quiet about them by popular request.
1095 			 */
1096 			if(s & (txJabber|txUnderrun|maxCollisions)){
1097 				if(ctlr->busmaster == 0)
1098 					COMMAND(port, TxReset, 0);
1099 				else
1100 					COMMAND(port, TxReset, (updnReset|dmaReset));
1101 				while(STATUS(port) & commandInProgress)
1102 					;
1103 				COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
1104 				if(ctlr->busmaster == 2)
1105 					outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
1106 				if(ctlr->dnenabled)
1107 					status |= dnComplete;
1108 			}
1109 
1110 			if(s & ~(txStatusComplete|maxCollisions))
1111 				print("#l%d: txstatus 0x%uX, threshold %d\n",
1112 			    		ether->ctlrno, s, ctlr->txthreshold);
1113 			COMMAND(port, TxEnable, 0);
1114 			ether->oerrs++;
1115 			status &= ~txComplete;
1116 			status |= txAvailable;
1117 		}
1118 
1119 		if(status & txAvailable){
1120 			COMMAND(port, AcknowledgeInterrupt, txAvailable);
1121 			ctlr->txbusy = 0;
1122 			txstart(ether);
1123 			status &= ~txAvailable;
1124 		}
1125 
1126 		if(status & dnComplete){
1127 			COMMAND(port, AcknowledgeInterrupt, dnComplete);
1128 			txstart905(ether);
1129 			status &= ~dnComplete;
1130 			ctlr->dninterrupts++;
1131 		}
1132 
1133 		if(status & updateStats){
1134 			statistics(ether);
1135 			status &= ~updateStats;
1136 		}
1137 
1138 		/*
1139 		 * Currently, this shouldn't happen.
1140 		 */
1141 		if(status & rxEarly){
1142 			COMMAND(port, AcknowledgeInterrupt, rxEarly);
1143 			status &= ~rxEarly;
1144 		}
1145 
1146 		/*
1147 		 * Panic if there are any interrupts not dealt with.
1148 		 */
1149 		if(status & interruptMask)
1150 			panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
1151 
1152 		COMMAND(port, AcknowledgeInterrupt, interruptLatch);
1153 		if(ctlr->cbfn != nil)
1154 			intrackcb(ctlr->cbfn);
1155 
1156 	}while((status = STATUS(port)) & (interruptMask|interruptLatch));
1157 
1158 	if(ctlr->busmaster == 2)
1159 		ctlr->timer[1] += inb(port+TIMER905) & 0xFF;
1160 	else
1161 		ctlr->timer[1] += inb(port+TIMER) & 0xFF;
1162 
1163 	COMMAND(port, SelectRegisterWindow, w);
1164 	iunlock(&ctlr->wlock);
1165 }
1166 
1167 static long
ifstat(Ether * ether,void * a,long n,ulong offset)1168 ifstat(Ether* ether, void* a, long n, ulong offset)
1169 {
1170 	char *p;
1171 	int len;
1172 	Ctlr *ctlr;
1173 
1174 	if(n == 0)
1175 		return 0;
1176 
1177 	ctlr = ether->ctlr;
1178 
1179 	ilock(&ctlr->wlock);
1180 	statistics(ether);
1181 	iunlock(&ctlr->wlock);
1182 
1183 	p = malloc(READSTR);
1184 	if(p == nil)
1185 		error(Enomem);
1186 	len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
1187 	len += snprint(p+len, READSTR-len, "bogusinterrupts: %lud\n", ctlr->bogusinterrupts);
1188 	len += snprint(p+len, READSTR-len, "timer: %lud %lud\n",
1189 		ctlr->timer[0], ctlr->timer[1]);
1190 	len += snprint(p+len, READSTR-len, "carrierlost: %lud\n",
1191 		ctlr->stats[CarrierLost]);
1192 	len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n",
1193 		ctlr->stats[SqeErrors]);
1194 	len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n",
1195 		ctlr->stats[MultipleColls]);
1196 	len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n",
1197 		ctlr->stats[SingleCollFrames]);
1198 	len += snprint(p+len, READSTR-len, "latecollisions: %lud\n",
1199 		ctlr->stats[LateCollisions]);
1200 	len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n",
1201 		ctlr->stats[RxOverruns]);
1202 	len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n",
1203 		ctlr->stats[FramesXmittedOk]);
1204 	len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n",
1205 		ctlr->stats[FramesRcvdOk]);
1206 	len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n",
1207 		ctlr->stats[FramesDeferred]);
1208 	len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n",
1209 		ctlr->stats[BytesRcvdOk]);
1210 	len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n",
1211 		ctlr->stats[BytesRcvdOk+1]);
1212 
1213 	if(ctlr->upenabled){
1214 		if(ctlr->upqmax > ctlr->upqmaxhw)
1215 			ctlr->upqmaxhw = ctlr->upqmax;
1216 		len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d h %d s %lud\n",
1217 			ctlr->upqueued, ctlr->upinterrupts,
1218 			ctlr->upqmax, ctlr->upqmaxhw, ctlr->upstalls);
1219 		ctlr->upqmax = 0;
1220 	}
1221 	if(ctlr->dnenabled){
1222 		if(ctlr->dnqmax > ctlr->dnqmaxhw)
1223 			ctlr->dnqmaxhw = ctlr->dnqmax;
1224 		len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d h %d\n",
1225 			ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax, ctlr->dnqmaxhw);
1226 		ctlr->dnqmax = 0;
1227 	}
1228 
1229 	snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]);
1230 
1231 	n = readstr(offset, a, n, p);
1232 	free(p);
1233 
1234 	return n;
1235 }
1236 
1237 static void
txrxreset(int port)1238 txrxreset(int port)
1239 {
1240 	COMMAND(port, TxReset, 0);
1241 	while(STATUS(port) & commandInProgress)
1242 		;
1243 	COMMAND(port, RxReset, 0);
1244 	while(STATUS(port) & commandInProgress)
1245 		;
1246 }
1247 
1248 static Ctlr*
tcmadapter(int port,int irq,Pcidev * pcidev)1249 tcmadapter(int port, int irq, Pcidev* pcidev)
1250 {
1251 	Ctlr *ctlr;
1252 
1253 	ctlr = malloc(sizeof(Ctlr));
1254 	if(ctlr == nil)
1255 		error(Enomem);
1256 	ctlr->port = port;
1257 	ctlr->irq = irq;
1258 	ctlr->pcidev = pcidev;
1259 	ctlr->eepromcmd = EepromReadRegister;
1260 
1261 	if(ctlrhead != nil)
1262 		ctlrtail->next = ctlr;
1263 	else
1264 		ctlrhead = ctlr;
1265 	ctlrtail = ctlr;
1266 
1267 	return ctlr;
1268 }
1269 
1270 /*
1271  * Write two 0 bytes to identify the IDport and then reset the
1272  * ID sequence. Then send the ID sequence to the card to get
1273  * the card into command state.
1274  */
1275 static void
idseq(void)1276 idseq(void)
1277 {
1278 	int i;
1279 	uchar al;
1280 	static int reset, untag;
1281 
1282 	/*
1283 	 * One time only:
1284 	 *	reset any adapters listening
1285 	 */
1286 	if(reset == 0){
1287 		outb(IDport, 0);
1288 		outb(IDport, 0);
1289 		outb(IDport, 0xC0);
1290 		delay(20);
1291 		reset = 1;
1292 	}
1293 
1294 	outb(IDport, 0);
1295 	outb(IDport, 0);
1296 	for(al = 0xFF, i = 0; i < 255; i++){
1297 		outb(IDport, al);
1298 		if(al & 0x80){
1299 			al <<= 1;
1300 			al ^= 0xCF;
1301 		}
1302 		else
1303 			al <<= 1;
1304 	}
1305 
1306 	/*
1307 	 * One time only:
1308 	 *	write ID sequence to get the attention of all adapters;
1309 	 *	untag all adapters.
1310 	 * If a global reset is done here on all adapters it will confuse
1311 	 * any ISA cards configured for EISA mode.
1312 	 */
1313 	if(untag == 0){
1314 		outb(IDport, 0xD0);
1315 		untag = 1;
1316 	}
1317 }
1318 
1319 static ulong
activate(void)1320 activate(void)
1321 {
1322 	int i;
1323 	ushort x, acr;
1324 
1325 	/*
1326 	 * Do the little configuration dance:
1327 	 *
1328 	 * 2. write the ID sequence to get to command state.
1329 	 */
1330 	idseq();
1331 
1332 	/*
1333 	 * 3. Read the Manufacturer ID from the EEPROM.
1334 	 *    This is done by writing the IDPort with 0x87 (0x80
1335 	 *    is the 'read EEPROM' command, 0x07 is the offset of
1336 	 *    the Manufacturer ID field in the EEPROM).
1337 	 *    The data comes back 1 bit at a time.
1338 	 *    A delay seems necessary between reading the bits.
1339 	 *
1340 	 * If the ID doesn't match, there are no more adapters.
1341 	 */
1342 	outb(IDport, 0x87);
1343 	delay(20);
1344 	for(x = 0, i = 0; i < 16; i++){
1345 		delay(20);
1346 		x <<= 1;
1347 		x |= inb(IDport) & 0x01;
1348 	}
1349 	if(x != 0x6D50)
1350 		return 0;
1351 
1352 	/*
1353 	 * 3. Read the Address Configuration from the EEPROM.
1354 	 *    The Address Configuration field is at offset 0x08 in the EEPROM).
1355 	 */
1356 	outb(IDport, 0x88);
1357 	for(acr = 0, i = 0; i < 16; i++){
1358 		delay(20);
1359 		acr <<= 1;
1360 		acr |= inb(IDport) & 0x01;
1361 	}
1362 
1363 	return (acr & 0x1F)*0x10 + 0x200;
1364 }
1365 
1366 static void
tcm509isa(void)1367 tcm509isa(void)
1368 {
1369 	int irq, port;
1370 
1371 	/*
1372 	 * Attempt to activate all adapters. If adapter is set for
1373 	 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
1374 	 * it fully.
1375 	 */
1376 	while(port = activate()){
1377 		if(ioalloc(port, 0x10, 0, "tcm509isa") < 0){
1378 			print("tcm509isa: port 0x%uX in use\n", port);
1379 			continue;
1380 		}
1381 
1382 		/*
1383 		 * 6. Tag the adapter so it won't respond in future.
1384 		 */
1385 		outb(IDport, 0xD1);
1386 		if(port == 0x3F0){
1387 			iofree(port);
1388 			continue;
1389 		}
1390 
1391 		/*
1392 		 * 6. Activate the adapter by writing the Activate command
1393 		 *    (0xFF).
1394 		 */
1395 		outb(IDport, 0xFF);
1396 		delay(20);
1397 
1398 		/*
1399 		 * 8. Can now talk to the adapter's I/O base addresses.
1400 		 *    Use the I/O base address from the acr just read.
1401 		 *
1402 		 *    Enable the adapter and clear out any lingering status
1403 		 *    and interrupts.
1404 		 */
1405 		while(STATUS(port) & commandInProgress)
1406 			;
1407 		COMMAND(port, SelectRegisterWindow, Wsetup);
1408 		outs(port+ConfigControl, Ena);
1409 
1410 		txrxreset(port);
1411 		COMMAND(port, AcknowledgeInterrupt, 0xFF);
1412 
1413 		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
1414 		tcmadapter(port, irq, nil);
1415 	}
1416 }
1417 
1418 static void
tcm5XXeisa(void)1419 tcm5XXeisa(void)
1420 {
1421 	ushort x;
1422 	int irq, port, slot;
1423 
1424 	/*
1425 	 * Check if this is an EISA machine.
1426 	 * If not, nothing to do.
1427 	 */
1428 	if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
1429 		return;
1430 
1431 	/*
1432 	 * Continue through the EISA slots looking for a match on both
1433 	 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
1434 	 * If an adapter is found, select window 0, enable it and clear
1435 	 * out any lingering status and interrupts.
1436 	 */
1437 	for(slot = 1; slot < MaxEISA; slot++){
1438 		port = slot*0x1000;
1439 		if(ioalloc(port, 0x1000, 0, "tcm5XXeisa") < 0){
1440 			print("tcm5XXeisa: port 0x%uX in use\n", port);
1441 			continue;
1442 		}
1443 		if(ins(port+0xC80+ManufacturerID) != 0x6D50){
1444 			iofree(port);
1445 			continue;
1446 		}
1447 		x = ins(port+0xC80+ProductID);
1448 		if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900){
1449 			iofree(port);
1450 			continue;
1451 		}
1452 
1453 		COMMAND(port, SelectRegisterWindow, Wsetup);
1454 		outs(port+ConfigControl, Ena);
1455 
1456 		txrxreset(port);
1457 		COMMAND(port, AcknowledgeInterrupt, 0xFF);
1458 
1459 		irq = (ins(port+ResourceConfig)>>12) & 0x0F;
1460 		tcmadapter(port, irq, nil);
1461 	}
1462 }
1463 
1464 static void
tcm59Xpci(void)1465 tcm59Xpci(void)
1466 {
1467 	Pcidev *p;
1468 	Ctlr *ctlr;
1469 	int irq, port;
1470 
1471 	p = nil;
1472 	while(p = pcimatch(p, 0x10B7, 0)){
1473 		if(p->ccrb != 0x02 || p->ccru != 0)
1474 			continue;
1475 		/*
1476 		 * Not prepared to deal with memory-mapped
1477 		 * devices yet.
1478 		 */
1479 		if(!(p->mem[0].bar & 0x01))
1480 			continue;
1481 		port = p->mem[0].bar & ~0x01;
1482 		if((port = ioalloc((port == 0)? -1: port,  p->mem[0].size,
1483 					  0, "tcm59Xpci")) < 0){
1484 			print("tcm59Xpci: port 0x%uX in use\n", port);
1485 			continue;
1486 		}
1487 		irq = p->intl;
1488 
1489 		txrxreset(port);
1490 		COMMAND(port, AcknowledgeInterrupt, 0xFF);
1491 
1492 		ctlr = tcmadapter(port, irq, p);
1493 		switch(p->did){
1494 		default:
1495 			break;
1496 		case 0x5157:
1497 			ctlr->eepromcmd = EepromRead8bRegister;
1498 			ctlr->cbfnpa = p->mem[2].bar&~0x0F;
1499 			ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
1500 			break;
1501 		case 0x6056:
1502 			ctlr->eepromcmd = EepromReadOffRegister;
1503 			ctlr->cbfnpa = p->mem[2].bar&~0x0F;
1504 			ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
1505 			break;
1506 		}
1507 		pcisetbme(p);
1508 	}
1509 }
1510 
1511 static char* tcmpcmcia[] = {
1512 	"3C589",			/* 3COM 589[ABCD] */
1513 	"3C562",			/* 3COM 562 */
1514 	"589E",				/* 3COM Megahertz 589E */
1515 	nil,
1516 };
1517 
1518 static Ctlr*
tcm5XXpcmcia(Ether * ether)1519 tcm5XXpcmcia(Ether* ether)
1520 {
1521 	int i;
1522 	Ctlr *ctlr;
1523 
1524 	if(ether->type == nil)
1525 		return nil;
1526 
1527 	for(i = 0; tcmpcmcia[i] != nil; i++){
1528 		if(cistrcmp(ether->type, tcmpcmcia[i]))
1529 			continue;
1530 		ctlr = tcmadapter(ether->port, ether->irq, nil);
1531 		ctlr->active = 1;
1532 		return ctlr;
1533 	}
1534 
1535 	return nil;
1536 }
1537 
1538 static void
setxcvr(Ctlr * ctlr,int xcvr)1539 setxcvr(Ctlr* ctlr, int xcvr)
1540 {
1541 	int port, x;
1542 
1543 	port = ctlr->port;
1544 	if(ctlr->rxstatus9){
1545 		COMMAND(port, SelectRegisterWindow, Wsetup);
1546 		x = ins(port+AddressConfig) & ~xcvrMask9;
1547 		x |= (xcvr>>20)<<14;
1548 		outs(port+AddressConfig, x);
1549 	}
1550 	else{
1551 		COMMAND(port, SelectRegisterWindow, Wfifo);
1552 		x = inl(port+InternalConfig) & ~xcvrMask;
1553 		x |= xcvr;
1554 		outl(port+InternalConfig, x);
1555 	}
1556 
1557 	txrxreset(port);
1558 }
1559 
1560 static void
setfullduplex(int port)1561 setfullduplex(int port)
1562 {
1563 	int x;
1564 
1565 	COMMAND(port, SelectRegisterWindow, Wfifo);
1566 	x = ins(port+MacControl);
1567 	outs(port+MacControl, fullDuplexEnable|x);
1568 
1569 	txrxreset(port);
1570 }
1571 
1572 static int
miimdi(int port,int n)1573 miimdi(int port, int n)
1574 {
1575 	int data, i;
1576 
1577 	/*
1578 	 * Read n bits from the MII Management Register.
1579 	 */
1580 	data = 0;
1581 	for(i = n-1; i >= 0; i--){
1582 		if(ins(port) & mgmtData)
1583 			data |= (1<<i);
1584 		microdelay(1);
1585 		outs(port, mgmtClk);
1586 		microdelay(1);
1587 		outs(port, 0);
1588 		microdelay(1);
1589 	}
1590 
1591 	return data;
1592 }
1593 
1594 static void
miimdo(int port,int bits,int n)1595 miimdo(int port, int bits, int n)
1596 {
1597 	int i, mdo;
1598 
1599 	/*
1600 	 * Write n bits to the MII Management Register.
1601 	 */
1602 	for(i = n-1; i >= 0; i--){
1603 		if(bits & (1<<i))
1604 			mdo = mgmtDir|mgmtData;
1605 		else
1606 			mdo = mgmtDir;
1607 		outs(port, mdo);
1608 		microdelay(1);
1609 		outs(port, mdo|mgmtClk);
1610 		microdelay(1);
1611 		outs(port, mdo);
1612 		microdelay(1);
1613 	}
1614 }
1615 
1616 static int
miir(int port,int phyad,int regad)1617 miir(int port, int phyad, int regad)
1618 {
1619 	int data, w;
1620 
1621 	w = (STATUS(port)>>13) & 0x07;
1622 	COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1623 	port += PhysicalMgmt;
1624 
1625 	/*
1626 	 * Preamble;
1627 	 * ST+OP+PHYAD+REGAD;
1628 	 * TA + 16 data bits.
1629 	 */
1630 	miimdo(port, 0xFFFFFFFF, 32);
1631 	miimdo(port, 0x1800|(phyad<<5)|regad, 14);
1632 	data = miimdi(port, 18);
1633 
1634 	port -= PhysicalMgmt;
1635 	COMMAND(port, SelectRegisterWindow, w);
1636 
1637 	if(data & 0x10000)
1638 		return -1;
1639 
1640 	return data & 0xFFFF;
1641 }
1642 
1643 static int
scanphy(int port)1644 scanphy(int port)
1645 {
1646 	int i, x;
1647 
1648 	for(i = 0; i < 32; i++){
1649 		if((x = miir(port, i, 2)) == -1 || x == 0)
1650 			continue;
1651 		x <<= 6;
1652 		x |= miir(port, i, 3)>>10;
1653 		XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
1654 		USED(x);
1655 
1656 		return i;
1657 	}
1658 	return 24;
1659 }
1660 
1661 static struct {
1662 	char *name;
1663 	int avail;
1664 	int xcvr;
1665 } media[] = {
1666 	"10BaseT",	base10TAvailable,	xcvr10BaseT,
1667 	"10Base2",	coaxAvailable,		xcvr10Base2,
1668 	"100BaseTX",	baseTXAvailable,	xcvr100BaseTX,
1669 	"100BaseFX",	baseFXAvailable,	xcvr100BaseFX,
1670 	"aui",		auiAvailable,		xcvrAui,
1671 	"mii",		miiConnector,		xcvrMii
1672 };
1673 
1674 static int
autoselect(Ctlr * ctlr)1675 autoselect(Ctlr* ctlr)
1676 {
1677 	int media, port, x;
1678 
1679 	/*
1680 	 * Pathetic attempt at automatic media selection.
1681 	 * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
1682 	 * cards operational.
1683 	 * It's a bonus if it works for anything else.
1684 	 */
1685 	port = ctlr->port;
1686 	if(ctlr->rxstatus9){
1687 		COMMAND(port, SelectRegisterWindow, Wsetup);
1688 		x = ins(port+ConfigControl);
1689 		media = 0;
1690 		if(x & base10TAvailable9)
1691 			media |= base10TAvailable;
1692 		if(x & coaxAvailable9)
1693 			media |= coaxAvailable;
1694 		if(x & auiAvailable9)
1695 			media |= auiAvailable;
1696 	}
1697 	else{
1698 		COMMAND(port, SelectRegisterWindow, Wfifo);
1699 		media = ins(port+ResetOptions);
1700 	}
1701 	XCVRDEBUG("autoselect: media %uX\n", media);
1702 
1703 	if(media & miiConnector)
1704 		return xcvrMii;
1705 
1706 	COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1707 	XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
1708 
1709 	if(media & baseTXAvailable){
1710 		/*
1711 		 * Must have InternalConfig register.
1712 		 */
1713 		setxcvr(ctlr, xcvr100BaseTX);
1714 
1715 		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1716 		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
1717 		outs(port+MediaStatus, linkBeatEnable|x);
1718 		delay(10);
1719 
1720 		if(ins(port+MediaStatus) & linkBeatDetect)
1721 			return xcvr100BaseTX;
1722 		outs(port+MediaStatus, x);
1723 	}
1724 
1725 	if(media & base10TAvailable){
1726 		setxcvr(ctlr, xcvr10BaseT);
1727 
1728 		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1729 		x = ins(port+MediaStatus) & ~dcConverterEnabled;
1730 		outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
1731 		delay(100);
1732 
1733 		XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
1734 		if(ins(port+MediaStatus) & linkBeatDetect)
1735 			return xcvr10BaseT;
1736 		outs(port+MediaStatus, x);
1737 	}
1738 
1739 	/*
1740 	 * Botch.
1741 	 */
1742 	return autoSelect;
1743 }
1744 
1745 static int
eepromdata(Ctlr * ctlr,int offset)1746 eepromdata(Ctlr* ctlr, int offset)
1747 {
1748 	int port;
1749 
1750 	port = ctlr->port;
1751 
1752 	COMMAND(port, SelectRegisterWindow, Wsetup);
1753 	while(EEPROMBUSY(port))
1754 		;
1755 	EEPROMCMD(port, ctlr->eepromcmd, offset);
1756 	while(EEPROMBUSY(port))
1757 		;
1758 	return EEPROMDATA(port);
1759 }
1760 
1761 static void
resetctlr(Ctlr * ctlr)1762 resetctlr(Ctlr *ctlr)
1763 {
1764 	int x, port = ctlr->port;
1765 
1766 	txrxreset(port);
1767 	x = ins(port+ResetOp905B);
1768 	XCVRDEBUG("905[BC] reset ops 0x%uX\n", x);
1769 	x &= ~0x4010;
1770 	if(ctlr->did == 0x5157){
1771 		x |= 0x0010;			/* Invert LED */
1772 		outs(port+ResetOp905B, x);
1773 	}
1774 	if(ctlr->did == 0x6056){
1775 		x |= 0x4000;
1776 		outs(port+ResetOp905B, x);
1777 
1778 		COMMAND(port, SelectRegisterWindow, Wsetup);
1779 		outs(port, 0x0800);
1780 	}
1781 }
1782 
1783 static void
shutdown(Ether * ether)1784 shutdown(Ether *ether)
1785 {
1786 print("etherelnk3 shutting down\n");
1787 	resetctlr(ether->ctlr);
1788 }
1789 
1790 int
etherelnk3reset(Ether * ether)1791 etherelnk3reset(Ether* ether)
1792 {
1793 	char *p;
1794 	Ctlr *ctlr;
1795 	uchar ea[Eaddrlen];
1796 	static int scandone;
1797 	int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x;
1798 
1799 	/*
1800 	 * Scan for adapter on PCI, EISA and finally
1801 	 * using the little ISA configuration dance.
1802 	 */
1803 	if(scandone == 0){
1804 		tcm59Xpci();
1805 		tcm5XXeisa();
1806 		tcm509isa();
1807 		scandone = 1;
1808 	}
1809 
1810 	/*
1811 	 * Any adapter matches if no ether->port is supplied,
1812 	 * otherwise the ports must match.
1813 	 */
1814 	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
1815 		if(ctlr->active)
1816 			continue;
1817 		if(ether->port == 0 || ether->port == ctlr->port){
1818 			ctlr->active = 1;
1819 			break;
1820 		}
1821 	}
1822 	if(ctlr == nil && (ctlr = tcm5XXpcmcia(ether)) == 0)
1823 		return -1;
1824 
1825 	ether->ctlr = ctlr;
1826 	port = ctlr->port;
1827 	ether->port = port;
1828 	ether->irq = ctlr->irq;
1829 	if(ctlr->pcidev != nil)
1830 		ether->tbdf = ctlr->pcidev->tbdf;
1831 	else
1832 		ether->tbdf = BUSUNKNOWN;
1833 
1834 	/*
1835 	 * Read the DeviceID from the EEPROM, it's at offset 0x03,
1836 	 * and do something depending on capabilities.
1837 	 */
1838 	switch(ctlr->did = eepromdata(ctlr, 0x03)){
1839 	case 0x5157:		/* 3C575 Cyclone */
1840 	case 0x6056:
1841 		/*FALLTHROUGH*/
1842 	case 0x4500:		/* 3C450 HomePNA Tornado */
1843 	case 0x7646:		/* 3CSOHO100-TX */
1844 	case 0x9055:		/* 3C905B-TX */
1845 	case 0x9200:		/* 3C905C-TX */
1846 	case 0x9201:		/* 3C920 */
1847 	case 0x9805:		/* 3C9805: 3C980-TX Python-T 10/100baseTX */
1848 		/*FALLTHROUGH*/
1849 	case 0x9000:		/* 3C900-TPO */
1850 	case 0x9001:		/* 3C900-COMBO */
1851 	case 0x9005:		/* 3C900B-COMBO */
1852 	case 0x9050:		/* 3C905-TX */
1853 	case 0x9051:		/* 3C905-T4 */
1854 		if(BUSTYPE(ether->tbdf) != BusPCI)
1855 			goto buggery;
1856 		ctlr->busmaster = 2;
1857 		goto vortex;
1858 	case 0x5900:		/* 3C590-[TP|COMBO|TPO] */
1859 	case 0x5920:		/* 3C592-[TP|COMBO|TPO] */
1860 	case 0x5950:		/* 3C595-TX */
1861 	case 0x5951:		/* 3C595-T4 */
1862 	case 0x5952:		/* 3C595-MII */
1863 	case 0x5970:		/* 3C597-TX */
1864 	case 0x5971:		/* 3C597-T4 */
1865 	case 0x5972:		/* 3C597-MII */
1866 		ctlr->busmaster = 1;
1867 	vortex:
1868 		COMMAND(port, SelectRegisterWindow, Wfifo);
1869 		ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
1870 		ctlr->rxearly = 8188;
1871 		ctlr->rxstatus9 = 0;
1872 		break;
1873 	buggery:
1874 	default:
1875 		ctlr->busmaster = 0;
1876 		COMMAND(port, SelectRegisterWindow, Wsetup);
1877 		x = ins(port+AddressConfig);
1878 		ctlr->xcvr = ((x & xcvrMask9)>>14)<<20;
1879 		if(x & autoSelect9)
1880 			ctlr->xcvr |= autoSelect;
1881 		ctlr->rxearly = 2044;
1882 		ctlr->rxstatus9 = 1;
1883 		break;
1884 	}
1885 	if(ctlr->rxearly >= 2048)
1886 		ctlr->ts = 2;
1887 
1888 	/*
1889 	 * Check if the adapter's station address is to be overridden.
1890 	 * If not, read it from the EEPROM and set in ether->ea prior to
1891 	 * loading the station address in Wstation.
1892 	 * The EEPROM returns 16-bits at a time.
1893 	 */
1894 	memset(ea, 0, Eaddrlen);
1895 	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
1896 		for(i = 0; i < Eaddrlen/2; i++){
1897 			x = eepromdata(ctlr, i);
1898 			ether->ea[2*i] = x>>8;
1899 			ether->ea[2*i+1] = x;
1900 		}
1901 	}
1902 
1903 	COMMAND(port, SelectRegisterWindow, Wstation);
1904 	for(i = 0; i < Eaddrlen; i++)
1905 		outb(port+i, ether->ea[i]);
1906 
1907 	/*
1908 	 * Enable the transceiver if necessary and determine whether
1909 	 * busmastering can be used. Due to bugs in the first revision
1910 	 * of the 3C59[05], don't use busmastering at 10Mbps.
1911 	 */
1912 	XCVRDEBUG("reset: xcvr %uX\n", ctlr->xcvr);
1913 
1914 	/*
1915 	 * Allow user to specify desired media in plan9.ini
1916 	 */
1917 	for(i = 0; i < ether->nopt; i++){
1918 		if(cistrncmp(ether->opt[i], "media=", 6) != 0)
1919 			continue;
1920 		p = ether->opt[i]+6;
1921 		for(j = 0; j < nelem(media); j++)
1922 			if(cistrcmp(p, media[j].name) == 0)
1923 				ctlr->xcvr = media[j].xcvr;
1924 	}
1925 
1926 	/*
1927 	 * forgive me, but i am weak
1928 	 */
1929 	switch(ctlr->did){
1930 	default:
1931 		if(ctlr->xcvr & autoSelect)
1932 			ctlr->xcvr = autoselect(ctlr);
1933 		break;
1934 	case 0x5157:
1935 	case 0x6056:
1936 	case 0x4500:
1937 	case 0x7646:
1938 	case 0x9055:
1939 	case 0x9200:
1940 	case 0x9201:
1941 	case 0x9805:
1942 		ctlr->xcvr = xcvrMii;
1943 		resetctlr(ctlr);
1944 		break;
1945 	}
1946 	XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did);
1947 
1948 	switch(ctlr->xcvr){
1949 	case xcvrMii:
1950 		/*
1951 		 * Quick hack.
1952 		 */
1953 		if(ctlr->did == 0x5157)
1954 			phyaddr = 0;
1955 		else if(ctlr->did == 0x6056)
1956 			phyaddr = scanphy(port);
1957 		else
1958 			phyaddr = 24;
1959 		for(i = 0; i < 7; i++)
1960 			XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
1961 			XCVRDEBUG("\n");
1962 
1963 		for(timeo = 0; timeo < 30; timeo++){
1964 			phystat = miir(port, phyaddr, 0x01);
1965 			if(phystat & 0x20)
1966 				break;
1967 			XCVRDEBUG(" %2.2uX", phystat);
1968 			delay(100);
1969 		}
1970 		XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
1971 		XCVRDEBUG("\n");
1972 
1973 		anar = miir(port, phyaddr, 0x04);
1974 		anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
1975 		anar &= anlpar;
1976 		miir(port, phyaddr, 0x00);
1977 		XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
1978 			anar, anlpar, miir(port, phyaddr, 0x00),
1979 			miir(port, phyaddr, 0x01));
1980 		for(i = 0; i < ether->nopt; i++){
1981 			if(cistrcmp(ether->opt[i], "fullduplex") == 0)
1982 				anar |= 0x0100;
1983 			else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
1984 				anar |= 0x0100;
1985 			else if(cistrcmp(ether->opt[i], "force100") == 0)
1986 				anar |= 0x0080;
1987 		}
1988 		XCVRDEBUG("mii anar: %uX\n", anar);
1989 		if(anar & 0x0100){		/* 100BASE-TXFD */
1990 			ether->mbps = 100;
1991 			setfullduplex(port);
1992 		}
1993 		else if(anar & 0x0200){		/* 100BASE-T4 */
1994 			/* nothing to do */
1995 		}
1996 		else if(anar & 0x0080)		/* 100BASE-TX */
1997 			ether->mbps = 100;
1998 		else if(anar & 0x0040)		/* 10BASE-TFD */
1999 			setfullduplex(port);
2000 		else{				/* 10BASE-T */
2001 			/* nothing to do */
2002 		}
2003 		break;
2004 	case xcvr100BaseTX:
2005 	case xcvr100BaseFX:
2006 		COMMAND(port, SelectRegisterWindow, Wfifo);
2007 		x = inl(port+InternalConfig) & ~ramPartitionMask;
2008 		outl(port+InternalConfig, x|ramPartition1to1);
2009 
2010 		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2011 		x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
2012 		x |= linkBeatEnable;
2013 		outs(port+MediaStatus, x);
2014 
2015 		if(x & dataRate100)
2016 			ether->mbps = 100;
2017 		break;
2018 	case xcvr10BaseT:
2019 		/*
2020 		 * Enable Link Beat and Jabber to start the
2021 		 * transceiver.
2022 		 */
2023 		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2024 		x = ins(port+MediaStatus) & ~dcConverterEnabled;
2025 		x |= linkBeatEnable|jabberGuardEnable;
2026 		outs(port+MediaStatus, x);
2027 
2028 		if((ctlr->did & 0xFF00) == 0x5900)
2029 			ctlr->busmaster = 0;
2030 		break;
2031 	case xcvr10Base2:
2032 		COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2033 		x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
2034 		outs(port+MediaStatus, x);
2035 
2036 		/*
2037 		 * Start the DC-DC converter.
2038 		 * Wait > 800 microseconds.
2039 		 */
2040 		COMMAND(port, EnableDcConverter, 0);
2041 		delay(1);
2042 		break;
2043 	}
2044 
2045 	/*
2046 	 * Wop is the normal operating register set.
2047 	 * The 3C59[0257] adapters allow access to more than one register window
2048 	 * at a time, but there are situations where switching still needs to be
2049 	 * done, so just do it.
2050 	 * Clear out any lingering Tx status.
2051 	 */
2052 	COMMAND(port, SelectRegisterWindow, Wop);
2053 	if(ctlr->busmaster == 2)
2054 		x = port+TxStatus905;
2055 	else
2056 		x = port+TxStatus;
2057 	while(inb(x))
2058 		outb(x, 0);
2059 
2060 	/*
2061 	 * Clear out the
2062 	 * adapter statistics, clear the statistics logged into ctlr
2063 	 * and enable statistics collection.
2064 	 */
2065 	ilock(&ctlr->wlock);
2066 	statistics(ether);
2067 	memset(ctlr->stats, 0, sizeof(ctlr->stats));
2068 
2069 	COMMAND(port, StatisticsEnable, 0);
2070 
2071 	/*
2072 	 * Allocate any receive buffers.
2073 	 */
2074 	switch(ctlr->busmaster){
2075 	case 2:
2076 		ctlr->dnenabled = 1;
2077 
2078 		/*
2079 		 * 10MUpldBug.
2080 		 * Disabling is too severe, can use receive busmastering at
2081 		 * 100Mbps OK, but how to tell which rate is actually being used -
2082 		 * the 3c905 always seems to have dataRate100 set?
2083 		 * Believe the bug doesn't apply if upRxEarlyEnable is set
2084 		 * and the threshold is set such that uploads won't start
2085 		 * until the whole packet has been received.
2086 		 */
2087 		ctlr->upenabled = 1;
2088 		x = eepromdata(ctlr, 0x0F);
2089 		if(!(x & 0x01))
2090 			outl(port+PktStatus, upRxEarlyEnable);
2091 
2092 		if(ctlr->upenabled || ctlr->dnenabled){
2093 			ctlr->nup = Nup;
2094 			ctlr->ndn = Ndn;
2095 			init905(ctlr);
2096 		}
2097 		else {
2098 			ctlr->rbp = rbpalloc(iallocb);
2099 			if(ctlr->rbp == nil)
2100 				panic("can't reset ethernet: out of memory");
2101 		}
2102 		outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
2103 		break;
2104 	default:
2105 		ctlr->rbp = rbpalloc(iallocb);
2106 		if(ctlr->rbp == nil)
2107 			panic("can't reset ethernet: out of memory");
2108 		break;
2109 	}
2110 
2111 	/*
2112 	 * Set a base TxStartThresh which will be incremented
2113 	 * if any txUnderrun errors occur and ensure no RxEarly
2114 	 * interrupts happen.
2115 	 */
2116 	ctlr->txthreshold = ETHERMAXTU/2;
2117 	COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
2118 	COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
2119 
2120 	iunlock(&ctlr->wlock);
2121 
2122 	/*
2123 	 * Linkage to the generic ethernet driver.
2124 	 */
2125 	ether->attach = attach;
2126 	ether->transmit = transmit;
2127 	ether->interrupt = interrupt;
2128 	ether->ifstat = ifstat;
2129 
2130 	ether->promiscuous = promiscuous;
2131 	ether->multicast = multicast;
2132 	ether->shutdown = shutdown;
2133 	ether->arg = ether;
2134 
2135 	return 0;
2136 }
2137 
2138 void
etherelnk3link(void)2139 etherelnk3link(void)
2140 {
2141 	addethercard("elnk3", etherelnk3reset);
2142 	addethercard("3C509", etherelnk3reset);
2143 	addethercard("3C575", etherelnk3reset);
2144 }
2145