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