2 * Etherlink III, Fast EtherLink and Fast EtherLink XL adapters.
4 * check robustness in the face of errors (e.g. busmaster & rxUnderrun);
5 * RxEarly and busmaster;
7 * PCI latency timer and master enable;
9 * rewrite all initialisation.
12 #include "../port/lib.h"
17 #include "../port/error.h"
18 #include "../port/netif.h"
22 #define XCVRDEBUG if(0)print
25 IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
28 enum { /* all windows */
35 SelectRegisterWindow = 0x0001,
36 EnableDcConverter = 0x0002,
40 Stall = 0x0006, /* 3C90x */
46 RequestInterrupt = 0x000C,
47 AcknowledgeInterrupt = 0x000D,
48 SetInterruptEnable = 0x000E,
49 SetIndicationEnable = 0x000F, /* SetReadZeroMask */
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 */
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 */
78 enum { /* Stall command bits */
85 enum { /* SetRxFilter command bits */
86 receiveIndividual = 0x0001, /* match station address */
87 receiveMulticast = 0x0002,
88 receiveBroadcast = 0x0004,
89 receiveAllFrames = 0x0008, /* promiscuous */
92 enum { /* StartDma command bits */
93 Upload = 0x0000, /* transfer data from adapter to memory */
94 Download = 0x0001, /* transfer data from memory to adapter */
97 enum { /* IntStatus bits */
98 interruptLatch = 0x0001,
99 hostError = 0x0002, /* Adapter Failure */
101 txAvailable = 0x0008,
104 intRequested = 0x0040,
105 updateStats = 0x0080,
106 transferInt = 0x0100, /* Bus Master Transfer Complete */
109 busMasterInProgress = 0x0800,
110 commandInProgress = 0x1000,
112 interruptMask = 0x07FE,
115 #define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
116 #define STATUS(port) ins((port)+IntStatusR)
118 enum { /* Window 0 - setup */
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,
128 /* AddressConfig Bits */
129 autoSelect9 = 0x0080,
131 /* ConfigControl bits */
133 base10TAvailable9 = 0x0200,
134 coaxAvailable9 = 0x1000,
135 auiAvailable9 = 0x2000,
136 /* EepromCommand bits */
137 EepromReadRegister = 0x0080,
138 EepromReadOffRegister = 0x00B0,
139 EepromRead8bRegister = 0x0230,
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)
147 enum { /* Window 1 - operating set */
151 RxError = 0x0004, /* 3C59[0257] only */
159 alignmentError = 0x0004, /* Framing */
161 oversizedFrame = 0x0010,
162 dribbleBits = 0x0080,
164 rxBytes = 0x1FFF, /* 3C59[0257] mask */
165 rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
166 rxError9 = 0x3800, /* 3C5[078]9 error mask */
168 oversizedFrame9 = 0x0800,
169 dribbleBits9 = 0x1000,
171 alignmentError9 = 0x2000, /* Framing */
174 rxIncomplete = 0x8000,
176 txStatusOverflow = 0x0004,
177 maxCollisions = 0x0008,
180 interruptRequested = 0x0040,
181 txStatusComplete = 0x0080,
184 enum { /* Window 2 - station address */
187 ResetOp905B = 0x000C,
190 enum { /* Window 3 - FIFO management */
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 */
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,
234 enum { /* Window 4 - diagnostic */
235 Wdiagnostic = 0x0004,
237 VcoDiagnostic = 0x0002,
238 FifoDiagnostic = 0x0004,
239 NetworkDiagnostic = 0x0006,
240 PhysicalMgmt = 0x0008,
241 MediaStatus = 0x000A,
243 UpperBytesOk = 0x000D,
244 /* FifoDiagnostic bits */
248 /* PhysicalMgmt bits */
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,
265 dcConverterEnabled = 0x4000,
266 auiDisable = 0x8000, /* 10BaseT transceiver selected */
269 enum { /* Window 5 - internal state */
272 TxStartThresh = 0x0000,
273 TxAvailableThresh = 0x0002,
274 RxEarlyThresh = 0x0006,
276 InterruptEnable = 0x000A,
277 IndicationEnable = 0x000C,
280 enum { /* Window 6 - statistics */
281 Wstatistics = 0x0006,
283 CarrierLost = 0x0000,
285 MultipleColls = 0x0002,
286 SingleCollFrames = 0x0003,
287 LateCollisions = 0x0004,
289 FramesXmittedOk = 0x0006,
290 FramesRcvdOk = 0x0007,
291 FramesDeferred = 0x0008,
292 UpperFramesOk = 0x0009,
293 BytesRcvdOk = 0x000A,
294 BytesXmittedOk = 0x000C,
297 enum { /* Window 7 - bus master operations */
300 MasterAddress = 0x0000,
302 MasterStatus = 0x000C,
303 /* MasterStatus bits */
304 masterAbort = 0x0001,
305 targetAbort = 0x0002,
306 targetRetry = 0x0004,
308 masterDownload = 0x1000,
309 masterUpload = 0x4000,
310 masterInProgress = 0x8000,
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 */
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,
352 dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */
354 updnLastFrag = 0x80000000, /* (dpd->len) */
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.
365 typedef struct Pd Pd;
367 ulong np; /* next pointer */
368 ulong control; /* FSH or UpPktStatus */
376 typedef struct Ctlr Ctlr;
377 typedef struct Ctlr {
385 Lock wlock; /* window access */
389 Block* rbp; /* receive buffer */
391 Block* txbp; /* FIFO -based transmission */
395 int nup; /* full-busmaster -based reception */
400 int ndn; /* full-busmaster -based transmission */
407 long interrupts; /* statistics */
408 long bogusinterrupts;
410 long stats[BytesRcvdOk+3];
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 */
429 ulong cbfnpa; /* CardBus functions */
433 static Ctlr* ctlrhead;
434 static Ctlr* ctlrtail;
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.
448 ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
449 ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
452 for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
453 pd->np = PADDR(&prev->np);
455 bp = iallocb(sizeof(Etherpkt));
457 panic("can't allocate ethernet receive ring");
458 pd->addr = PADDR(bp->rp);
459 pd->len = updnLastFrag|sizeof(Etherpkt);
465 ctlr->uphead = ctlr->upr;
467 ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
468 ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
471 for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
475 ctlr->dnhead = ctlr->dnr;
476 ctlr->dntail = ctlr->dnr;
481 rbpalloc(Block* (*f)(int))
487 * The receive buffers must be on a 32-byte
488 * boundary for EISA busmastering.
490 if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
491 addr = (ulong)bp->base;
492 addr = ROUNDUP(addr, 32);
493 bp->rp = (uchar*)addr;
500 startdma(Ether* ether, ulong address)
507 w = (STATUS(port)>>13) & 0x07;
508 COMMAND(port, SelectRegisterWindow, Wmaster);
510 wp = KADDR(inl(port+MasterAddress));
511 status = ins(port+MasterStatus);
512 if(status & (masterInProgress|targetAbort|masterAbort))
513 print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
514 outs(port+MasterStatus, masterMask);
515 outl(port+MasterAddress, address);
516 outs(port+MasterLen, sizeof(Etherpkt));
517 COMMAND(port, StartDma, Upload);
519 COMMAND(port, SelectRegisterWindow, w);
524 promiscuous(void* arg, int on)
532 filter = receiveBroadcast|receiveIndividual;
534 filter |= receiveMulticast;
536 filter |= receiveAllFrames;
537 COMMAND(port, SetRxFilter, filter);
541 multicast(void* arg, uchar *addr, int on)
551 filter = receiveBroadcast|receiveIndividual;
553 filter |= receiveMulticast;
555 filter |= receiveAllFrames;
556 COMMAND(port, SetRxFilter, filter);
559 /* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
561 intrackcb(ulong *cbfn)
575 iunlock(&ctlr->wlock);
582 * Set the receiver packet filter for this and broadcast addresses,
583 * set the interrupt masks for all interrupts, enable the receiver
586 promiscuous(ether, ether->prom);
589 if(ctlr->busmaster == 1)
590 x &= ~(rxEarly|rxComplete);
595 x &= ~(rxEarly|rxComplete);
597 COMMAND(port, SetIndicationEnable, x);
598 COMMAND(port, SetInterruptEnable, x);
599 COMMAND(port, RxEnable, 0);
600 COMMAND(port, TxEnable, 0);
603 * If this is a CardBus card, acknowledge any interrupts.
605 if(ctlr->cbfn != nil)
606 intrackcb(ctlr->cbfn);
609 * Prime the busmaster channel for receiving directly into a
610 * receive packet buffer if necessary.
612 if(ctlr->busmaster == 1)
613 startdma(ether, PADDR(ctlr->rbp->rp));
616 outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
620 iunlock(&ctlr->wlock);
624 statistics(Ether* ether)
633 * 3C59[27] require a read between a PIO write and
634 * reading a statistics register.
636 w = (STATUS(port)>>13) & 0x07;
637 COMMAND(port, SelectRegisterWindow, Wstatistics);
640 for(i = 0; i < UpperFramesOk; i++)
641 ctlr->stats[i] += inb(port+i) & 0xFF;
642 u = inb(port+UpperFramesOk) & 0xFF;
643 ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
644 ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
645 ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
646 ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
653 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
655 ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
659 COMMAND(port, SelectRegisterWindow, w);
663 txstart(Ether* ether)
673 * Attempt to top-up the transmit FIFO. If there's room simply
674 * stuff in the packet length (unpadded to a dword boundary), the
675 * packet data (padded) and remove the packet from the queue.
676 * If there's no room post an interrupt for when there is.
677 * This routine is called both from the top level and from interrupt
678 * level and expects to be called with ctlr->wlock already locked
679 * and the correct register window (Wop) in place.
687 bp = qget(ether->oq);
692 len = ROUNDUP(BLEN(bp), 4);
693 if(len+4 <= ins(port+TxFree)){
694 outl(port+Fifo, BLEN(bp));
695 outsl(port+Fifo, bp->rp, len/4);
703 if(ctlr->txbusy == 0){
705 COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
713 txstart905(Ether* ether)
716 int port, stalled, timeo;
724 * Free any completed packets.
728 if(PADDR(&pd->np) == inl(port+DnListPtr))
740 while(ctlr->dnq < (ctlr->ndn-1)){
741 bp = qget(ether->oq);
745 pd = ctlr->dnhead->next;
747 pd->control = dnIndicate|BLEN(bp);
748 pd->addr = PADDR(bp->rp);
749 pd->len = updnLastFrag|BLEN(bp);
752 if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
753 COMMAND(port, Stall, dnStall);
754 for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
757 print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
762 ctlr->dnhead->np = PADDR(&pd->np);
763 ctlr->dnhead->control &= ~dnIndicate;
772 if(ctlr->dnq > ctlr->dnqmax)
773 ctlr->dnqmax = ctlr->dnq;
776 * If the adapter is not currently processing anything
777 * and there is something on the queue, start it processing.
779 if(inl(port+DnListPtr) == 0 && ctlr->dnq)
780 outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
782 COMMAND(port, Stall, dnUnStall);
786 transmit(Ether* ether)
798 w = (STATUS(port)>>13) & 0x07;
799 COMMAND(port, SelectRegisterWindow, Wop);
801 COMMAND(port, SelectRegisterWindow, w);
803 iunlock(&ctlr->wlock);
807 receive905(Ether* ether)
817 if(inl(port+UpPktStatus) & upStalled)
820 for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
821 if(pd->control & upError){
822 if(pd->control & upOverrun)
824 if(pd->control & (upOversizedFrame|upRuntFrame))
826 if(pd->control & upAlignmentError)
828 if(pd->control & upCRCError)
831 else if(bp = iallocb(sizeof(Etherpkt)+4)){
832 len = pd->control & rxBytes;
833 pd->bp->wp = pd->bp->rp+len;
834 etheriq(ether, pd->bp, 1);
836 pd->addr = PADDR(bp->rp);
841 COMMAND(port, Stall, upUnStall);
853 receive(Ether* ether)
855 int len, port, rxerror, rxstatus;
862 while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
863 if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
867 * If there was an error, log it and continue.
868 * Unfortunately the 3C5[078]9 has the error info in the status register
869 * and the 3C59[0257] implement a separate RxError register.
871 if(rxstatus & rxError){
873 switch(rxstatus & rxError9){
879 case oversizedFrame9:
884 case alignmentError9:
895 rxerror = inb(port+RxError);
896 if(rxerror & rxOverrun)
898 if(rxerror & (oversizedFrame|runtFrame))
900 if(rxerror & alignmentError)
902 if(rxerror & crcError)
908 * If there was an error or a new receive buffer can't be
909 * allocated, discard the packet and go on to the next.
911 if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){
912 COMMAND(port, RxDiscard, 0);
913 while(STATUS(port) & commandInProgress)
916 if(ctlr->busmaster == 1)
917 startdma(ether, PADDR(ctlr->rbp->rp));
923 * A valid receive packet awaits:
924 * if using PIO, read it into the buffer;
925 * discard the packet from the FIFO;
926 * if using busmastering, start a new transfer for
927 * the next packet and as a side-effect get the
928 * end-pointer of the one just received;
929 * pass the packet on to whoever wants it.
931 if(ctlr->busmaster == 0 || ctlr->busmaster == 2){
932 len = (rxstatus & rxBytes9);
933 ctlr->rbp->wp = ctlr->rbp->rp + len;
934 insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4));
937 COMMAND(port, RxDiscard, 0);
938 while(STATUS(port) & commandInProgress)
941 if(ctlr->busmaster == 1)
942 ctlr->rbp->wp = startdma(ether, PADDR(bp->rp));
944 etheriq(ether, ctlr->rbp, 1);
962 interrupt(Ureg*, void* arg)
965 int port, status, s, txstatus, w, x;
973 status = STATUS(port);
974 if(!(status & (interruptMask|interruptLatch))){
975 ctlr->bogusinterrupts++;
976 iunlock(&ctlr->wlock);
979 w = (status>>13) & 0x07;
980 COMMAND(port, SelectRegisterWindow, Wop);
983 if(ctlr->busmaster == 2)
984 ctlr->timer[0] += inb(port+TIMER905) & 0xFF;
986 ctlr->timer[0] += inb(port+TIMER) & 0xFF;
989 if(status & hostError){
991 * Adapter failure, try to find out why, reset if
992 * necessary. What happens if Tx is active and a reset
993 * occurs, need to retransmit? This probably isn't right.
995 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
996 x = ins(port+FifoDiagnostic);
997 COMMAND(port, SelectRegisterWindow, Wop);
999 if (status == 0xFFFF && x == 0xFFFF && ejectable(ctlr->did)) {
1000 print("#l%d: Card ejected?\n", ether->ctlrno);
1001 iunlock(&ctlr->wlock);
1005 print("#l%d: status 0x%uX, diag 0x%uX\n",
1006 ether->ctlrno, status, x);
1009 if(ctlr->busmaster == 0)
1010 COMMAND(port, TxReset, 0);
1012 COMMAND(port, TxReset, (updnReset|dmaReset));
1013 COMMAND(port, TxEnable, 0);
1018 * This shouldn't happen...
1019 * Reset the receiver and restore the filter and RxEarly
1020 * threshold before re-enabling.
1021 * Need to restart any busmastering?
1023 COMMAND(port, SelectRegisterWindow, Wstate);
1024 s = (port+RxFilter) & 0x000F;
1025 COMMAND(port, SelectRegisterWindow, Wop);
1026 COMMAND(port, RxReset, 0);
1027 while(STATUS(port) & commandInProgress)
1029 COMMAND(port, SetRxFilter, s);
1030 COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
1031 COMMAND(port, RxEnable, 0);
1034 status &= ~hostError;
1037 if(status & (transferInt|rxComplete)){
1039 status &= ~(transferInt|rxComplete);
1042 if(status & (upComplete)){
1043 COMMAND(port, AcknowledgeInterrupt, upComplete);
1045 status &= ~upComplete;
1046 ctlr->upinterrupts++;
1049 if(status & txComplete){
1051 * Pop the TxStatus stack, accumulating errors.
1052 * Adjust the TX start threshold if there was an underrun.
1053 * If there was a Jabber or Underrun error, reset
1054 * the transmitter, taking care not to reset the dma logic
1055 * as a busmaster receive may be in progress.
1056 * For all conditions enable the transmitter.
1058 if(ctlr->busmaster == 2)
1059 txstatus = port+TxStatus905;
1061 txstatus = port+TxStatus;
1064 if(x = inb(txstatus))
1067 }while(STATUS(port) & txComplete);
1070 if(ctlr->dnenabled){
1071 while(inl(port+PktStatus) & dnInProg)
1074 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1075 while(ins(port+MediaStatus) & txInProg)
1077 COMMAND(port, SelectRegisterWindow, Wop);
1078 if(ctlr->txthreshold < ETHERMAXTU)
1079 ctlr->txthreshold += ETHERMINTU;
1083 * According to the manual, maxCollisions does not require
1084 * a TxReset, merely a TxEnable. However, evidence points to
1085 * it being necessary on the 3C905. The jury is still out.
1086 * On busy or badly configured networks maxCollisions can
1087 * happen frequently enough for messages to be annoying so
1088 * keep quiet about them by popular request.
1090 if(s & (txJabber|txUnderrun|maxCollisions)){
1091 if(ctlr->busmaster == 0)
1092 COMMAND(port, TxReset, 0);
1094 COMMAND(port, TxReset, (updnReset|dmaReset));
1095 while(STATUS(port) & commandInProgress)
1097 COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
1098 if(ctlr->busmaster == 2)
1099 outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
1101 status |= dnComplete;
1104 if(s & ~(txStatusComplete|maxCollisions))
1105 print("#l%d: txstatus 0x%uX, threshold %d\n",
1106 ether->ctlrno, s, ctlr->txthreshold);
1107 COMMAND(port, TxEnable, 0);
1109 status &= ~txComplete;
1110 status |= txAvailable;
1113 if(status & txAvailable){
1114 COMMAND(port, AcknowledgeInterrupt, txAvailable);
1117 status &= ~txAvailable;
1120 if(status & dnComplete){
1121 COMMAND(port, AcknowledgeInterrupt, dnComplete);
1123 status &= ~dnComplete;
1124 ctlr->dninterrupts++;
1127 if(status & updateStats){
1129 status &= ~updateStats;
1133 * Currently, this shouldn't happen.
1135 if(status & rxEarly){
1136 COMMAND(port, AcknowledgeInterrupt, rxEarly);
1141 * Panic if there are any interrupts not dealt with.
1143 if(status & interruptMask)
1144 panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
1146 COMMAND(port, AcknowledgeInterrupt, interruptLatch);
1147 if(ctlr->cbfn != nil)
1148 intrackcb(ctlr->cbfn);
1150 }while((status = STATUS(port)) & (interruptMask|interruptLatch));
1152 if(ctlr->busmaster == 2)
1153 ctlr->timer[1] += inb(port+TIMER905) & 0xFF;
1155 ctlr->timer[1] += inb(port+TIMER) & 0xFF;
1157 COMMAND(port, SelectRegisterWindow, w);
1158 iunlock(&ctlr->wlock);
1162 ifstat(Ether* ether, void* a, long n, ulong offset)
1173 ilock(&ctlr->wlock);
1175 iunlock(&ctlr->wlock);
1177 p = malloc(READSTR);
1178 len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
1179 len += snprint(p+len, READSTR-len, "bogusinterrupts: %lud\n", ctlr->bogusinterrupts);
1180 len += snprint(p+len, READSTR-len, "timer: %lud %lud\n",
1181 ctlr->timer[0], ctlr->timer[1]);
1182 len += snprint(p+len, READSTR-len, "carrierlost: %lud\n",
1183 ctlr->stats[CarrierLost]);
1184 len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n",
1185 ctlr->stats[SqeErrors]);
1186 len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n",
1187 ctlr->stats[MultipleColls]);
1188 len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n",
1189 ctlr->stats[SingleCollFrames]);
1190 len += snprint(p+len, READSTR-len, "latecollisions: %lud\n",
1191 ctlr->stats[LateCollisions]);
1192 len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n",
1193 ctlr->stats[RxOverruns]);
1194 len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n",
1195 ctlr->stats[FramesXmittedOk]);
1196 len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n",
1197 ctlr->stats[FramesRcvdOk]);
1198 len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n",
1199 ctlr->stats[FramesDeferred]);
1200 len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n",
1201 ctlr->stats[BytesRcvdOk]);
1202 len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n",
1203 ctlr->stats[BytesRcvdOk+1]);
1205 if(ctlr->upenabled){
1206 if(ctlr->upqmax > ctlr->upqmaxhw)
1207 ctlr->upqmaxhw = ctlr->upqmax;
1208 len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d h %d s %lud\n",
1209 ctlr->upqueued, ctlr->upinterrupts,
1210 ctlr->upqmax, ctlr->upqmaxhw, ctlr->upstalls);
1213 if(ctlr->dnenabled){
1214 if(ctlr->dnqmax > ctlr->dnqmaxhw)
1215 ctlr->dnqmaxhw = ctlr->dnqmax;
1216 len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d h %d\n",
1217 ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax, ctlr->dnqmaxhw);
1221 snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]);
1223 n = readstr(offset, a, n, p);
1232 COMMAND(port, TxReset, 0);
1233 while(STATUS(port) & commandInProgress)
1235 COMMAND(port, RxReset, 0);
1236 while(STATUS(port) & commandInProgress)
1241 tcmadapter(int port, int irq, Pcidev* pcidev)
1245 ctlr = malloc(sizeof(Ctlr));
1248 ctlr->pcidev = pcidev;
1249 ctlr->eepromcmd = EepromReadRegister;
1252 ctlrtail->next = ctlr;
1261 * Write two 0 bytes to identify the IDport and then reset the
1262 * ID sequence. Then send the ID sequence to the card to get
1263 * the card into command state.
1270 static int reset, untag;
1274 * reset any adapters listening
1286 for(al = 0xFF, i = 0; i < 255; i++){
1298 * write ID sequence to get the attention of all adapters;
1299 * untag all adapters.
1300 * If a global reset is done here on all adapters it will confuse
1301 * any ISA cards configured for EISA mode.
1316 * Do the little configuration dance:
1318 * 2. write the ID sequence to get to command state.
1323 * 3. Read the Manufacturer ID from the EEPROM.
1324 * This is done by writing the IDPort with 0x87 (0x80
1325 * is the 'read EEPROM' command, 0x07 is the offset of
1326 * the Manufacturer ID field in the EEPROM).
1327 * The data comes back 1 bit at a time.
1328 * A delay seems necessary between reading the bits.
1330 * If the ID doesn't match, there are no more adapters.
1334 for(x = 0, i = 0; i < 16; i++){
1337 x |= inb(IDport) & 0x01;
1343 * 3. Read the Address Configuration from the EEPROM.
1344 * The Address Configuration field is at offset 0x08 in the EEPROM).
1347 for(acr = 0, i = 0; i < 16; i++){
1350 acr |= inb(IDport) & 0x01;
1353 return (acr & 0x1F)*0x10 + 0x200;
1362 * Attempt to activate all adapters. If adapter is set for
1363 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
1366 while(port = activate()){
1367 if(ioalloc(port, 0x10, 0, "tcm509isa") < 0){
1368 print("tcm509isa: port 0x%uX in use\n", port);
1373 * 6. Tag the adapter so it won't respond in future.
1382 * 6. Activate the adapter by writing the Activate command
1389 * 8. Can now talk to the adapter's I/O base addresses.
1390 * Use the I/O base address from the acr just read.
1392 * Enable the adapter and clear out any lingering status
1395 while(STATUS(port) & commandInProgress)
1397 COMMAND(port, SelectRegisterWindow, Wsetup);
1398 outs(port+ConfigControl, Ena);
1401 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1403 irq = (ins(port+ResourceConfig)>>12) & 0x0F;
1404 tcmadapter(port, irq, nil);
1412 int irq, port, slot;
1415 * Check if this is an EISA machine.
1416 * If not, nothing to do.
1418 if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
1422 * Continue through the EISA slots looking for a match on both
1423 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
1424 * If an adapter is found, select window 0, enable it and clear
1425 * out any lingering status and interrupts.
1427 for(slot = 1; slot < MaxEISA; slot++){
1429 if(ioalloc(port, 0x1000, 0, "tcm5XXeisa") < 0){
1430 print("tcm5XXeisa: port 0x%uX in use\n", port);
1433 if(ins(port+0xC80+ManufacturerID) != 0x6D50){
1437 x = ins(port+0xC80+ProductID);
1438 if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900){
1443 COMMAND(port, SelectRegisterWindow, Wsetup);
1444 outs(port+ConfigControl, Ena);
1447 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1449 irq = (ins(port+ResourceConfig)>>12) & 0x0F;
1450 tcmadapter(port, irq, nil);
1462 while(p = pcimatch(p, 0x10B7, 0)){
1463 if(p->ccrb != 0x02 || p->ccru != 0)
1466 * Not prepared to deal with memory-mapped
1469 if(!(p->mem[0].bar & 0x01))
1471 port = p->mem[0].bar & ~0x01;
1472 if((port = ioalloc((port == 0)? -1: port, p->mem[0].size,
1473 0, "tcm59Xpci")) < 0){
1474 print("tcm59Xpci: port 0x%uX in use\n", port);
1480 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1482 ctlr = tcmadapter(port, irq, p);
1487 ctlr->eepromcmd = EepromRead8bRegister;
1488 ctlr->cbfnpa = p->mem[2].bar&~0x0F;
1489 ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
1492 ctlr->eepromcmd = EepromReadOffRegister;
1493 ctlr->cbfnpa = p->mem[2].bar&~0x0F;
1494 ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
1501 static char* tcmpcmcia[] = {
1502 "3C589", /* 3COM 589[ABCD] */
1503 "3C562", /* 3COM 562 */
1504 "589E", /* 3COM Megahertz 589E */
1509 tcm5XXpcmcia(Ether* ether)
1514 if(ether->type == nil)
1517 for(i = 0; tcmpcmcia[i] != nil; i++){
1518 if(cistrcmp(ether->type, tcmpcmcia[i]))
1520 ctlr = tcmadapter(ether->port, ether->irq, nil);
1529 setxcvr(Ctlr* ctlr, int xcvr)
1534 if(ctlr->rxstatus9){
1535 COMMAND(port, SelectRegisterWindow, Wsetup);
1536 x = ins(port+AddressConfig) & ~xcvrMask9;
1537 x |= (xcvr>>20)<<14;
1538 outs(port+AddressConfig, x);
1541 COMMAND(port, SelectRegisterWindow, Wfifo);
1542 x = inl(port+InternalConfig) & ~xcvrMask;
1544 outl(port+InternalConfig, x);
1551 setfullduplex(int port)
1555 COMMAND(port, SelectRegisterWindow, Wfifo);
1556 x = ins(port+MacControl);
1557 outs(port+MacControl, fullDuplexEnable|x);
1563 miimdi(int port, int n)
1568 * Read n bits from the MII Management Register.
1571 for(i = n-1; i >= 0; i--){
1572 if(ins(port) & mgmtData)
1575 outs(port, mgmtClk);
1585 miimdo(int port, int bits, int n)
1590 * Write n bits to the MII Management Register.
1592 for(i = n-1; i >= 0; i--){
1594 mdo = mgmtDir|mgmtData;
1599 outs(port, mdo|mgmtClk);
1607 miir(int port, int phyad, int regad)
1611 w = (STATUS(port)>>13) & 0x07;
1612 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1613 port += PhysicalMgmt;
1617 * ST+OP+PHYAD+REGAD;
1618 * TA + 16 data bits.
1620 miimdo(port, 0xFFFFFFFF, 32);
1621 miimdo(port, 0x1800|(phyad<<5)|regad, 14);
1622 data = miimdi(port, 18);
1624 port -= PhysicalMgmt;
1625 COMMAND(port, SelectRegisterWindow, w);
1630 return data & 0xFFFF;
1638 for(i = 0; i < 32; i++){
1639 if((x = miir(port, i, 2)) == -1 || x == 0)
1642 x |= miir(port, i, 3)>>10;
1643 XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
1656 "10BaseT", base10TAvailable, xcvr10BaseT,
1657 "10Base2", coaxAvailable, xcvr10Base2,
1658 "100BaseTX", baseTXAvailable, xcvr100BaseTX,
1659 "100BaseFX", baseFXAvailable, xcvr100BaseFX,
1660 "aui", auiAvailable, xcvrAui,
1661 "mii", miiConnector, xcvrMii
1665 autoselect(Ctlr* ctlr)
1670 * Pathetic attempt at automatic media selection.
1671 * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
1672 * cards operational.
1673 * It's a bonus if it works for anything else.
1676 if(ctlr->rxstatus9){
1677 COMMAND(port, SelectRegisterWindow, Wsetup);
1678 x = ins(port+ConfigControl);
1680 if(x & base10TAvailable9)
1681 media |= base10TAvailable;
1682 if(x & coaxAvailable9)
1683 media |= coaxAvailable;
1684 if(x & auiAvailable9)
1685 media |= auiAvailable;
1688 COMMAND(port, SelectRegisterWindow, Wfifo);
1689 media = ins(port+ResetOptions);
1691 XCVRDEBUG("autoselect: media %uX\n", media);
1693 if(media & miiConnector)
1696 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1697 XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
1699 if(media & baseTXAvailable){
1701 * Must have InternalConfig register.
1703 setxcvr(ctlr, xcvr100BaseTX);
1705 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1706 x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
1707 outs(port+MediaStatus, linkBeatEnable|x);
1710 if(ins(port+MediaStatus) & linkBeatDetect)
1711 return xcvr100BaseTX;
1712 outs(port+MediaStatus, x);
1715 if(media & base10TAvailable){
1716 setxcvr(ctlr, xcvr10BaseT);
1718 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1719 x = ins(port+MediaStatus) & ~dcConverterEnabled;
1720 outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
1723 XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
1724 if(ins(port+MediaStatus) & linkBeatDetect)
1726 outs(port+MediaStatus, x);
1736 eepromdata(Ctlr* ctlr, int offset)
1742 COMMAND(port, SelectRegisterWindow, Wsetup);
1743 while(EEPROMBUSY(port))
1745 EEPROMCMD(port, ctlr->eepromcmd, offset);
1746 while(EEPROMBUSY(port))
1748 return EEPROMDATA(port);
1752 resetctlr(Ctlr *ctlr)
1754 int x, port = ctlr->port;
1757 x = ins(port+ResetOp905B);
1758 XCVRDEBUG("905[BC] reset ops 0x%uX\n", x);
1760 if(ctlr->did == 0x5157){
1761 x |= 0x0010; /* Invert LED */
1762 outs(port+ResetOp905B, x);
1764 if(ctlr->did == 0x6056){
1766 outs(port+ResetOp905B, x);
1768 COMMAND(port, SelectRegisterWindow, Wsetup);
1774 shutdown(Ether *ether)
1776 print("etherelnk3 shutting down\n");
1777 resetctlr(ether->ctlr);
1781 etherelnk3reset(Ether* ether)
1786 static int scandone;
1787 int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x;
1790 * Scan for adapter on PCI, EISA and finally
1791 * using the little ISA configuration dance.
1801 * Any adapter matches if no ether->port is supplied,
1802 * otherwise the ports must match.
1804 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
1807 if(ether->port == 0 || ether->port == ctlr->port){
1812 if(ctlr == nil && (ctlr = tcm5XXpcmcia(ether)) == 0)
1818 ether->irq = ctlr->irq;
1819 if(ctlr->pcidev != nil)
1820 ether->tbdf = ctlr->pcidev->tbdf;
1822 ether->tbdf = BUSUNKNOWN;
1825 * Read the DeviceID from the EEPROM, it's at offset 0x03,
1826 * and do something depending on capabilities.
1828 switch(ctlr->did = eepromdata(ctlr, 0x03)){
1829 case 0x5157: /* 3C575 Cyclone */
1832 case 0x4500: /* 3C450 HomePNA Tornado */
1833 case 0x7646: /* 3CSOHO100-TX */
1834 case 0x9055: /* 3C905B-TX */
1835 case 0x9200: /* 3C905C-TX */
1836 case 0x9201: /* 3C920 */
1837 case 0x9805: /* 3C9805: 3C980-TX Python-T 10/100baseTX */
1839 case 0x9000: /* 3C900-TPO */
1840 case 0x9001: /* 3C900-COMBO */
1841 case 0x9005: /* 3C900B-COMBO */
1842 case 0x9050: /* 3C905-TX */
1843 case 0x9051: /* 3C905-T4 */
1844 if(BUSTYPE(ether->tbdf) != BusPCI)
1846 ctlr->busmaster = 2;
1848 case 0x5900: /* 3C590-[TP|COMBO|TPO] */
1849 case 0x5920: /* 3C592-[TP|COMBO|TPO] */
1850 case 0x5950: /* 3C595-TX */
1851 case 0x5951: /* 3C595-T4 */
1852 case 0x5952: /* 3C595-MII */
1853 case 0x5970: /* 3C597-TX */
1854 case 0x5971: /* 3C597-T4 */
1855 case 0x5972: /* 3C597-MII */
1856 ctlr->busmaster = 1;
1858 COMMAND(port, SelectRegisterWindow, Wfifo);
1859 ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
1860 ctlr->rxearly = 8188;
1861 ctlr->rxstatus9 = 0;
1865 ctlr->busmaster = 0;
1866 COMMAND(port, SelectRegisterWindow, Wsetup);
1867 x = ins(port+AddressConfig);
1868 ctlr->xcvr = ((x & xcvrMask9)>>14)<<20;
1870 ctlr->xcvr |= autoSelect;
1871 ctlr->rxearly = 2044;
1872 ctlr->rxstatus9 = 1;
1875 if(ctlr->rxearly >= 2048)
1879 * Check if the adapter's station address is to be overridden.
1880 * If not, read it from the EEPROM and set in ether->ea prior to
1881 * loading the station address in Wstation.
1882 * The EEPROM returns 16-bits at a time.
1884 memset(ea, 0, Eaddrlen);
1885 if(memcmp(ea, ether->ea, Eaddrlen) == 0){
1886 for(i = 0; i < Eaddrlen/2; i++){
1887 x = eepromdata(ctlr, i);
1888 ether->ea[2*i] = x>>8;
1889 ether->ea[2*i+1] = x;
1893 COMMAND(port, SelectRegisterWindow, Wstation);
1894 for(i = 0; i < Eaddrlen; i++)
1895 outb(port+i, ether->ea[i]);
1898 * Enable the transceiver if necessary and determine whether
1899 * busmastering can be used. Due to bugs in the first revision
1900 * of the 3C59[05], don't use busmastering at 10Mbps.
1902 XCVRDEBUG("reset: xcvr %uX\n", ctlr->xcvr);
1905 * Allow user to specify desired media in plan9.ini
1907 for(i = 0; i < ether->nopt; i++){
1908 if(cistrncmp(ether->opt[i], "media=", 6) != 0)
1910 p = ether->opt[i]+6;
1911 for(j = 0; j < nelem(media); j++)
1912 if(cistrcmp(p, media[j].name) == 0)
1913 ctlr->xcvr = media[j].xcvr;
1917 * forgive me, but i am weak
1921 if(ctlr->xcvr & autoSelect)
1922 ctlr->xcvr = autoselect(ctlr);
1932 ctlr->xcvr = xcvrMii;
1936 XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did);
1943 if(ctlr->did == 0x5157)
1945 else if(ctlr->did == 0x6056)
1946 phyaddr = scanphy(port);
1949 for(i = 0; i < 7; i++)
1950 XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
1953 for(timeo = 0; timeo < 30; timeo++){
1954 phystat = miir(port, phyaddr, 0x01);
1957 XCVRDEBUG(" %2.2uX", phystat);
1960 XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
1963 anar = miir(port, phyaddr, 0x04);
1964 anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
1966 miir(port, phyaddr, 0x00);
1967 XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
1968 anar, anlpar, miir(port, phyaddr, 0x00),
1969 miir(port, phyaddr, 0x01));
1970 for(i = 0; i < ether->nopt; i++){
1971 if(cistrcmp(ether->opt[i], "fullduplex") == 0)
1973 else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
1975 else if(cistrcmp(ether->opt[i], "force100") == 0)
1978 XCVRDEBUG("mii anar: %uX\n", anar);
1979 if(anar & 0x0100){ /* 100BASE-TXFD */
1981 setfullduplex(port);
1983 else if(anar & 0x0200){ /* 100BASE-T4 */
1986 else if(anar & 0x0080) /* 100BASE-TX */
1988 else if(anar & 0x0040) /* 10BASE-TFD */
1989 setfullduplex(port);
1990 else{ /* 10BASE-T */
1996 COMMAND(port, SelectRegisterWindow, Wfifo);
1997 x = inl(port+InternalConfig) & ~ramPartitionMask;
1998 outl(port+InternalConfig, x|ramPartition1to1);
2000 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2001 x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
2002 x |= linkBeatEnable;
2003 outs(port+MediaStatus, x);
2010 * Enable Link Beat and Jabber to start the
2013 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2014 x = ins(port+MediaStatus) & ~dcConverterEnabled;
2015 x |= linkBeatEnable|jabberGuardEnable;
2016 outs(port+MediaStatus, x);
2018 if((ctlr->did & 0xFF00) == 0x5900)
2019 ctlr->busmaster = 0;
2022 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2023 x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
2024 outs(port+MediaStatus, x);
2027 * Start the DC-DC converter.
2028 * Wait > 800 microseconds.
2030 COMMAND(port, EnableDcConverter, 0);
2036 * Wop is the normal operating register set.
2037 * The 3C59[0257] adapters allow access to more than one register window
2038 * at a time, but there are situations where switching still needs to be
2039 * done, so just do it.
2040 * Clear out any lingering Tx status.
2042 COMMAND(port, SelectRegisterWindow, Wop);
2043 if(ctlr->busmaster == 2)
2044 x = port+TxStatus905;
2052 * adapter statistics, clear the statistics logged into ctlr
2053 * and enable statistics collection.
2055 ilock(&ctlr->wlock);
2057 memset(ctlr->stats, 0, sizeof(ctlr->stats));
2059 COMMAND(port, StatisticsEnable, 0);
2062 * Allocate any receive buffers.
2064 switch(ctlr->busmaster){
2066 ctlr->dnenabled = 1;
2070 * Disabling is too severe, can use receive busmastering at
2071 * 100Mbps OK, but how to tell which rate is actually being used -
2072 * the 3c905 always seems to have dataRate100 set?
2073 * Believe the bug doesn't apply if upRxEarlyEnable is set
2074 * and the threshold is set such that uploads won't start
2075 * until the whole packet has been received.
2077 ctlr->upenabled = 1;
2078 x = eepromdata(ctlr, 0x0F);
2080 outl(port+PktStatus, upRxEarlyEnable);
2082 if(ctlr->upenabled || ctlr->dnenabled){
2088 ctlr->rbp = rbpalloc(iallocb);
2089 if(ctlr->rbp == nil)
2090 panic("can't reset ethernet: out of memory");
2092 outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
2095 ctlr->rbp = rbpalloc(iallocb);
2096 if(ctlr->rbp == nil)
2097 panic("can't reset ethernet: out of memory");
2102 * Set a base TxStartThresh which will be incremented
2103 * if any txUnderrun errors occur and ensure no RxEarly
2104 * interrupts happen.
2106 ctlr->txthreshold = ETHERMAXTU/2;
2107 COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
2108 COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
2110 iunlock(&ctlr->wlock);
2113 * Linkage to the generic ethernet driver.
2115 ether->attach = attach;
2116 ether->transmit = transmit;
2117 ether->interrupt = interrupt;
2118 ether->ifstat = ifstat;
2120 ether->promiscuous = promiscuous;
2121 ether->multicast = multicast;
2122 ether->shutdown = shutdown;
2129 etherelnk3link(void)
2131 addethercard("elnk3", etherelnk3reset);
2132 addethercard("3C509", etherelnk3reset);
2133 addethercard("3C575", etherelnk3reset);