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"
19 #include "../port/etherif.h"
21 #define XCVRDEBUG if(0)print
24 IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
27 enum { /* all windows */
34 SelectRegisterWindow = 0x0001,
35 EnableDcConverter = 0x0002,
39 Stall = 0x0006, /* 3C90x */
45 RequestInterrupt = 0x000C,
46 AcknowledgeInterrupt = 0x000D,
47 SetInterruptEnable = 0x000E,
48 SetIndicationEnable = 0x000F, /* SetReadZeroMask */
50 SetRxEarlyThresh = 0x0011,
51 SetTxAvailableThresh = 0x0012,
52 SetTxStartThresh = 0x0013,
53 StartDma = 0x0014, /* initiate busmaster operation */
54 StatisticsEnable = 0x0015,
55 StatisticsDisable = 0x0016,
56 DisableDcConverter = 0x0017,
57 SetTxReclaimThresh = 0x0018, /* PIO-only adapters */
58 PowerUp = 0x001B, /* not all adapters */
59 PowerDownFull = 0x001C, /* not all adapters */
60 PowerAuto = 0x001D, /* not all adapters */
63 enum { /* (Global|Rx|Tx)Reset command bits */
64 tpAuiReset = 0x0001, /* 10BaseT and AUI transceivers */
65 endecReset = 0x0002, /* internal Ethernet encoder/decoder */
66 networkReset = 0x0004, /* network interface logic */
67 fifoReset = 0x0008, /* FIFO control logic */
68 aismReset = 0x0010, /* autoinitialise state-machine logic */
69 hostReset = 0x0020, /* bus interface logic */
70 dmaReset = 0x0040, /* bus master logic */
71 vcoReset = 0x0080, /* on-board 10Mbps VCO */
72 updnReset = 0x0100, /* upload/download (Rx/TX) logic */
77 enum { /* Stall command bits */
84 enum { /* SetRxFilter command bits */
85 receiveIndividual = 0x0001, /* match station address */
86 receiveMulticast = 0x0002,
87 receiveBroadcast = 0x0004,
88 receiveAllFrames = 0x0008, /* promiscuous */
91 enum { /* StartDma command bits */
92 Upload = 0x0000, /* transfer data from adapter to memory */
93 Download = 0x0001, /* transfer data from memory to adapter */
96 enum { /* IntStatus bits */
97 interruptLatch = 0x0001,
98 hostError = 0x0002, /* Adapter Failure */
100 txAvailable = 0x0008,
103 intRequested = 0x0040,
104 updateStats = 0x0080,
105 transferInt = 0x0100, /* Bus Master Transfer Complete */
108 busMasterInProgress = 0x0800,
109 commandInProgress = 0x1000,
111 interruptMask = 0x07FE,
114 #define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
115 #define STATUS(port) ins((port)+IntStatusR)
117 enum { /* Window 0 - setup */
120 ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
121 ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
122 ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
123 AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
124 ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
125 EepromCommand = 0x000A,
127 /* AddressConfig Bits */
128 autoSelect9 = 0x0080,
130 /* ConfigControl bits */
132 base10TAvailable9 = 0x0200,
133 coaxAvailable9 = 0x1000,
134 auiAvailable9 = 0x2000,
135 /* EepromCommand bits */
136 EepromReadRegister = 0x0080,
137 EepromReadOffRegister = 0x00B0,
138 EepromRead8bRegister = 0x0230,
142 #define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
143 #define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
144 #define EEPROMDATA(port) ins((port)+EepromData)
146 enum { /* Window 1 - operating set */
150 RxError = 0x0004, /* 3C59[0257] only */
158 alignmentError = 0x0004, /* Framing */
160 oversizedFrame = 0x0010,
161 dribbleBits = 0x0080,
163 rxBytes = 0x1FFF, /* 3C59[0257] mask */
164 rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
165 rxError9 = 0x3800, /* 3C5[078]9 error mask */
167 oversizedFrame9 = 0x0800,
168 dribbleBits9 = 0x1000,
170 alignmentError9 = 0x2000, /* Framing */
173 rxIncomplete = 0x8000,
175 txStatusOverflow = 0x0004,
176 maxCollisions = 0x0008,
179 interruptRequested = 0x0040,
180 txStatusComplete = 0x0080,
183 enum { /* Window 2 - station address */
186 ResetOp905B = 0x000C,
189 enum { /* Window 3 - FIFO management */
192 InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
193 OtherInt = 0x0004, /* 3C59[0257] */
194 RomControl = 0x0006, /* 3C509B, 3C59[27] */
195 MacControl = 0x0006, /* 3C59[0257] */
196 ResetOptions = 0x0008, /* 3C59[0257] */
197 MediaOptions = 0x0008, /* 3C905B */
199 /* InternalConfig bits */
200 disableBadSsdDetect = 0x00000100,
201 ramLocation = 0x00000200, /* 0 external, 1 internal */
202 ramPartition5to3 = 0x00000000,
203 ramPartition3to1 = 0x00010000,
204 ramPartition1to1 = 0x00020000,
205 ramPartition3to5 = 0x00030000,
206 ramPartitionMask = 0x00030000,
207 xcvr10BaseT = 0x00000000,
208 xcvrAui = 0x00100000, /* 10BASE5 */
209 xcvr10Base2 = 0x00300000,
210 xcvr100BaseTX = 0x00400000,
211 xcvr100BaseFX = 0x00500000,
212 xcvrMii = 0x00600000,
213 xcvrMask = 0x00700000,
214 autoSelect = 0x01000000,
215 /* MacControl bits */
216 deferExtendEnable = 0x0001,
217 deferTIMERSelect = 0x001E, /* mask */
218 fullDuplexEnable = 0x0020,
219 allowLargePackets = 0x0040,
220 extendAfterCollision = 0x0080, /* 3C90xB */
221 flowControlEnable = 0x0100, /* 3C90xB */
222 vltEnable = 0x0200, /* 3C90xB */
223 /* ResetOptions bits */
224 baseT4Available = 0x0001,
225 baseTXAvailable = 0x0002,
226 baseFXAvailable = 0x0004,
227 base10TAvailable = 0x0008,
228 coaxAvailable = 0x0010,
229 auiAvailable = 0x0020,
230 miiConnector = 0x0040,
233 enum { /* Window 4 - diagnostic */
234 Wdiagnostic = 0x0004,
236 VcoDiagnostic = 0x0002,
237 FifoDiagnostic = 0x0004,
238 NetworkDiagnostic = 0x0006,
239 PhysicalMgmt = 0x0008,
240 MediaStatus = 0x000A,
242 UpperBytesOk = 0x000D,
243 /* FifoDiagnostic bits */
247 /* PhysicalMgmt bits */
251 cat5LinkTestDefeat = 0x8000,
252 /* MediaStatus bits */
253 dataRate100 = 0x0002,
254 crcStripDisable = 0x0004,
255 enableSqeStats = 0x0008,
256 collisionDetect = 0x0010,
257 carrierSense = 0x0020,
258 jabberGuardEnable = 0x0040,
259 linkBeatEnable = 0x0080,
260 jabberDetect = 0x0200,
261 polarityReversed = 0x0400,
262 linkBeatDetect = 0x0800,
264 dcConverterEnabled = 0x4000,
265 auiDisable = 0x8000, /* 10BaseT transceiver selected */
268 enum { /* Window 5 - internal state */
271 TxStartThresh = 0x0000,
272 TxAvailableThresh = 0x0002,
273 RxEarlyThresh = 0x0006,
275 InterruptEnable = 0x000A,
276 IndicationEnable = 0x000C,
279 enum { /* Window 6 - statistics */
280 Wstatistics = 0x0006,
282 CarrierLost = 0x0000,
284 MultipleColls = 0x0002,
285 SingleCollFrames = 0x0003,
286 LateCollisions = 0x0004,
288 FramesXmittedOk = 0x0006,
289 FramesRcvdOk = 0x0007,
290 FramesDeferred = 0x0008,
291 UpperFramesOk = 0x0009,
292 BytesRcvdOk = 0x000A,
293 BytesXmittedOk = 0x000C,
296 enum { /* Window 7 - bus master operations */
299 MasterAddress = 0x0000,
301 MasterStatus = 0x000C,
302 /* MasterStatus bits */
303 masterAbort = 0x0001,
304 targetAbort = 0x0002,
305 targetRetry = 0x0004,
307 masterDownload = 0x1000,
308 masterUpload = 0x4000,
309 masterInProgress = 0x8000,
314 enum { /* 3C90x extended register set */
315 TIMER905 = 0x001A, /* 8-bits */
316 TxStatus905 = 0x001B, /* 8-bits */
317 PktStatus = 0x0020, /* 32-bits */
318 DnListPtr = 0x0024, /* 32-bits, 8-byte aligned */
319 FragAddr = 0x0028, /* 32-bits */
320 FragLen = 0x002C, /* 16-bits */
321 ListOffset = 0x002E, /* 8-bits */
322 TxFreeThresh = 0x002F, /* 8-bits */
323 UpPktStatus = 0x0030, /* 32-bits */
324 FreeTIMER = 0x0034, /* 16-bits */
325 UpListPtr = 0x0038, /* 32-bits, 8-byte aligned */
328 fragLast = 0x00000001,
329 dnCmplReq = 0x00000002,
330 dnStalled = 0x00000004,
331 upCompleteX = 0x00000008,
332 dnCompleteX = 0x00000010,
333 upRxEarlyEnable = 0x00000020,
334 armCountdown = 0x00000040,
335 dnInProg = 0x00000080,
336 counterSpeed = 0x00000010, /* 0 3.2uS, 1 320nS */
337 countdownMode = 0x00000020,
338 /* UpPktStatus bits (dpd->control) */
339 upPktLenMask = 0x00001FFF,
340 upStalled = 0x00002000,
341 upError = 0x00004000,
342 upPktComplete = 0x00008000,
343 upOverrun = 0x00010000, /* RxError<<16 */
344 upRuntFrame = 0x00020000,
345 upAlignmentError = 0x00040000,
346 upCRCError = 0x00080000,
347 upOversizedFrame = 0x00100000,
348 upDribbleBits = 0x00800000,
349 upOverflow = 0x01000000,
351 dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */
353 updnLastFrag = 0x80000000, /* (dpd->len) */
360 * Up/Dn Packet Descriptors.
361 * The hardware info (np, control, addr, len) must be 8-byte aligned
362 * and this structure size must be a multiple of 8.
364 typedef struct Pd Pd;
366 ulong np; /* next pointer */
367 ulong control; /* FSH or UpPktStatus */
375 typedef struct Ctlr Ctlr;
376 typedef struct Ctlr {
384 Lock wlock; /* window access */
388 Block* rbp; /* receive buffer */
390 Block* txbp; /* FIFO -based transmission */
394 int nup; /* full-busmaster -based reception */
399 int ndn; /* full-busmaster -based transmission */
406 long interrupts; /* statistics */
407 long bogusinterrupts;
409 long stats[BytesRcvdOk+3];
421 int xcvr; /* transceiver type */
422 int eepromcmd; /* EEPROM read command */
423 int rxstatus9; /* old-style RxStatus register */
424 int rxearly; /* RxEarlyThreshold */
425 int ts; /* threshold shift */
428 ulong cbfnpa; /* CardBus functions */
432 static Ctlr* ctlrhead;
433 static Ctlr* ctlrtail;
442 * Create rings for the receive and transmit sides.
443 * Take care with alignment:
444 * make sure ring base is 8-byte aligned;
445 * make sure each entry is 8-byte aligned.
447 ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
448 if(ctlr->upbase == nil)
449 panic("etherlnk3: can't allocate upr");
450 ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
453 for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
454 pd->np = PADDR(&prev->np);
456 bp = iallocb(sizeof(Etherpkt));
458 panic("etherlnk3: iallocb: out of memory");
459 pd->addr = PADDR(bp->rp);
460 pd->len = updnLastFrag|sizeof(Etherpkt);
466 ctlr->uphead = ctlr->upr;
468 ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
469 if(ctlr->dnbase == nil)
470 panic("etherlnk3: can't allocate dnr");
471 ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
474 for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
478 ctlr->dnhead = ctlr->dnr;
479 ctlr->dntail = ctlr->dnr;
484 rbpalloc(Block* (*f)(int))
490 * The receive buffers must be on a 32-byte
491 * boundary for EISA busmastering.
493 if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
494 addr = (ulong)bp->base;
495 addr = ROUNDUP(addr, 32);
496 bp->rp = (uchar*)addr;
503 startdma(Ether* ether, ulong address)
510 w = (STATUS(port)>>13) & 0x07;
511 COMMAND(port, SelectRegisterWindow, Wmaster);
513 wp = KADDR(inl(port+MasterAddress));
514 status = ins(port+MasterStatus);
515 if(status & (masterInProgress|targetAbort|masterAbort))
516 print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
517 outs(port+MasterStatus, masterMask);
518 outl(port+MasterAddress, address);
519 outs(port+MasterLen, sizeof(Etherpkt));
520 COMMAND(port, StartDma, Upload);
522 COMMAND(port, SelectRegisterWindow, w);
527 promiscuous(void* arg, int on)
535 filter = receiveBroadcast|receiveIndividual;
537 filter |= receiveMulticast;
539 filter |= receiveAllFrames;
540 COMMAND(port, SetRxFilter, filter);
544 multicast(void* arg, uchar *addr, int on)
554 filter = receiveBroadcast|receiveIndividual;
556 filter |= receiveMulticast;
558 filter |= receiveAllFrames;
559 COMMAND(port, SetRxFilter, filter);
562 /* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
564 intrackcb(ulong *cbfn)
578 iunlock(&ctlr->wlock);
585 * Set the receiver packet filter for this and broadcast addresses,
586 * set the interrupt masks for all interrupts, enable the receiver
589 promiscuous(ether, ether->prom);
592 if(ctlr->busmaster == 1)
593 x &= ~(rxEarly|rxComplete);
598 x &= ~(rxEarly|rxComplete);
600 COMMAND(port, SetIndicationEnable, x);
601 COMMAND(port, SetInterruptEnable, x);
602 COMMAND(port, RxEnable, 0);
603 COMMAND(port, TxEnable, 0);
606 * If this is a CardBus card, acknowledge any interrupts.
608 if(ctlr->cbfn != nil)
609 intrackcb(ctlr->cbfn);
612 * Prime the busmaster channel for receiving directly into a
613 * receive packet buffer if necessary.
615 if(ctlr->busmaster == 1)
616 startdma(ether, PADDR(ctlr->rbp->rp));
619 outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
623 iunlock(&ctlr->wlock);
627 statistics(Ether* ether)
636 * 3C59[27] require a read between a PIO write and
637 * reading a statistics register.
639 w = (STATUS(port)>>13) & 0x07;
640 COMMAND(port, SelectRegisterWindow, Wstatistics);
643 for(i = 0; i < UpperFramesOk; i++)
644 ctlr->stats[i] += inb(port+i) & 0xFF;
645 u = inb(port+UpperFramesOk) & 0xFF;
646 ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
647 ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
648 ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
649 ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
656 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
658 ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
662 COMMAND(port, SelectRegisterWindow, w);
666 txstart(Ether* ether)
676 * Attempt to top-up the transmit FIFO. If there's room simply
677 * stuff in the packet length (unpadded to a dword boundary), the
678 * packet data (padded) and remove the packet from the queue.
679 * If there's no room post an interrupt for when there is.
680 * This routine is called both from the top level and from interrupt
681 * level and expects to be called with ctlr->wlock already locked
682 * and the correct register window (Wop) in place.
690 bp = qget(ether->oq);
695 len = ROUNDUP(BLEN(bp), 4);
696 if(len+4 <= ins(port+TxFree)){
697 outl(port+Fifo, BLEN(bp));
698 outsl(port+Fifo, bp->rp, len/4);
706 if(ctlr->txbusy == 0){
708 COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
716 txstart905(Ether* ether)
719 int port, stalled, timeo;
727 * Free any completed packets.
731 if(PADDR(&pd->np) == inl(port+DnListPtr))
743 while(ctlr->dnq < (ctlr->ndn-1)){
744 bp = qget(ether->oq);
748 pd = ctlr->dnhead->next;
750 pd->control = dnIndicate|BLEN(bp);
751 pd->addr = PADDR(bp->rp);
752 pd->len = updnLastFrag|BLEN(bp);
755 if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
756 COMMAND(port, Stall, dnStall);
757 for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
760 print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
765 ctlr->dnhead->np = PADDR(&pd->np);
766 ctlr->dnhead->control &= ~dnIndicate;
775 if(ctlr->dnq > ctlr->dnqmax)
776 ctlr->dnqmax = ctlr->dnq;
779 * If the adapter is not currently processing anything
780 * and there is something on the queue, start it processing.
782 if(inl(port+DnListPtr) == 0 && ctlr->dnq)
783 outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
785 COMMAND(port, Stall, dnUnStall);
789 transmit(Ether* ether)
801 w = (STATUS(port)>>13) & 0x07;
802 COMMAND(port, SelectRegisterWindow, Wop);
804 COMMAND(port, SelectRegisterWindow, w);
806 iunlock(&ctlr->wlock);
810 receive905(Ether* ether)
820 if(inl(port+UpPktStatus) & upStalled)
823 for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
824 if(pd->control & upError){
825 if(pd->control & upOverrun)
827 if(pd->control & (upOversizedFrame|upRuntFrame))
829 if(pd->control & upAlignmentError)
831 if(pd->control & upCRCError)
834 else if(bp = iallocb(sizeof(Etherpkt)+4)){
835 len = pd->control & rxBytes;
836 pd->bp->wp = pd->bp->rp+len;
837 etheriq(ether, pd->bp);
839 pd->addr = PADDR(bp->rp);
844 COMMAND(port, Stall, upUnStall);
856 receive(Ether* ether)
858 int len, port, rxerror, rxstatus;
865 while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
866 if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
870 * If there was an error, log it and continue.
871 * Unfortunately the 3C5[078]9 has the error info in the status register
872 * and the 3C59[0257] implement a separate RxError register.
874 if(rxstatus & rxError){
876 switch(rxstatus & rxError9){
882 case oversizedFrame9:
887 case alignmentError9:
898 rxerror = inb(port+RxError);
899 if(rxerror & rxOverrun)
901 if(rxerror & (oversizedFrame|runtFrame))
903 if(rxerror & alignmentError)
905 if(rxerror & crcError)
911 * If there was an error or a new receive buffer can't be
912 * allocated, discard the packet and go on to the next.
914 if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){
915 COMMAND(port, RxDiscard, 0);
916 while(STATUS(port) & commandInProgress)
919 if(ctlr->busmaster == 1)
920 startdma(ether, PADDR(ctlr->rbp->rp));
926 * A valid receive packet awaits:
927 * if using PIO, read it into the buffer;
928 * discard the packet from the FIFO;
929 * if using busmastering, start a new transfer for
930 * the next packet and as a side-effect get the
931 * end-pointer of the one just received;
932 * pass the packet on to whoever wants it.
934 if(ctlr->busmaster == 0 || ctlr->busmaster == 2){
935 len = (rxstatus & rxBytes9);
936 ctlr->rbp->wp = ctlr->rbp->rp + len;
937 insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4));
940 COMMAND(port, RxDiscard, 0);
941 while(STATUS(port) & commandInProgress)
944 if(ctlr->busmaster == 1)
945 ctlr->rbp->wp = startdma(ether, PADDR(bp->rp));
947 etheriq(ether, ctlr->rbp);
965 interrupt(Ureg*, void* arg)
968 int port, status, s, txstatus, w, x;
976 status = STATUS(port);
977 if(!(status & (interruptMask|interruptLatch))){
978 ctlr->bogusinterrupts++;
979 iunlock(&ctlr->wlock);
982 w = (status>>13) & 0x07;
983 COMMAND(port, SelectRegisterWindow, Wop);
986 if(ctlr->busmaster == 2)
987 ctlr->timer[0] += inb(port+TIMER905) & 0xFF;
989 ctlr->timer[0] += inb(port+TIMER) & 0xFF;
992 if(status & hostError){
994 * Adapter failure, try to find out why, reset if
995 * necessary. What happens if Tx is active and a reset
996 * occurs, need to retransmit? This probably isn't right.
998 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
999 x = ins(port+FifoDiagnostic);
1000 COMMAND(port, SelectRegisterWindow, Wop);
1002 if (status == 0xFFFF && x == 0xFFFF && ejectable(ctlr->did)) {
1003 print("#l%d: Card ejected?\n", ether->ctlrno);
1004 iunlock(&ctlr->wlock);
1008 print("#l%d: status 0x%uX, diag 0x%uX\n",
1009 ether->ctlrno, status, x);
1012 if(ctlr->busmaster == 0)
1013 COMMAND(port, TxReset, 0);
1015 COMMAND(port, TxReset, (updnReset|dmaReset));
1016 COMMAND(port, TxEnable, 0);
1021 * This shouldn't happen...
1022 * Reset the receiver and restore the filter and RxEarly
1023 * threshold before re-enabling.
1024 * Need to restart any busmastering?
1026 COMMAND(port, SelectRegisterWindow, Wstate);
1027 s = (port+RxFilter) & 0x000F;
1028 COMMAND(port, SelectRegisterWindow, Wop);
1029 COMMAND(port, RxReset, 0);
1030 while(STATUS(port) & commandInProgress)
1032 COMMAND(port, SetRxFilter, s);
1033 COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
1034 COMMAND(port, RxEnable, 0);
1037 status &= ~hostError;
1040 if(status & (transferInt|rxComplete)){
1042 status &= ~(transferInt|rxComplete);
1045 if(status & (upComplete)){
1046 COMMAND(port, AcknowledgeInterrupt, upComplete);
1048 status &= ~upComplete;
1049 ctlr->upinterrupts++;
1052 if(status & txComplete){
1054 * Pop the TxStatus stack, accumulating errors.
1055 * Adjust the TX start threshold if there was an underrun.
1056 * If there was a Jabber or Underrun error, reset
1057 * the transmitter, taking care not to reset the dma logic
1058 * as a busmaster receive may be in progress.
1059 * For all conditions enable the transmitter.
1061 if(ctlr->busmaster == 2)
1062 txstatus = port+TxStatus905;
1064 txstatus = port+TxStatus;
1067 if(x = inb(txstatus))
1070 }while(STATUS(port) & txComplete);
1073 if(ctlr->dnenabled){
1074 while(inl(port+PktStatus) & dnInProg)
1077 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1078 while(ins(port+MediaStatus) & txInProg)
1080 COMMAND(port, SelectRegisterWindow, Wop);
1081 if(ctlr->txthreshold < ETHERMAXTU)
1082 ctlr->txthreshold += ETHERMINTU;
1086 * According to the manual, maxCollisions does not require
1087 * a TxReset, merely a TxEnable. However, evidence points to
1088 * it being necessary on the 3C905. The jury is still out.
1089 * On busy or badly configured networks maxCollisions can
1090 * happen frequently enough for messages to be annoying so
1091 * keep quiet about them by popular request.
1093 if(s & (txJabber|txUnderrun|maxCollisions)){
1094 if(ctlr->busmaster == 0)
1095 COMMAND(port, TxReset, 0);
1097 COMMAND(port, TxReset, (updnReset|dmaReset));
1098 while(STATUS(port) & commandInProgress)
1100 COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
1101 if(ctlr->busmaster == 2)
1102 outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
1104 status |= dnComplete;
1107 if(s & ~(txStatusComplete|maxCollisions))
1108 print("#l%d: txstatus 0x%uX, threshold %d\n",
1109 ether->ctlrno, s, ctlr->txthreshold);
1110 COMMAND(port, TxEnable, 0);
1112 status &= ~txComplete;
1113 status |= txAvailable;
1116 if(status & txAvailable){
1117 COMMAND(port, AcknowledgeInterrupt, txAvailable);
1120 status &= ~txAvailable;
1123 if(status & dnComplete){
1124 COMMAND(port, AcknowledgeInterrupt, dnComplete);
1126 status &= ~dnComplete;
1127 ctlr->dninterrupts++;
1130 if(status & updateStats){
1132 status &= ~updateStats;
1136 * Currently, this shouldn't happen.
1138 if(status & rxEarly){
1139 COMMAND(port, AcknowledgeInterrupt, rxEarly);
1144 * Panic if there are any interrupts not dealt with.
1146 if(status & interruptMask)
1147 panic("#l%d: interrupt mask 0x%uX", ether->ctlrno, status);
1149 COMMAND(port, AcknowledgeInterrupt, interruptLatch);
1150 if(ctlr->cbfn != nil)
1151 intrackcb(ctlr->cbfn);
1153 }while((status = STATUS(port)) & (interruptMask|interruptLatch));
1155 if(ctlr->busmaster == 2)
1156 ctlr->timer[1] += inb(port+TIMER905) & 0xFF;
1158 ctlr->timer[1] += inb(port+TIMER) & 0xFF;
1160 COMMAND(port, SelectRegisterWindow, w);
1161 iunlock(&ctlr->wlock);
1165 ifstat(Ether* ether, void* a, long n, ulong offset)
1176 ilock(&ctlr->wlock);
1178 iunlock(&ctlr->wlock);
1180 p = smalloc(READSTR);
1181 len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
1182 len += snprint(p+len, READSTR-len, "bogusinterrupts: %lud\n", ctlr->bogusinterrupts);
1183 len += snprint(p+len, READSTR-len, "timer: %lud %lud\n",
1184 ctlr->timer[0], ctlr->timer[1]);
1185 len += snprint(p+len, READSTR-len, "carrierlost: %lud\n",
1186 ctlr->stats[CarrierLost]);
1187 len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n",
1188 ctlr->stats[SqeErrors]);
1189 len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n",
1190 ctlr->stats[MultipleColls]);
1191 len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n",
1192 ctlr->stats[SingleCollFrames]);
1193 len += snprint(p+len, READSTR-len, "latecollisions: %lud\n",
1194 ctlr->stats[LateCollisions]);
1195 len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n",
1196 ctlr->stats[RxOverruns]);
1197 len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n",
1198 ctlr->stats[FramesXmittedOk]);
1199 len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n",
1200 ctlr->stats[FramesRcvdOk]);
1201 len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n",
1202 ctlr->stats[FramesDeferred]);
1203 len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n",
1204 ctlr->stats[BytesRcvdOk]);
1205 len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n",
1206 ctlr->stats[BytesRcvdOk+1]);
1208 if(ctlr->upenabled){
1209 if(ctlr->upqmax > ctlr->upqmaxhw)
1210 ctlr->upqmaxhw = ctlr->upqmax;
1211 len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d h %d s %lud\n",
1212 ctlr->upqueued, ctlr->upinterrupts,
1213 ctlr->upqmax, ctlr->upqmaxhw, ctlr->upstalls);
1216 if(ctlr->dnenabled){
1217 if(ctlr->dnqmax > ctlr->dnqmaxhw)
1218 ctlr->dnqmaxhw = ctlr->dnqmax;
1219 len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d h %d\n",
1220 ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax, ctlr->dnqmaxhw);
1224 snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]);
1226 n = readstr(offset, a, n, p);
1235 COMMAND(port, TxReset, 0);
1236 while(STATUS(port) & commandInProgress)
1238 COMMAND(port, RxReset, 0);
1239 while(STATUS(port) & commandInProgress)
1244 tcmadapter(int port, int irq, Pcidev* pcidev)
1248 ctlr = malloc(sizeof(Ctlr));
1250 print("etherelnk3: can't allocate memory\n");
1255 ctlr->pcidev = pcidev;
1256 ctlr->eepromcmd = EepromReadRegister;
1259 ctlrtail->next = ctlr;
1268 * Write two 0 bytes to identify the IDport and then reset the
1269 * ID sequence. Then send the ID sequence to the card to get
1270 * the card into command state.
1277 static int reset, untag;
1281 * reset any adapters listening
1293 for(al = 0xFF, i = 0; i < 255; i++){
1305 * write ID sequence to get the attention of all adapters;
1306 * untag all adapters.
1307 * If a global reset is done here on all adapters it will confuse
1308 * any ISA cards configured for EISA mode.
1323 * Do the little configuration dance:
1325 * 2. write the ID sequence to get to command state.
1330 * 3. Read the Manufacturer ID from the EEPROM.
1331 * This is done by writing the IDPort with 0x87 (0x80
1332 * is the 'read EEPROM' command, 0x07 is the offset of
1333 * the Manufacturer ID field in the EEPROM).
1334 * The data comes back 1 bit at a time.
1335 * A delay seems necessary between reading the bits.
1337 * If the ID doesn't match, there are no more adapters.
1341 for(x = 0, i = 0; i < 16; i++){
1344 x |= inb(IDport) & 0x01;
1350 * 3. Read the Address Configuration from the EEPROM.
1351 * The Address Configuration field is at offset 0x08 in the EEPROM).
1354 for(acr = 0, i = 0; i < 16; i++){
1357 acr |= inb(IDport) & 0x01;
1360 return (acr & 0x1F)*0x10 + 0x200;
1369 * Attempt to activate all adapters. If adapter is set for
1370 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
1373 while(port = activate()){
1374 if(ioalloc(port, 0x10, 0, "tcm509isa") < 0){
1375 print("tcm509isa: port 0x%uX in use\n", port);
1380 * 6. Tag the adapter so it won't respond in future.
1389 * 6. Activate the adapter by writing the Activate command
1396 * 8. Can now talk to the adapter's I/O base addresses.
1397 * Use the I/O base address from the acr just read.
1399 * Enable the adapter and clear out any lingering status
1402 while(STATUS(port) & commandInProgress)
1404 COMMAND(port, SelectRegisterWindow, Wsetup);
1405 outs(port+ConfigControl, Ena);
1408 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1410 irq = (ins(port+ResourceConfig)>>12) & 0x0F;
1411 tcmadapter(port, irq, nil);
1419 int irq, port, slot;
1422 * Check if this is an EISA machine.
1423 * If not, nothing to do.
1425 if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
1429 * Continue through the EISA slots looking for a match on both
1430 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
1431 * If an adapter is found, select window 0, enable it and clear
1432 * out any lingering status and interrupts.
1434 for(slot = 1; slot < MaxEISA; slot++){
1436 if(ioalloc(port, 0x1000, 0, "tcm5XXeisa") < 0){
1437 print("tcm5XXeisa: port 0x%uX in use\n", port);
1440 if(ins(port+0xC80+ManufacturerID) != 0x6D50){
1444 x = ins(port+0xC80+ProductID);
1445 if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900){
1450 COMMAND(port, SelectRegisterWindow, Wsetup);
1451 outs(port+ConfigControl, Ena);
1454 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1456 irq = (ins(port+ResourceConfig)>>12) & 0x0F;
1457 tcmadapter(port, irq, nil);
1469 while(p = pcimatch(p, 0x10B7, 0)){
1470 if(p->ccrb != 0x02 || p->ccru != 0)
1473 * Not prepared to deal with memory-mapped
1476 if(!(p->mem[0].bar & 0x01))
1478 port = p->mem[0].bar & ~0x01;
1479 if((port = ioalloc((port == 0)? -1: port, p->mem[0].size,
1480 0, "tcm59Xpci")) < 0){
1481 print("tcm59Xpci: port 0x%uX in use\n", port);
1487 COMMAND(port, AcknowledgeInterrupt, 0xFF);
1489 ctlr = tcmadapter(port, irq, p);
1496 ctlr->eepromcmd = EepromRead8bRegister;
1497 ctlr->cbfnpa = p->mem[2].bar&~0x0F;
1498 ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
1501 ctlr->eepromcmd = EepromReadOffRegister;
1502 ctlr->cbfnpa = p->mem[2].bar&~0x0F;
1503 ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
1510 static char* tcmpcmcia[] = {
1511 "3C589", /* 3COM 589[ABCD] */
1512 "3C562", /* 3COM 562 */
1513 "589E", /* 3COM Megahertz 589E */
1518 tcm5XXpcmcia(Ether* ether)
1523 if(ether->type == nil)
1526 for(i = 0; tcmpcmcia[i] != nil; i++){
1527 if(cistrcmp(ether->type, tcmpcmcia[i]))
1529 if(ctlr = tcmadapter(ether->port, ether->irq, nil))
1538 setxcvr(Ctlr* ctlr, int xcvr)
1543 if(ctlr->rxstatus9){
1544 COMMAND(port, SelectRegisterWindow, Wsetup);
1545 x = ins(port+AddressConfig) & ~xcvrMask9;
1546 x |= (xcvr>>20)<<14;
1547 outs(port+AddressConfig, x);
1550 COMMAND(port, SelectRegisterWindow, Wfifo);
1551 x = inl(port+InternalConfig) & ~xcvrMask;
1553 outl(port+InternalConfig, x);
1560 setfullduplex(int port)
1564 COMMAND(port, SelectRegisterWindow, Wfifo);
1565 x = ins(port+MacControl);
1566 outs(port+MacControl, fullDuplexEnable|x);
1572 miimdi(int port, int n)
1577 * Read n bits from the MII Management Register.
1580 for(i = n-1; i >= 0; i--){
1581 if(ins(port) & mgmtData)
1584 outs(port, mgmtClk);
1594 miimdo(int port, int bits, int n)
1599 * Write n bits to the MII Management Register.
1601 for(i = n-1; i >= 0; i--){
1603 mdo = mgmtDir|mgmtData;
1608 outs(port, mdo|mgmtClk);
1616 miir(int port, int phyad, int regad)
1620 w = (STATUS(port)>>13) & 0x07;
1621 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1622 port += PhysicalMgmt;
1626 * ST+OP+PHYAD+REGAD;
1627 * TA + 16 data bits.
1629 miimdo(port, 0xFFFFFFFF, 32);
1630 miimdo(port, 0x1800|(phyad<<5)|regad, 14);
1631 data = miimdi(port, 18);
1633 port -= PhysicalMgmt;
1634 COMMAND(port, SelectRegisterWindow, w);
1639 return data & 0xFFFF;
1647 for(i = 0; i < 32; i++){
1648 if((x = miir(port, i, 2)) == -1 || x == 0)
1651 x |= miir(port, i, 3)>>10;
1652 XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
1665 "10BaseT", base10TAvailable, xcvr10BaseT,
1666 "10Base2", coaxAvailable, xcvr10Base2,
1667 "100BaseTX", baseTXAvailable, xcvr100BaseTX,
1668 "100BaseFX", baseFXAvailable, xcvr100BaseFX,
1669 "aui", auiAvailable, xcvrAui,
1670 "mii", miiConnector, xcvrMii
1674 autoselect(Ctlr* ctlr)
1679 * Pathetic attempt at automatic media selection.
1680 * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
1681 * cards operational.
1682 * It's a bonus if it works for anything else.
1685 if(ctlr->rxstatus9){
1686 COMMAND(port, SelectRegisterWindow, Wsetup);
1687 x = ins(port+ConfigControl);
1689 if(x & base10TAvailable9)
1690 media |= base10TAvailable;
1691 if(x & coaxAvailable9)
1692 media |= coaxAvailable;
1693 if(x & auiAvailable9)
1694 media |= auiAvailable;
1697 COMMAND(port, SelectRegisterWindow, Wfifo);
1698 media = ins(port+ResetOptions);
1700 XCVRDEBUG("autoselect: media %uX\n", media);
1702 if(media & miiConnector)
1705 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1706 XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
1708 if(media & baseTXAvailable){
1710 * Must have InternalConfig register.
1712 setxcvr(ctlr, xcvr100BaseTX);
1714 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1715 x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
1716 outs(port+MediaStatus, linkBeatEnable|x);
1719 if(ins(port+MediaStatus) & linkBeatDetect)
1720 return xcvr100BaseTX;
1721 outs(port+MediaStatus, x);
1724 if(media & base10TAvailable){
1725 setxcvr(ctlr, xcvr10BaseT);
1727 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1728 x = ins(port+MediaStatus) & ~dcConverterEnabled;
1729 outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
1732 XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
1733 if(ins(port+MediaStatus) & linkBeatDetect)
1735 outs(port+MediaStatus, x);
1745 eepromdata(Ctlr* ctlr, int offset)
1751 COMMAND(port, SelectRegisterWindow, Wsetup);
1752 while(EEPROMBUSY(port))
1754 EEPROMCMD(port, ctlr->eepromcmd, offset);
1755 while(EEPROMBUSY(port))
1757 return EEPROMDATA(port);
1761 resetctlr(Ctlr *ctlr)
1763 int x, port = ctlr->port;
1766 x = ins(port+ResetOp905B);
1767 XCVRDEBUG("905[BC] reset ops 0x%uX\n", x);
1769 if(ctlr->did == 0x5157){
1770 x |= 0x0010; /* Invert LED */
1771 outs(port+ResetOp905B, x);
1773 if(ctlr->did == 0x6056){
1775 outs(port+ResetOp905B, x);
1777 COMMAND(port, SelectRegisterWindow, Wsetup);
1783 shutdown(Ether *ether)
1785 print("etherelnk3 shutting down\n");
1786 resetctlr(ether->ctlr);
1790 etherelnk3reset(Ether* ether)
1795 static int scandone;
1796 int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x;
1799 * Scan for adapter on PCI, EISA and finally
1800 * using the little ISA configuration dance.
1810 * Any adapter matches if no ether->port is supplied,
1811 * otherwise the ports must match.
1813 for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
1816 if(ether->port == 0 || ether->port == ctlr->port){
1821 if(ctlr == nil && (ctlr = tcm5XXpcmcia(ether)) == 0)
1827 ether->irq = ctlr->irq;
1828 if(ctlr->pcidev != nil)
1829 ether->tbdf = ctlr->pcidev->tbdf;
1831 ether->tbdf = BUSUNKNOWN;
1834 * Read the DeviceID from the EEPROM, it's at offset 0x03,
1835 * and do something depending on capabilities.
1837 switch(ctlr->did = eepromdata(ctlr, 0x03)){
1838 case 0x5157: /* 3C575 Cyclone */
1841 case 0x4500: /* 3C450 HomePNA Tornado */
1842 case 0x7646: /* 3CSOHO100-TX */
1843 case 0x9055: /* 3C905B-TX */
1844 case 0x9200: /* 3C905C-TX */
1845 case 0x9201: /* 3C920 */
1846 case 0x9805: /* 3C9805: 3C980-TX Python-T 10/100baseTX */
1848 case 0x9000: /* 3C900-TPO */
1849 case 0x9001: /* 3C900-COMBO */
1850 case 0x9005: /* 3C900B-COMBO */
1851 case 0x9050: /* 3C905-TX */
1852 case 0x9051: /* 3C905-T4 */
1853 if(BUSTYPE(ether->tbdf) != BusPCI)
1855 ctlr->busmaster = 2;
1857 case 0x5900: /* 3C590-[TP|COMBO|TPO] */
1858 case 0x5920: /* 3C592-[TP|COMBO|TPO] */
1859 case 0x5950: /* 3C595-TX */
1860 case 0x5951: /* 3C595-T4 */
1861 case 0x5952: /* 3C595-MII */
1862 case 0x5970: /* 3C597-TX */
1863 case 0x5971: /* 3C597-T4 */
1864 case 0x5972: /* 3C597-MII */
1865 ctlr->busmaster = 1;
1867 COMMAND(port, SelectRegisterWindow, Wfifo);
1868 ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
1869 ctlr->rxearly = 8188;
1870 ctlr->rxstatus9 = 0;
1874 ctlr->busmaster = 0;
1875 COMMAND(port, SelectRegisterWindow, Wsetup);
1876 x = ins(port+AddressConfig);
1877 ctlr->xcvr = ((x & xcvrMask9)>>14)<<20;
1879 ctlr->xcvr |= autoSelect;
1880 ctlr->rxearly = 2044;
1881 ctlr->rxstatus9 = 1;
1884 if(ctlr->rxearly >= 2048)
1888 * Check if the adapter's station address is to be overridden.
1889 * If not, read it from the EEPROM and set in ether->ea prior to
1890 * loading the station address in Wstation.
1891 * The EEPROM returns 16-bits at a time.
1893 memset(ea, 0, Eaddrlen);
1894 if(memcmp(ea, ether->ea, Eaddrlen) == 0){
1895 for(i = 0; i < Eaddrlen/2; i++){
1896 x = eepromdata(ctlr, i);
1897 ether->ea[2*i] = x>>8;
1898 ether->ea[2*i+1] = x;
1902 COMMAND(port, SelectRegisterWindow, Wstation);
1903 for(i = 0; i < Eaddrlen; i++)
1904 outb(port+i, ether->ea[i]);
1907 * Enable the transceiver if necessary and determine whether
1908 * busmastering can be used. Due to bugs in the first revision
1909 * of the 3C59[05], don't use busmastering at 10Mbps.
1911 XCVRDEBUG("reset: xcvr %uX\n", ctlr->xcvr);
1914 * Allow user to specify desired media in plan9.ini
1916 for(i = 0; i < ether->nopt; i++){
1917 if(cistrncmp(ether->opt[i], "media=", 6) != 0)
1919 p = ether->opt[i]+6;
1920 for(j = 0; j < nelem(media); j++)
1921 if(cistrcmp(p, media[j].name) == 0)
1922 ctlr->xcvr = media[j].xcvr;
1926 * forgive me, but i am weak
1930 if(ctlr->xcvr & autoSelect)
1931 ctlr->xcvr = autoselect(ctlr);
1941 ctlr->xcvr = xcvrMii;
1945 XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did);
1952 if(ctlr->did == 0x5157)
1954 else if(ctlr->did == 0x6056)
1955 phyaddr = scanphy(port);
1958 for(i = 0; i < 7; i++)
1959 XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
1962 for(timeo = 0; timeo < 30; timeo++){
1963 phystat = miir(port, phyaddr, 0x01);
1966 XCVRDEBUG(" %2.2uX", phystat);
1969 XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
1972 anar = miir(port, phyaddr, 0x04);
1973 anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
1975 miir(port, phyaddr, 0x00);
1976 XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
1977 anar, anlpar, miir(port, phyaddr, 0x00),
1978 miir(port, phyaddr, 0x01));
1979 for(i = 0; i < ether->nopt; i++){
1980 if(cistrcmp(ether->opt[i], "fullduplex") == 0)
1982 else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
1984 else if(cistrcmp(ether->opt[i], "force100") == 0)
1987 XCVRDEBUG("mii anar: %uX\n", anar);
1988 if(anar & 0x0100){ /* 100BASE-TXFD */
1990 setfullduplex(port);
1992 else if(anar & 0x0200){ /* 100BASE-T4 */
1995 else if(anar & 0x0080) /* 100BASE-TX */
1997 else if(anar & 0x0040) /* 10BASE-TFD */
1998 setfullduplex(port);
1999 else{ /* 10BASE-T */
2005 COMMAND(port, SelectRegisterWindow, Wfifo);
2006 x = inl(port+InternalConfig) & ~ramPartitionMask;
2007 outl(port+InternalConfig, x|ramPartition1to1);
2009 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2010 x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
2011 x |= linkBeatEnable;
2012 outs(port+MediaStatus, x);
2019 * Enable Link Beat and Jabber to start the
2022 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2023 x = ins(port+MediaStatus) & ~dcConverterEnabled;
2024 x |= linkBeatEnable|jabberGuardEnable;
2025 outs(port+MediaStatus, x);
2027 if((ctlr->did & 0xFF00) == 0x5900)
2028 ctlr->busmaster = 0;
2031 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
2032 x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
2033 outs(port+MediaStatus, x);
2036 * Start the DC-DC converter.
2037 * Wait > 800 microseconds.
2039 COMMAND(port, EnableDcConverter, 0);
2045 * Wop is the normal operating register set.
2046 * The 3C59[0257] adapters allow access to more than one register window
2047 * at a time, but there are situations where switching still needs to be
2048 * done, so just do it.
2049 * Clear out any lingering Tx status.
2051 COMMAND(port, SelectRegisterWindow, Wop);
2052 if(ctlr->busmaster == 2)
2053 x = port+TxStatus905;
2061 * adapter statistics, clear the statistics logged into ctlr
2062 * and enable statistics collection.
2064 ilock(&ctlr->wlock);
2066 memset(ctlr->stats, 0, sizeof(ctlr->stats));
2068 COMMAND(port, StatisticsEnable, 0);
2071 * Allocate any receive buffers.
2073 switch(ctlr->busmaster){
2075 ctlr->dnenabled = 1;
2079 * Disabling is too severe, can use receive busmastering at
2080 * 100Mbps OK, but how to tell which rate is actually being used -
2081 * the 3c905 always seems to have dataRate100 set?
2082 * Believe the bug doesn't apply if upRxEarlyEnable is set
2083 * and the threshold is set such that uploads won't start
2084 * until the whole packet has been received.
2086 ctlr->upenabled = 1;
2087 x = eepromdata(ctlr, 0x0F);
2089 outl(port+PktStatus, upRxEarlyEnable);
2091 if(ctlr->upenabled || ctlr->dnenabled){
2097 ctlr->rbp = rbpalloc(iallocb);
2098 if(ctlr->rbp == nil)
2099 panic("etherlnk3: iallocb: out of memory");
2101 outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
2104 ctlr->rbp = rbpalloc(iallocb);
2105 if(ctlr->rbp == nil)
2106 panic("etherlnk3: iallocb: out of memory");
2111 * Set a base TxStartThresh which will be incremented
2112 * if any txUnderrun errors occur and ensure no RxEarly
2113 * interrupts happen.
2115 ctlr->txthreshold = ETHERMAXTU/2;
2116 COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
2117 COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
2119 iunlock(&ctlr->wlock);
2122 * Linkage to the generic ethernet driver.
2124 ether->attach = attach;
2125 ether->transmit = transmit;
2126 ether->ifstat = ifstat;
2128 ether->promiscuous = promiscuous;
2129 ether->multicast = multicast;
2130 ether->shutdown = shutdown;
2133 intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
2139 etherelnk3link(void)
2141 addethercard("elnk3", etherelnk3reset);
2142 addethercard("3C509", etherelnk3reset);
2143 addethercard("3C575", etherelnk3reset);