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 if(ctlr->upbase == nil)
450 panic("etherlnk3: can't allocate upr");
451 ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
454 for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
455 pd->np = PADDR(&prev->np);
457 bp = iallocb(sizeof(Etherpkt));
459 panic("etherlnk3: iallocb: out of memory");
460 pd->addr = PADDR(bp->rp);
461 pd->len = updnLastFrag|sizeof(Etherpkt);
467 ctlr->uphead = ctlr->upr;
469 ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
470 if(ctlr->dnbase == nil)
471 panic("etherlnk3: can't allocate dnr");
472 ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
475 for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
479 ctlr->dnhead = ctlr->dnr;
480 ctlr->dntail = ctlr->dnr;
485 rbpalloc(Block* (*f)(int))
491 * The receive buffers must be on a 32-byte
492 * boundary for EISA busmastering.
494 if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
495 addr = (ulong)bp->base;
496 addr = ROUNDUP(addr, 32);
497 bp->rp = (uchar*)addr;
504 startdma(Ether* ether, ulong address)
511 w = (STATUS(port)>>13) & 0x07;
512 COMMAND(port, SelectRegisterWindow, Wmaster);
514 wp = KADDR(inl(port+MasterAddress));
515 status = ins(port+MasterStatus);
516 if(status & (masterInProgress|targetAbort|masterAbort))
517 print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
518 outs(port+MasterStatus, masterMask);
519 outl(port+MasterAddress, address);
520 outs(port+MasterLen, sizeof(Etherpkt));
521 COMMAND(port, StartDma, Upload);
523 COMMAND(port, SelectRegisterWindow, w);
528 promiscuous(void* arg, int on)
536 filter = receiveBroadcast|receiveIndividual;
538 filter |= receiveMulticast;
540 filter |= receiveAllFrames;
541 COMMAND(port, SetRxFilter, filter);
545 multicast(void* arg, uchar *addr, int on)
555 filter = receiveBroadcast|receiveIndividual;
557 filter |= receiveMulticast;
559 filter |= receiveAllFrames;
560 COMMAND(port, SetRxFilter, filter);
563 /* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
565 intrackcb(ulong *cbfn)
579 iunlock(&ctlr->wlock);
586 * Set the receiver packet filter for this and broadcast addresses,
587 * set the interrupt masks for all interrupts, enable the receiver
590 promiscuous(ether, ether->prom);
593 if(ctlr->busmaster == 1)
594 x &= ~(rxEarly|rxComplete);
599 x &= ~(rxEarly|rxComplete);
601 COMMAND(port, SetIndicationEnable, x);
602 COMMAND(port, SetInterruptEnable, x);
603 COMMAND(port, RxEnable, 0);
604 COMMAND(port, TxEnable, 0);
607 * If this is a CardBus card, acknowledge any interrupts.
609 if(ctlr->cbfn != nil)
610 intrackcb(ctlr->cbfn);
613 * Prime the busmaster channel for receiving directly into a
614 * receive packet buffer if necessary.
616 if(ctlr->busmaster == 1)
617 startdma(ether, PADDR(ctlr->rbp->rp));
620 outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
624 iunlock(&ctlr->wlock);
628 statistics(Ether* ether)
637 * 3C59[27] require a read between a PIO write and
638 * reading a statistics register.
640 w = (STATUS(port)>>13) & 0x07;
641 COMMAND(port, SelectRegisterWindow, Wstatistics);
644 for(i = 0; i < UpperFramesOk; i++)
645 ctlr->stats[i] += inb(port+i) & 0xFF;
646 u = inb(port+UpperFramesOk) & 0xFF;
647 ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
648 ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
649 ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
650 ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
657 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
659 ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
663 COMMAND(port, SelectRegisterWindow, w);
667 txstart(Ether* ether)
677 * Attempt to top-up the transmit FIFO. If there's room simply
678 * stuff in the packet length (unpadded to a dword boundary), the
679 * packet data (padded) and remove the packet from the queue.
680 * If there's no room post an interrupt for when there is.
681 * This routine is called both from the top level and from interrupt
682 * level and expects to be called with ctlr->wlock already locked
683 * and the correct register window (Wop) in place.
691 bp = qget(ether->oq);
696 len = ROUNDUP(BLEN(bp), 4);
697 if(len+4 <= ins(port+TxFree)){
698 outl(port+Fifo, BLEN(bp));
699 outsl(port+Fifo, bp->rp, len/4);
707 if(ctlr->txbusy == 0){
709 COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
717 txstart905(Ether* ether)
720 int port, stalled, timeo;
728 * Free any completed packets.
732 if(PADDR(&pd->np) == inl(port+DnListPtr))
744 while(ctlr->dnq < (ctlr->ndn-1)){
745 bp = qget(ether->oq);
749 pd = ctlr->dnhead->next;
751 pd->control = dnIndicate|BLEN(bp);
752 pd->addr = PADDR(bp->rp);
753 pd->len = updnLastFrag|BLEN(bp);
756 if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
757 COMMAND(port, Stall, dnStall);
758 for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
761 print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
766 ctlr->dnhead->np = PADDR(&pd->np);
767 ctlr->dnhead->control &= ~dnIndicate;
776 if(ctlr->dnq > ctlr->dnqmax)
777 ctlr->dnqmax = ctlr->dnq;
780 * If the adapter is not currently processing anything
781 * and there is something on the queue, start it processing.
783 if(inl(port+DnListPtr) == 0 && ctlr->dnq)
784 outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
786 COMMAND(port, Stall, dnUnStall);
790 transmit(Ether* ether)
802 w = (STATUS(port)>>13) & 0x07;
803 COMMAND(port, SelectRegisterWindow, Wop);
805 COMMAND(port, SelectRegisterWindow, w);
807 iunlock(&ctlr->wlock);
811 receive905(Ether* ether)
821 if(inl(port+UpPktStatus) & upStalled)
824 for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
825 if(pd->control & upError){
826 if(pd->control & upOverrun)
828 if(pd->control & (upOversizedFrame|upRuntFrame))
830 if(pd->control & upAlignmentError)
832 if(pd->control & upCRCError)
835 else if(bp = iallocb(sizeof(Etherpkt)+4)){
836 len = pd->control & rxBytes;
837 pd->bp->wp = pd->bp->rp+len;
838 etheriq(ether, pd->bp, 1);
840 pd->addr = PADDR(bp->rp);
845 COMMAND(port, Stall, upUnStall);
857 receive(Ether* ether)
859 int len, port, rxerror, rxstatus;
866 while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
867 if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
871 * If there was an error, log it and continue.
872 * Unfortunately the 3C5[078]9 has the error info in the status register
873 * and the 3C59[0257] implement a separate RxError register.
875 if(rxstatus & rxError){
877 switch(rxstatus & rxError9){
883 case oversizedFrame9:
888 case alignmentError9:
899 rxerror = inb(port+RxError);
900 if(rxerror & rxOverrun)
902 if(rxerror & (oversizedFrame|runtFrame))
904 if(rxerror & alignmentError)
906 if(rxerror & crcError)
912 * If there was an error or a new receive buffer can't be
913 * allocated, discard the packet and go on to the next.
915 if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){
916 COMMAND(port, RxDiscard, 0);
917 while(STATUS(port) & commandInProgress)
920 if(ctlr->busmaster == 1)
921 startdma(ether, PADDR(ctlr->rbp->rp));
927 * A valid receive packet awaits:
928 * if using PIO, read it into the buffer;
929 * discard the packet from the FIFO;
930 * if using busmastering, start a new transfer for
931 * the next packet and as a side-effect get the
932 * end-pointer of the one just received;
933 * pass the packet on to whoever wants it.
935 if(ctlr->busmaster == 0 || ctlr->busmaster == 2){
936 len = (rxstatus & rxBytes9);
937 ctlr->rbp->wp = ctlr->rbp->rp + len;
938 insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4));
941 COMMAND(port, RxDiscard, 0);
942 while(STATUS(port) & commandInProgress)
945 if(ctlr->busmaster == 1)
946 ctlr->rbp->wp = startdma(ether, PADDR(bp->rp));
948 etheriq(ether, ctlr->rbp, 1);
966 interrupt(Ureg*, void* arg)
969 int port, status, s, txstatus, w, x;
977 status = STATUS(port);
978 if(!(status & (interruptMask|interruptLatch))){
979 ctlr->bogusinterrupts++;
980 iunlock(&ctlr->wlock);
983 w = (status>>13) & 0x07;
984 COMMAND(port, SelectRegisterWindow, Wop);
987 if(ctlr->busmaster == 2)
988 ctlr->timer[0] += inb(port+TIMER905) & 0xFF;
990 ctlr->timer[0] += inb(port+TIMER) & 0xFF;
993 if(status & hostError){
995 * Adapter failure, try to find out why, reset if
996 * necessary. What happens if Tx is active and a reset
997 * occurs, need to retransmit? This probably isn't right.
999 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1000 x = ins(port+FifoDiagnostic);
1001 COMMAND(port, SelectRegisterWindow, Wop);
1003 if (status == 0xFFFF && x == 0xFFFF && ejectable(ctlr->did)) {
1004 print("#l%d: Card ejected?\n", ether->ctlrno);
1005 iunlock(&ctlr->wlock);
1009 print("#l%d: status 0x%uX, diag 0x%uX\n",
1010 ether->ctlrno, status, x);
1013 if(ctlr->busmaster == 0)
1014 COMMAND(port, TxReset, 0);
1016 COMMAND(port, TxReset, (updnReset|dmaReset));
1017 COMMAND(port, TxEnable, 0);
1022 * This shouldn't happen...
1023 * Reset the receiver and restore the filter and RxEarly
1024 * threshold before re-enabling.
1025 * Need to restart any busmastering?
1027 COMMAND(port, SelectRegisterWindow, Wstate);
1028 s = (port+RxFilter) & 0x000F;
1029 COMMAND(port, SelectRegisterWindow, Wop);
1030 COMMAND(port, RxReset, 0);
1031 while(STATUS(port) & commandInProgress)
1033 COMMAND(port, SetRxFilter, s);
1034 COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
1035 COMMAND(port, RxEnable, 0);
1038 status &= ~hostError;
1041 if(status & (transferInt|rxComplete)){
1043 status &= ~(transferInt|rxComplete);
1046 if(status & (upComplete)){
1047 COMMAND(port, AcknowledgeInterrupt, upComplete);
1049 status &= ~upComplete;
1050 ctlr->upinterrupts++;
1053 if(status & txComplete){
1055 * Pop the TxStatus stack, accumulating errors.
1056 * Adjust the TX start threshold if there was an underrun.
1057 * If there was a Jabber or Underrun error, reset
1058 * the transmitter, taking care not to reset the dma logic
1059 * as a busmaster receive may be in progress.
1060 * For all conditions enable the transmitter.
1062 if(ctlr->busmaster == 2)
1063 txstatus = port+TxStatus905;
1065 txstatus = port+TxStatus;
1068 if(x = inb(txstatus))
1071 }while(STATUS(port) & txComplete);
1074 if(ctlr->dnenabled){
1075 while(inl(port+PktStatus) & dnInProg)
1078 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1079 while(ins(port+MediaStatus) & txInProg)
1081 COMMAND(port, SelectRegisterWindow, Wop);
1082 if(ctlr->txthreshold < ETHERMAXTU)
1083 ctlr->txthreshold += ETHERMINTU;
1087 * According to the manual, maxCollisions does not require
1088 * a TxReset, merely a TxEnable. However, evidence points to
1089 * it being necessary on the 3C905. The jury is still out.
1090 * On busy or badly configured networks maxCollisions can
1091 * happen frequently enough for messages to be annoying so
1092 * keep quiet about them by popular request.
1094 if(s & (txJabber|txUnderrun|maxCollisions)){
1095 if(ctlr->busmaster == 0)
1096 COMMAND(port, TxReset, 0);
1098 COMMAND(port, TxReset, (updnReset|dmaReset));
1099 while(STATUS(port) & commandInProgress)
1101 COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
1102 if(ctlr->busmaster == 2)
1103 outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
1105 status |= dnComplete;
1108 if(s & ~(txStatusComplete|maxCollisions))
1109 print("#l%d: txstatus 0x%uX, threshold %d\n",
1110 ether->ctlrno, s, ctlr->txthreshold);
1111 COMMAND(port, TxEnable, 0);
1113 status &= ~txComplete;
1114 status |= txAvailable;
1117 if(status & txAvailable){
1118 COMMAND(port, AcknowledgeInterrupt, txAvailable);
1121 status &= ~txAvailable;
1124 if(status & dnComplete){
1125 COMMAND(port, AcknowledgeInterrupt, dnComplete);
1127 status &= ~dnComplete;
1128 ctlr->dninterrupts++;
1131 if(status & updateStats){
1133 status &= ~updateStats;
1137 * Currently, this shouldn't happen.
1139 if(status & rxEarly){
1140 COMMAND(port, AcknowledgeInterrupt, rxEarly);
1145 * Panic if there are any interrupts not dealt with.
1147 if(status & interruptMask)
1148 panic("#l%d: interrupt mask 0x%uX", ether->ctlrno, status);
1150 COMMAND(port, AcknowledgeInterrupt, interruptLatch);
1151 if(ctlr->cbfn != nil)
1152 intrackcb(ctlr->cbfn);
1154 }while((status = STATUS(port)) & (interruptMask|interruptLatch));
1156 if(ctlr->busmaster == 2)
1157 ctlr->timer[1] += inb(port+TIMER905) & 0xFF;
1159 ctlr->timer[1] += inb(port+TIMER) & 0xFF;
1161 COMMAND(port, SelectRegisterWindow, w);
1162 iunlock(&ctlr->wlock);
1166 ifstat(Ether* ether, void* a, long n, ulong offset)
1177 ilock(&ctlr->wlock);
1179 iunlock(&ctlr->wlock);
1181 p = smalloc(READSTR);
1182 len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
1183 len += snprint(p+len, READSTR-len, "bogusinterrupts: %lud\n", ctlr->bogusinterrupts);
1184 len += snprint(p+len, READSTR-len, "timer: %lud %lud\n",
1185 ctlr->timer[0], ctlr->timer[1]);
1186 len += snprint(p+len, READSTR-len, "carrierlost: %lud\n",
1187 ctlr->stats[CarrierLost]);
1188 len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n",
1189 ctlr->stats[SqeErrors]);
1190 len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n",
1191 ctlr->stats[MultipleColls]);
1192 len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n",
1193 ctlr->stats[SingleCollFrames]);
1194 len += snprint(p+len, READSTR-len, "latecollisions: %lud\n",
1195 ctlr->stats[LateCollisions]);
1196 len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n",
1197 ctlr->stats[RxOverruns]);
1198 len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n",
1199 ctlr->stats[FramesXmittedOk]);
1200 len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n",
1201 ctlr->stats[FramesRcvdOk]);
1202 len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n",
1203 ctlr->stats[FramesDeferred]);
1204 len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n",
1205 ctlr->stats[BytesRcvdOk]);
1206 len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n",
1207 ctlr->stats[BytesRcvdOk+1]);
1209 if(ctlr->upenabled){
1210 if(ctlr->upqmax > ctlr->upqmaxhw)
1211 ctlr->upqmaxhw = ctlr->upqmax;
1212 len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d h %d s %lud\n",
1213 ctlr->upqueued, ctlr->upinterrupts,
1214 ctlr->upqmax, ctlr->upqmaxhw, ctlr->upstalls);
1217 if(ctlr->dnenabled){
1218 if(ctlr->dnqmax > ctlr->dnqmaxhw)
1219 ctlr->dnqmaxhw = ctlr->dnqmax;
1220 len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d h %d\n",
1221 ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax, ctlr->dnqmaxhw);
1225 snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]);
1227 n = readstr(offset, a, n, p);
1236 COMMAND(port, TxReset, 0);
1237 while(STATUS(port) & commandInProgress)
1239 COMMAND(port, RxReset, 0);
1240 while(STATUS(port) & commandInProgress)
1245 tcmadapter(int port, int irq, Pcidev* pcidev)
1249 ctlr = malloc(sizeof(Ctlr));
1251 print("etherelnk3: can't allocate memory\n");
1256 ctlr->pcidev = pcidev;
1257 ctlr->eepromcmd = EepromReadRegister;
1260 ctlrtail->next = ctlr;
1269 * Write two 0 bytes to identify the IDport and then reset the
1270 * ID sequence. Then send the ID sequence to the card to get
1271 * the card into command state.
1278 static int reset, untag;
1282 * reset any adapters listening
1294 for(al = 0xFF, i = 0; i < 255; i++){
1306 * write ID sequence to get the attention of all adapters;
1307 * untag all adapters.
1308 * If a global reset is done here on all adapters it will confuse
1309 * any ISA cards configured for EISA mode.
1324 * Do the little configuration dance:
1326 * 2. write the ID sequence to get to command state.
1331 * 3. Read the Manufacturer ID from the EEPROM.
1332 * This is done by writing the IDPort with 0x87 (0x80
1333 * is the 'read EEPROM' command, 0x07 is the offset of
1334 * the Manufacturer ID field in the EEPROM).
1335 * The data comes back 1 bit at a time.
1336 * A delay seems necessary between reading the bits.
1338 * If the ID doesn't match, there are no more adapters.
1342 for(x = 0, i = 0; i < 16; i++){
1345 x |= inb(IDport) & 0x01;
1351 * 3. Read the Address Configuration from the EEPROM.
1352 * The Address Configuration field is at offset 0x08 in the EEPROM).
1355 for(acr = 0, i = 0; i < 16; i++){
1358 acr |= inb(IDport) & 0x01;
1361 return (acr & 0x1F)*0x10 + 0x200;
1370 * Attempt to activate all adapters. If adapter is set for
1371 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
1374 while(port = activate()){
1375 if(ioalloc(port, 0x10, 0, "tcm509isa") < 0){
1376 print("tcm509isa: port 0x%uX in use\n", port);
1381 * 6. Tag the adapter so it won't respond in future.
1390 * 6. Activate the adapter by writing the Activate command
1397 * 8. Can now talk to the adapter's I/O base addresses.
1398 * Use the I/O base address from the acr just read.
1400 * Enable the adapter and clear out any lingering status
1403 while(STATUS(port) & commandInProgress)
1405 COMMAND(port, SelectRegisterWindow, Wsetup);
1406 outs(port+ConfigControl, Ena);
1409 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1411 irq = (ins(port+ResourceConfig)>>12) & 0x0F;
1412 tcmadapter(port, irq, nil);
1420 int irq, port, slot;
1423 * Check if this is an EISA machine.
1424 * If not, nothing to do.
1426 if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
1430 * Continue through the EISA slots looking for a match on both
1431 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
1432 * If an adapter is found, select window 0, enable it and clear
1433 * out any lingering status and interrupts.
1435 for(slot = 1; slot < MaxEISA; slot++){
1437 if(ioalloc(port, 0x1000, 0, "tcm5XXeisa") < 0){
1438 print("tcm5XXeisa: port 0x%uX in use\n", port);
1441 if(ins(port+0xC80+ManufacturerID) != 0x6D50){
1445 x = ins(port+0xC80+ProductID);
1446 if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900){
1451 COMMAND(port, SelectRegisterWindow, Wsetup);
1452 outs(port+ConfigControl, Ena);
1455 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1457 irq = (ins(port+ResourceConfig)>>12) & 0x0F;
1458 tcmadapter(port, irq, nil);
1470 while(p = pcimatch(p, 0x10B7, 0)){
1471 if(p->ccrb != 0x02 || p->ccru != 0)
1474 * Not prepared to deal with memory-mapped
1477 if(!(p->mem[0].bar & 0x01))
1479 port = p->mem[0].bar & ~0x01;
1480 if((port = ioalloc((port == 0)? -1: port, p->mem[0].size,
1481 0, "tcm59Xpci")) < 0){
1482 print("tcm59Xpci: port 0x%uX in use\n", port);
1488 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1490 ctlr = tcmadapter(port, irq, p);
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);
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);
1511 static char* tcmpcmcia[] = {
1512 "3C589", /* 3COM 589[ABCD] */
1513 "3C562", /* 3COM 562 */
1514 "589E", /* 3COM Megahertz 589E */
1519 tcm5XXpcmcia(Ether* ether)
1524 if(ether->type == nil)
1527 for(i = 0; tcmpcmcia[i] != nil; i++){
1528 if(cistrcmp(ether->type, tcmpcmcia[i]))
1530 if(ctlr = tcmadapter(ether->port, ether->irq, nil))
1539 setxcvr(Ctlr* ctlr, int xcvr)
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);
1551 COMMAND(port, SelectRegisterWindow, Wfifo);
1552 x = inl(port+InternalConfig) & ~xcvrMask;
1554 outl(port+InternalConfig, x);
1561 setfullduplex(int port)
1565 COMMAND(port, SelectRegisterWindow, Wfifo);
1566 x = ins(port+MacControl);
1567 outs(port+MacControl, fullDuplexEnable|x);
1573 miimdi(int port, int n)
1578 * Read n bits from the MII Management Register.
1581 for(i = n-1; i >= 0; i--){
1582 if(ins(port) & mgmtData)
1585 outs(port, mgmtClk);
1595 miimdo(int port, int bits, int n)
1600 * Write n bits to the MII Management Register.
1602 for(i = n-1; i >= 0; i--){
1604 mdo = mgmtDir|mgmtData;
1609 outs(port, mdo|mgmtClk);
1617 miir(int port, int phyad, int regad)
1621 w = (STATUS(port)>>13) & 0x07;
1622 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1623 port += PhysicalMgmt;
1627 * ST+OP+PHYAD+REGAD;
1628 * TA + 16 data bits.
1630 miimdo(port, 0xFFFFFFFF, 32);
1631 miimdo(port, 0x1800|(phyad<<5)|regad, 14);
1632 data = miimdi(port, 18);
1634 port -= PhysicalMgmt;
1635 COMMAND(port, SelectRegisterWindow, w);
1640 return data & 0xFFFF;
1648 for(i = 0; i < 32; i++){
1649 if((x = miir(port, i, 2)) == -1 || x == 0)
1652 x |= miir(port, i, 3)>>10;
1653 XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
1666 "10BaseT", base10TAvailable, xcvr10BaseT,
1667 "10Base2", coaxAvailable, xcvr10Base2,
1668 "100BaseTX", baseTXAvailable, xcvr100BaseTX,
1669 "100BaseFX", baseFXAvailable, xcvr100BaseFX,
1670 "aui", auiAvailable, xcvrAui,
1671 "mii", miiConnector, xcvrMii
1675 autoselect(Ctlr* ctlr)
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.
1686 if(ctlr->rxstatus9){
1687 COMMAND(port, SelectRegisterWindow, Wsetup);
1688 x = ins(port+ConfigControl);
1690 if(x & base10TAvailable9)
1691 media |= base10TAvailable;
1692 if(x & coaxAvailable9)
1693 media |= coaxAvailable;
1694 if(x & auiAvailable9)
1695 media |= auiAvailable;
1698 COMMAND(port, SelectRegisterWindow, Wfifo);
1699 media = ins(port+ResetOptions);
1701 XCVRDEBUG("autoselect: media %uX\n", media);
1703 if(media & miiConnector)
1706 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1707 XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
1709 if(media & baseTXAvailable){
1711 * Must have InternalConfig register.
1713 setxcvr(ctlr, xcvr100BaseTX);
1715 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1716 x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
1717 outs(port+MediaStatus, linkBeatEnable|x);
1720 if(ins(port+MediaStatus) & linkBeatDetect)
1721 return xcvr100BaseTX;
1722 outs(port+MediaStatus, x);
1725 if(media & base10TAvailable){
1726 setxcvr(ctlr, xcvr10BaseT);
1728 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1729 x = ins(port+MediaStatus) & ~dcConverterEnabled;
1730 outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
1733 XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
1734 if(ins(port+MediaStatus) & linkBeatDetect)
1736 outs(port+MediaStatus, x);
1746 eepromdata(Ctlr* ctlr, int offset)
1752 COMMAND(port, SelectRegisterWindow, Wsetup);
1753 while(EEPROMBUSY(port))
1755 EEPROMCMD(port, ctlr->eepromcmd, offset);
1756 while(EEPROMBUSY(port))
1758 return EEPROMDATA(port);
1762 resetctlr(Ctlr *ctlr)
1764 int x, port = ctlr->port;
1767 x = ins(port+ResetOp905B);
1768 XCVRDEBUG("905[BC] reset ops 0x%uX\n", x);
1770 if(ctlr->did == 0x5157){
1771 x |= 0x0010; /* Invert LED */
1772 outs(port+ResetOp905B, x);
1774 if(ctlr->did == 0x6056){
1776 outs(port+ResetOp905B, x);
1778 COMMAND(port, SelectRegisterWindow, Wsetup);
1784 shutdown(Ether *ether)
1786 print("etherelnk3 shutting down\n");
1787 resetctlr(ether->ctlr);
1791 etherelnk3reset(Ether* ether)
1796 static int scandone;
1797 int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x;
1800 * Scan for adapter on PCI, EISA and finally
1801 * using the little ISA configuration dance.
1811 * Any adapter matches if no ether->port is supplied,
1812 * otherwise the ports must match.
1814 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
1817 if(ether->port == 0 || ether->port == ctlr->port){
1822 if(ctlr == nil && (ctlr = tcm5XXpcmcia(ether)) == 0)
1828 ether->irq = ctlr->irq;
1829 if(ctlr->pcidev != nil)
1830 ether->tbdf = ctlr->pcidev->tbdf;
1832 ether->tbdf = BUSUNKNOWN;
1835 * Read the DeviceID from the EEPROM, it's at offset 0x03,
1836 * and do something depending on capabilities.
1838 switch(ctlr->did = eepromdata(ctlr, 0x03)){
1839 case 0x5157: /* 3C575 Cyclone */
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 */
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)
1856 ctlr->busmaster = 2;
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;
1868 COMMAND(port, SelectRegisterWindow, Wfifo);
1869 ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
1870 ctlr->rxearly = 8188;
1871 ctlr->rxstatus9 = 0;
1875 ctlr->busmaster = 0;
1876 COMMAND(port, SelectRegisterWindow, Wsetup);
1877 x = ins(port+AddressConfig);
1878 ctlr->xcvr = ((x & xcvrMask9)>>14)<<20;
1880 ctlr->xcvr |= autoSelect;
1881 ctlr->rxearly = 2044;
1882 ctlr->rxstatus9 = 1;
1885 if(ctlr->rxearly >= 2048)
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.
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;
1903 COMMAND(port, SelectRegisterWindow, Wstation);
1904 for(i = 0; i < Eaddrlen; i++)
1905 outb(port+i, ether->ea[i]);
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.
1912 XCVRDEBUG("reset: xcvr %uX\n", ctlr->xcvr);
1915 * Allow user to specify desired media in plan9.ini
1917 for(i = 0; i < ether->nopt; i++){
1918 if(cistrncmp(ether->opt[i], "media=", 6) != 0)
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;
1927 * forgive me, but i am weak
1931 if(ctlr->xcvr & autoSelect)
1932 ctlr->xcvr = autoselect(ctlr);
1942 ctlr->xcvr = xcvrMii;
1946 XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did);
1953 if(ctlr->did == 0x5157)
1955 else if(ctlr->did == 0x6056)
1956 phyaddr = scanphy(port);
1959 for(i = 0; i < 7; i++)
1960 XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
1963 for(timeo = 0; timeo < 30; timeo++){
1964 phystat = miir(port, phyaddr, 0x01);
1967 XCVRDEBUG(" %2.2uX", phystat);
1970 XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
1973 anar = miir(port, phyaddr, 0x04);
1974 anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
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)
1983 else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
1985 else if(cistrcmp(ether->opt[i], "force100") == 0)
1988 XCVRDEBUG("mii anar: %uX\n", anar);
1989 if(anar & 0x0100){ /* 100BASE-TXFD */
1991 setfullduplex(port);
1993 else if(anar & 0x0200){ /* 100BASE-T4 */
1996 else if(anar & 0x0080) /* 100BASE-TX */
1998 else if(anar & 0x0040) /* 10BASE-TFD */
1999 setfullduplex(port);
2000 else{ /* 10BASE-T */
2006 COMMAND(port, SelectRegisterWindow, Wfifo);
2007 x = inl(port+InternalConfig) & ~ramPartitionMask;
2008 outl(port+InternalConfig, x|ramPartition1to1);
2010 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2011 x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
2012 x |= linkBeatEnable;
2013 outs(port+MediaStatus, x);
2020 * Enable Link Beat and Jabber to start the
2023 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2024 x = ins(port+MediaStatus) & ~dcConverterEnabled;
2025 x |= linkBeatEnable|jabberGuardEnable;
2026 outs(port+MediaStatus, x);
2028 if((ctlr->did & 0xFF00) == 0x5900)
2029 ctlr->busmaster = 0;
2032 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2033 x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
2034 outs(port+MediaStatus, x);
2037 * Start the DC-DC converter.
2038 * Wait > 800 microseconds.
2040 COMMAND(port, EnableDcConverter, 0);
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.
2052 COMMAND(port, SelectRegisterWindow, Wop);
2053 if(ctlr->busmaster == 2)
2054 x = port+TxStatus905;
2062 * adapter statistics, clear the statistics logged into ctlr
2063 * and enable statistics collection.
2065 ilock(&ctlr->wlock);
2067 memset(ctlr->stats, 0, sizeof(ctlr->stats));
2069 COMMAND(port, StatisticsEnable, 0);
2072 * Allocate any receive buffers.
2074 switch(ctlr->busmaster){
2076 ctlr->dnenabled = 1;
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.
2087 ctlr->upenabled = 1;
2088 x = eepromdata(ctlr, 0x0F);
2090 outl(port+PktStatus, upRxEarlyEnable);
2092 if(ctlr->upenabled || ctlr->dnenabled){
2098 ctlr->rbp = rbpalloc(iallocb);
2099 if(ctlr->rbp == nil)
2100 panic("etherlnk3: iallocb: out of memory");
2102 outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
2105 ctlr->rbp = rbpalloc(iallocb);
2106 if(ctlr->rbp == nil)
2107 panic("etherlnk3: iallocb: out of memory");
2112 * Set a base TxStartThresh which will be incremented
2113 * if any txUnderrun errors occur and ensure no RxEarly
2114 * interrupts happen.
2116 ctlr->txthreshold = ETHERMAXTU/2;
2117 COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
2118 COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
2120 iunlock(&ctlr->wlock);
2123 * Linkage to the generic ethernet driver.
2125 ether->attach = attach;
2126 ether->transmit = transmit;
2127 ether->interrupt = interrupt;
2128 ether->ifstat = ifstat;
2130 ether->promiscuous = promiscuous;
2131 ether->multicast = multicast;
2132 ether->shutdown = shutdown;
2139 etherelnk3link(void)
2141 addethercard("elnk3", etherelnk3reset);
2142 addethercard("3C509", etherelnk3reset);
2143 addethercard("3C575", etherelnk3reset);