1 /*
2 * Etherlink III and Fast EtherLink adapters.
3 * To do:
4 * autoSelect;
5 * busmaster channel;
6 * PCMCIA;
7 * PCI latency timer and master enable;
8 * errata list.
9 *
10 * Product ID:
11 * 9150 ISA 3C509[B]
12 * 9050 ISA 3C509[B]-TP
13 * 9450 ISA 3C509[B]-COMBO
14 * 9550 ISA 3C509[B]-TPO
15 *
16 * 9350 EISA 3C579
17 * 9250 EISA 3C579-TP
18 *
19 * 5920 EISA 3C592-[TP|COMBO|TPO]
20 * 5970 EISA 3C597-TX Fast Etherlink 10BASE-T/100BASE-TX
21 * 5971 EISA 3C597-T4 Fast Etherlink 10BASE-T/100BASE-T4
22 * 5972 EISA 3C597-MII Fast Etherlink 10BASE-T/MII
23 *
24 * 5900 PCI 3C590-[TP|COMBO|TPO]
25 * 5950 PCI 3C595-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
26 * 5951 PCI 3C595-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4
27 * 5952 PCI 3C595-MII Fast Etherlink 10BASE-T/MII
28 *
29 * 9058 PCMCIA 3C589[B]-[TP|COMBO]
30 *
31 * 627C MCA 3C529
32 * 627D MCA 3C529-TP
33 */
34 #include "u.h"
35 #include "lib.h"
36 #include "mem.h"
37 #include "dat.h"
38 #include "fns.h"
39 #include "io.h"
40
41 #include "etherif.h"
42
43 enum {
44 IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
45 };
46
47 enum { /* all windows */
48 Command = 0x000E,
49 IntStatus = 0x000E,
50 };
51
52 enum { /* Commands */
53 GlobalReset = 0x0000,
54 SelectRegisterWindow = 0x0001,
55 EnableDcConverter = 0x0002,
56 RxDisable = 0x0003,
57 RxEnable = 0x0004,
58 RxReset = 0x0005,
59 TxDone = 0x0007,
60 RxDiscard = 0x0008,
61 TxEnable = 0x0009,
62 TxDisable = 0x000A,
63 TxReset = 0x000B,
64 RequestInterrupt = 0x000C,
65 AcknowledgeInterrupt = 0x000D,
66 SetInterruptEnable = 0x000E,
67 SetIndicationEnable = 0x000F, /* SetReadZeroMask */
68 SetRxFilter = 0x0010,
69 SetRxEarlyThresh = 0x0011,
70 SetTxAvailableThresh = 0x0012,
71 SetTxStartThresh = 0x0013,
72 StartDma = 0x0014, /* initiate busmaster operation */
73 StatisticsEnable = 0x0015,
74 StatisticsDisable = 0x0016,
75 DisableDcConverter = 0x0017,
76 SetTxReclaimThresh = 0x0018, /* PIO-only adapters */
77 PowerUp = 0x001B, /* not all adapters */
78 PowerDownFull = 0x001C, /* not all adapters */
79 PowerAuto = 0x001D, /* not all adapters */
80 };
81
82 enum { /* (Global|Rx|Tx)Reset command bits */
83 tpAuiReset = 0x0001, /* 10BaseT and AUI transceivers */
84 endecReset = 0x0002, /* internal Ethernet encoder/decoder */
85 networkReset = 0x0004, /* network interface logic */
86 fifoReset = 0x0008, /* FIFO control logic */
87 aismReset = 0x0010, /* autoinitialise state-machine logic */
88 hostReset = 0x0020, /* bus interface logic */
89 dmaReset = 0x0040, /* bus master logic */
90 vcoReset = 0x0080, /* on-board 10Mbps VCO */
91
92 resetMask = 0x00FF,
93 };
94
95 enum { /* SetRxFilter command bits */
96 receiveIndividual = 0x0001, /* match station address */
97 receiveMulticast = 0x0002,
98 receiveBroadcast = 0x0004,
99 receiveAllFrames = 0x0008, /* promiscuous */
100 };
101
102 enum { /* StartDma command bits */
103 Upload = 0x0000, /* transfer data from adapter to memory */
104 Download = 0x0001, /* transfer data from memory to adapter */
105 };
106
107 enum { /* IntStatus bits */
108 interruptLatch = 0x0001,
109 hostError = 0x0002, /* Adapter Failure */
110 txComplete = 0x0004,
111 txAvailable = 0x0008,
112 rxComplete = 0x0010,
113 rxEarly = 0x0020,
114 intRequested = 0x0040,
115 updateStats = 0x0080,
116 transferInt = 0x0100, /* Bus Master Transfer Complete */
117 busMasterInProgress = 0x0800,
118 commandInProgress = 0x1000,
119
120 interruptMask = 0x01FE,
121 };
122
123 #define COMMAND(port, cmd, a) outs((port)+Command, ((cmd)<<11)|(a))
124 #define STATUS(port) ins((port)+IntStatus)
125
126 enum { /* Window 0 - setup */
127 Wsetup = 0x0000,
128 /* registers */
129 ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
130 ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
131 ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
132 AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
133 ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
134 EepromCommand = 0x000A,
135 EepromData = 0x000C,
136 /* AddressConfig Bits */
137 autoSelect9 = 0x0080,
138 xcvrMask9 = 0xC000,
139 /* ConfigControl bits */
140 Ena = 0x0001,
141 /* EepromCommand bits */
142 EepromReadRegister = 0x0080,
143 EepromBusy = 0x8000,
144 };
145
146 #define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
147 #define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
148 #define EEPROMDATA(port) ins((port)+EepromData)
149
150 enum { /* Window 1 - operating set */
151 Wop = 0x0001,
152 /* registers */
153 Fifo = 0x0000,
154 RxError = 0x0004, /* 3C59[0257] only */
155 RxStatus = 0x0008,
156 Timer = 0x000A,
157 TxStatus = 0x000B,
158 TxFree = 0x000C,
159 /* RxError bits */
160 rxOverrun = 0x0001,
161 runtFrame = 0x0002,
162 alignmentError = 0x0004, /* Framing */
163 crcError = 0x0008,
164 oversizedFrame = 0x0010,
165 dribbleBits = 0x0080,
166 /* RxStatus bits */
167 rxBytes = 0x1FFF, /* 3C59[0257] mask */
168 rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
169 rxError9 = 0x3800, /* 3C5[078]9 error mask */
170 rxOverrun9 = 0x0000,
171 oversizedFrame9 = 0x0800,
172 dribbleBits9 = 0x1000,
173 runtFrame9 = 0x1800,
174 alignmentError9 = 0x2000, /* Framing */
175 crcError9 = 0x2800,
176 rxError = 0x4000,
177 rxIncomplete = 0x8000,
178 /* TxStatus Bits */
179 txStatusOverflow = 0x0004,
180 maxCollisions = 0x0008,
181 txUnderrun = 0x0010,
182 txJabber = 0x0020,
183 interruptRequested = 0x0040,
184 txStatusComplete = 0x0080,
185 };
186
187 enum { /* Window 2 - station address */
188 Wstation = 0x0002,
189 };
190
191 enum { /* Window 3 - FIFO management */
192 Wfifo = 0x0003,
193 /* registers */
194 InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
195 OtherInt = 0x0004, /* 3C59[0257] */
196 RomControl = 0x0006, /* 3C509B, 3C59[27] */
197 MacControl = 0x0006, /* 3C59[0257] */
198 ResetOptions = 0x0008, /* 3C59[0257] */
199 RxFree = 0x000A,
200 /* InternalConfig bits */
201 disableBadSsdDetect = 0x00000100,
202 ramLocation = 0x00000200, /* 0 external, 1 internal */
203 ramPartition5to3 = 0x00000000,
204 ramPartition3to1 = 0x00010000,
205 ramPartition1to1 = 0x00020000,
206 ramPartition3to5 = 0x00030000,
207 ramPartitionMask = 0x00030000,
208 xcvr10BaseT = 0x00000000,
209 xcvrAui = 0x00100000, /* 10BASE5 */
210 xcvr10Base2 = 0x00300000,
211 xcvr100BaseTX = 0x00400000,
212 xcvr100BaseFX = 0x00500000,
213 xcvrMii = 0x00600000,
214 xcvrMask = 0x00700000,
215 autoSelect = 0x01000000,
216 /* MacControl bits */
217 deferExtendEnable = 0x0001,
218 deferTimerSelect = 0x001E, /* mask */
219 fullDuplexEnable = 0x0020,
220 allowLargePackets = 0x0040,
221 /* ResetOptions bits */
222 baseT4Available = 0x0001,
223 baseTXAvailable = 0x0002,
224 baseFXAvailable = 0x0004,
225 base10TAvailable = 0x0008,
226 coaxAvailable = 0x0010,
227 auiAvailable = 0x0020,
228 miiConnector = 0x0040,
229 };
230
231 enum { /* Window 4 - diagnostic */
232 Wdiagnostic = 0x0004,
233 /* registers */
234 VcoDiagnostic = 0x0002,
235 FifoDiagnostic = 0x0004,
236 NetworkDiagnostic = 0x0006,
237 PhysicalMgmt = 0x0008,
238 MediaStatus = 0x000A,
239 BadSSD = 0x000C,
240 /* FifoDiagnostic bits */
241 txOverrun = 0x0400,
242 rxUnderrun = 0x2000,
243 receiving = 0x8000,
244 /* MediaStatus bits */
245 dataRate100 = 0x0002,
246 crcStripDisable = 0x0004,
247 enableSqeStats = 0x0008,
248 collisionDetect = 0x0010,
249 carrierSense = 0x0020,
250 jabberGuardEnable = 0x0040,
251 linkBeatEnable = 0x0080,
252 jabberDetect = 0x0200,
253 polarityReversed = 0x0400,
254 linkBeatDetect = 0x0800,
255 txInProg = 0x1000,
256 dcConverterEnabled = 0x4000,
257 auiDisable = 0x8000,
258 };
259
260 enum { /* Window 5 - internal state */
261 Wstate = 0x0005,
262 /* registers */
263 TxStartThresh = 0x0000,
264 TxAvalableThresh = 0x0002,
265 RxEarlyThresh = 0x0006,
266 RxFilter = 0x0008,
267 InterruptEnable = 0x000A,
268 IndicationEnable = 0x000C,
269 };
270
271 enum { /* Window 6 - statistics */
272 Wstatistics = 0x0006,
273 /* registers */
274 CarrierLost = 0x0000,
275 SqeErrors = 0x0001,
276 MultipleColls = 0x0002,
277 SingleCollFrames = 0x0003,
278 LateCollisions = 0x0004,
279 RxOverruns = 0x0005,
280 FramesXmittedOk = 0x0006,
281 FramesRcvdOk = 0x0007,
282 FramesDeferred = 0x0008,
283 UpperFramesOk = 0x0009,
284 BytesRcvdOk = 0x000A,
285 BytesXmittedOk = 0x000C,
286 };
287
288 enum { /* Window 7 - bus master operations */
289 Wmaster = 0x0007,
290 /* registers */
291 MasterAddress = 0x0000,
292 MasterLen = 0x0006,
293 MasterStatus = 0x000C,
294 /* MasterStatus bits */
295 masterAbort = 0x0001,
296 targetAbort = 0x0002,
297 targetRetry = 0x0004,
298 targetDisc = 0x0008,
299 masterDownload = 0x1000,
300 masterUpload = 0x4000,
301 masterInProgress = 0x8000,
302
303 masterMask = 0xD00F,
304 };
305
306 typedef struct {
307 int txthreshold;
308 } Ctlr;
309
310 static void
attach(Ether * ether)311 attach(Ether* ether)
312 {
313 int port, x;
314
315 port = ether->port;
316
317 /*
318 * Set the receiver packet filter for this and broadcast addresses,
319 * set the interrupt masks for all interrupts, enable the receiver
320 * and transmitter.
321 */
322 x = receiveBroadcast|receiveIndividual;
323 COMMAND(port, SetRxFilter, x);
324
325 x = interruptMask|interruptLatch;
326 COMMAND(port, SetIndicationEnable, x);
327 COMMAND(port, SetInterruptEnable, x);
328
329 COMMAND(port, RxEnable, 0);
330 COMMAND(port, TxEnable, 0);
331 }
332
333 static void
transmit(Ether * ether)334 transmit(Ether* ether)
335 {
336 int port, len;
337 RingBuf *tb;
338
339 /*
340 * Attempt to top-up the transmit FIFO. If there's room simply
341 * stuff in the packet length (unpadded to a dword boundary), the
342 * packet data (padded) and remove the packet from the queue.
343 * If there's no room post an interrupt for when there is.
344 * This routine is called both from the top level and from interrupt
345 * level.
346 */
347 port = ether->port;
348 for(tb = ðer->tb[ether->ti]; tb->owner == Interface; tb = ðer->tb[ether->ti]){
349 len = ROUNDUP(tb->len, 4);
350 if(len+4 <= ins(port+TxFree)){
351 outl(port+Fifo, tb->len);
352 outsl(port+Fifo, tb->pkt, len/4);
353 tb->owner = Host;
354 ether->ti = NEXT(ether->ti, ether->ntb);
355 }
356 else{
357 COMMAND(port, SetTxAvailableThresh, len);
358 break;
359 }
360 }
361 }
362
363 static void
receive(Ether * ether)364 receive(Ether* ether)
365 {
366 int len, port, rxstatus;
367 RingBuf *rb;
368
369 port = ether->port;
370
371 while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
372 /*
373 * If there was an error, throw it away and continue.
374 * The 3C5[078]9 has the error info in the status register
375 * and the 3C59[0257] implement a separate RxError register.
376 */
377 if((rxstatus & rxError) == 0){
378 /*
379 * Packet received. Read it into the next free
380 * ring buffer, if any. Must read len bytes padded
381 * to a doubleword, can be picked out 32-bits at
382 * a time. The CRC is already stripped off.
383 */
384 rb = ðer->rb[ether->ri];
385 if(rb->owner == Interface){
386 len = (rxstatus & rxBytes9);
387 rb->len = len;
388 insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
389
390 rb->owner = Host;
391 ether->ri = NEXT(ether->ri, ether->nrb);
392 }
393 }
394
395 /*
396 * All done, discard the packet.
397 */
398 COMMAND(port, RxDiscard, 0);
399 while(STATUS(port) & commandInProgress)
400 ;
401 }
402 }
403
404 static void
statistics(Ether * ether)405 statistics(Ether* ether)
406 {
407 int i, port, w;
408
409 port = ether->port;
410 w = (STATUS(port)>>13) & 0x07;
411 COMMAND(port, SelectRegisterWindow, Wop);
412 COMMAND(port, SelectRegisterWindow, Wstatistics);
413
414 for(i = 0; i < 0x0A; i++)
415 inb(port+i);
416 ins(port+BytesRcvdOk);
417 ins(port+BytesXmittedOk);
418
419 COMMAND(port, SelectRegisterWindow, w);
420 }
421
422 static void
interrupt(Ureg *,void * arg)423 interrupt(Ureg*, void* arg)
424 {
425 Ether *ether;
426 int port, status, txstatus, w, x;
427 Ctlr *ctlr;
428
429 ether = arg;
430 port = ether->port;
431 ctlr = ether->ctlr;
432
433 w = (STATUS(port)>>13) & 0x07;
434 COMMAND(port, SelectRegisterWindow, Wop);
435
436 for(;;){
437 /*
438 * Clear the interrupt latch.
439 * It's possible to receive a packet and for another
440 * to become complete before exiting the interrupt
441 * handler so this must be done first to ensure another
442 * interrupt will occur.
443 */
444 COMMAND(port, AcknowledgeInterrupt, interruptLatch);
445 status = STATUS(port);
446 if((status & interruptMask) == 0)
447 break;
448
449 if(status & hostError){
450 /*
451 * Adapter failure, try to find out why, reset if
452 * necessary. What happens if Tx is active and a reset
453 * occurs, need to retransmit? This probably isn't right.
454 */
455 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
456 x = ins(port+FifoDiagnostic);
457 COMMAND(port, SelectRegisterWindow, Wop);
458 print("elnk3#%d: status 0x%uX, diag 0x%uX\n",
459 ether->ctlrno, status, x);
460
461 if(x & txOverrun){
462 COMMAND(port, TxReset, 0);
463 COMMAND(port, TxEnable, 0);
464 }
465
466 if(x & rxUnderrun){
467 /*
468 * This shouldn't happen...
469 * Need to restart any busmastering?
470 */
471 COMMAND(port, RxReset, 0);
472 while(STATUS(port) & commandInProgress)
473 ;
474 COMMAND(port, RxEnable, 0);
475 }
476
477 status &= ~hostError;
478 }
479
480 if(status & (transferInt|rxComplete)){
481 receive(ether);
482 status &= ~(transferInt|rxComplete);
483 }
484
485 if(status & txComplete){
486 /*
487 * Pop the TxStatus stack, accumulating errors.
488 * Adjust the TX start threshold if there was an underrun.
489 * If there was a Jabber or Underrun error, reset
490 * the transmitter.
491 * For all conditions enable the transmitter.
492 */
493 txstatus = 0;
494 do{
495 if(x = inb(port+TxStatus))
496 outb(port+TxStatus, 0);
497 txstatus |= x;
498 }while(STATUS(port) & txComplete);
499
500 if(txstatus & txUnderrun){
501 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
502 while(ins(port+MediaStatus) & txInProg)
503 ;
504 COMMAND(port, SelectRegisterWindow, Wop);
505 if(ctlr->txthreshold < ETHERMAXTU)
506 ctlr->txthreshold += ETHERMINTU;
507 }
508
509 if(txstatus & (txJabber|txUnderrun)){
510 COMMAND(port, TxReset, 0);
511 while(STATUS(port) & commandInProgress)
512 ;
513 COMMAND(port, SetTxStartThresh, ctlr->txthreshold);
514 }
515 COMMAND(port, TxEnable, 0);
516 status &= ~txComplete;
517 status |= txAvailable;
518 }
519
520 if(status & txAvailable){
521 COMMAND(port, AcknowledgeInterrupt, txAvailable);
522 transmit(ether);
523 status &= ~txAvailable;
524 }
525
526 if(status & updateStats){
527 statistics(ether);
528 status &= ~updateStats;
529 }
530
531 /*
532 * Panic if there are any interrupts not dealt with.
533 */
534 if(status & interruptMask)
535 panic("elnk3#%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
536 }
537
538 COMMAND(port, SelectRegisterWindow, w);
539 }
540
541 typedef struct Adapter {
542 int port;
543 int irq;
544 int tbdf;
545 } Adapter;
546 static Block* adapter;
547
548 static void
tcmadapter(int port,int irq,int tbdf)549 tcmadapter(int port, int irq, int tbdf)
550 {
551 Block *bp;
552 Adapter *ap;
553
554 bp = allocb(sizeof(Adapter));
555 ap = (Adapter*)bp->rp;
556 ap->port = port;
557 ap->irq = irq;
558 ap->tbdf = tbdf;
559
560 bp->next = adapter;
561 adapter = bp;
562 }
563
564 /*
565 * Write two 0 bytes to identify the IDport and then reset the
566 * ID sequence. Then send the ID sequence to the card to get
567 * the card into command state.
568 */
569 static void
idseq(void)570 idseq(void)
571 {
572 int i;
573 uchar al;
574 static int reset, untag;
575
576 /*
577 * One time only:
578 * reset any adapters listening
579 */
580 if(reset == 0){
581 outb(IDport, 0);
582 outb(IDport, 0);
583 outb(IDport, 0xC0);
584 delay(20);
585 reset = 1;
586 }
587
588 outb(IDport, 0);
589 outb(IDport, 0);
590 for(al = 0xFF, i = 0; i < 255; i++){
591 outb(IDport, al);
592 if(al & 0x80){
593 al <<= 1;
594 al ^= 0xCF;
595 }
596 else
597 al <<= 1;
598 }
599
600 /*
601 * One time only:
602 * write ID sequence to get the attention of all adapters;
603 * untag all adapters.
604 * If we do a global reset here on all adapters we'll confuse any
605 * ISA cards configured for EISA mode.
606 */
607 if(untag == 0){
608 outb(IDport, 0xD0);
609 untag = 1;
610 }
611 }
612
613 static ulong
activate(void)614 activate(void)
615 {
616 int i;
617 ushort x, acr;
618
619 /*
620 * Do the little configuration dance:
621 *
622 * 2. write the ID sequence to get to command state.
623 */
624 idseq();
625
626 /*
627 * 3. Read the Manufacturer ID from the EEPROM.
628 * This is done by writing the IDPort with 0x87 (0x80
629 * is the 'read EEPROM' command, 0x07 is the offset of
630 * the Manufacturer ID field in the EEPROM).
631 * The data comes back 1 bit at a time.
632 * We seem to need a delay here between reading the bits.
633 *
634 * If the ID doesn't match, there are no more adapters.
635 */
636 outb(IDport, 0x87);
637 delay(20);
638 for(x = 0, i = 0; i < 16; i++){
639 delay(20);
640 x <<= 1;
641 x |= inb(IDport) & 0x01;
642 }
643 if(x != 0x6D50)
644 return 0;
645
646 /*
647 * 3. Read the Address Configuration from the EEPROM.
648 * The Address Configuration field is at offset 0x08 in the EEPROM).
649 */
650 outb(IDport, 0x88);
651 for(acr = 0, i = 0; i < 16; i++){
652 delay(20);
653 acr <<= 1;
654 acr |= inb(IDport) & 0x01;
655 }
656
657 return (acr & 0x1F)*0x10 + 0x200;
658 }
659
660 #ifdef notjustpcmcia
661 static void
tcm509isa(void)662 tcm509isa(void)
663 {
664 int irq, port;
665
666 /*
667 * Attempt to activate all adapters. If adapter is set for
668 * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
669 * it fully.
670 */
671 while(port = activate()){
672 /*
673 * 6. Tag the adapter so it won't respond in future.
674 */
675 outb(IDport, 0xD1);
676 if(port == 0x3F0)
677 continue;
678
679 /*
680 * 6. Activate the adapter by writing the Activate command
681 * (0xFF).
682 */
683 outb(IDport, 0xFF);
684 delay(20);
685
686 /*
687 * 8. Can now talk to the adapter's I/O base addresses.
688 * Use the I/O base address from the acr just read.
689 *
690 * Enable the adapter and clear out any lingering status
691 * and interrupts.
692 */
693 while(STATUS(port) & commandInProgress)
694 ;
695 COMMAND(port, SelectRegisterWindow, Wsetup);
696 outs(port+ConfigControl, Ena);
697
698 COMMAND(port, TxReset, 0);
699 COMMAND(port, RxReset, 0);
700 COMMAND(port, AcknowledgeInterrupt, 0xFF);
701
702 irq = (ins(port+ResourceConfig)>>12) & 0x0F;
703 tcmadapter(port, irq, BUSUNKNOWN);
704 }
705 }
706
707 static void
tcm5XXeisa(void)708 tcm5XXeisa(void)
709 {
710 ushort x;
711 int irq, port, slot;
712
713 /*
714 * Check if this is an EISA machine.
715 * If not, nothing to do.
716 */
717 if(strncmp((char*)(KZERO|0xFFFD9), "EISA", 4))
718 return;
719
720 /*
721 * Continue through the EISA slots looking for a match on both
722 * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
723 * If an adapter is found, select window 0, enable it and clear
724 * out any lingering status and interrupts.
725 */
726 for(slot = 1; slot < MaxEISA; slot++){
727 port = slot*0x1000;
728 if(ins(port+0xC80+ManufacturerID) != 0x6D50)
729 continue;
730 x = ins(port+0xC80+ProductID);
731 if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
732 continue;
733
734 COMMAND(port, SelectRegisterWindow, Wsetup);
735 outs(port+ConfigControl, Ena);
736
737 COMMAND(port, TxReset, 0);
738 COMMAND(port, RxReset, 0);
739 COMMAND(port, AcknowledgeInterrupt, 0xFF);
740
741 irq = (ins(port+ResourceConfig)>>12) & 0x0F;
742 tcmadapter(port, irq, BUSUNKNOWN);
743 }
744 }
745
746 static void
tcm59Xpci(void)747 tcm59Xpci(void)
748 {
749 Pcidev *p;
750 int irq, port;
751
752 p = nil;
753 while(p = pcimatch(p, 0x10B7, 0)){
754 port = p->mem[0].bar & ~0x01;
755 irq = p->intl;
756 COMMAND(port, GlobalReset, 0);
757 while(STATUS(port) & commandInProgress)
758 ;
759
760 tcmadapter(port, irq, p->tbdf);
761 }
762 }
763 #endif /* notjustpcmcia */
764
765 static char* tcmpcmcia[] = {
766 "3C589", /* 3COM 589[ABCD] */
767 "3C562", /* 3COM 562 */
768 "589E", /* 3COM Megahertz 589E */
769 nil,
770 };
771
772 static int
tcm5XXpcmcia(Ether * ether)773 tcm5XXpcmcia(Ether* ether)
774 {
775 int i;
776
777 for(i = 0; tcmpcmcia[i] != nil; i++){
778 if(!cistrcmp(ether->type, tcmpcmcia[i]))
779 return ether->port;
780 }
781
782 return 0;
783 }
784
785 static int
autoselect(int port,int rxstatus9)786 autoselect(int port, int rxstatus9)
787 {
788 int media, x;
789
790 /*
791 * Pathetic attempt at automatic media selection.
792 * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
793 * cards operational.
794 */
795 media = auiAvailable|coaxAvailable|base10TAvailable;
796 if(rxstatus9 == 0){
797 COMMAND(port, SelectRegisterWindow, Wfifo);
798 media = ins(port+ResetOptions);
799 }
800
801 if(media & miiConnector)
802 return xcvrMii;
803
804 if(media & baseTXAvailable){
805 /*
806 * Must have InternalConfig register.
807 */
808 COMMAND(port, SelectRegisterWindow, Wfifo);
809 x = inl(port+InternalConfig) & ~xcvrMask;
810 x |= xcvr100BaseTX;
811 outl(port+InternalConfig, x);
812 COMMAND(port, TxReset, 0);
813 while(STATUS(port) & commandInProgress)
814 ;
815 COMMAND(port, RxReset, 0);
816 while(STATUS(port) & commandInProgress)
817 ;
818
819 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
820 x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
821 outs(port+MediaStatus, linkBeatEnable|x);
822 delay(10);
823
824 { int i, v;
825 for(i = 0; i < 10000; i++){
826 v = ins(port+MediaStatus);
827 if(v & linkBeatDetect){
828 print("count %d v %uX\n", i, v);
829 return xcvr100BaseTX;
830 }
831 delay(1);
832 }
833 print("count %d v %uX\n", i, ins(port+MediaStatus));
834 }
835 if(ins(port+MediaStatus) & linkBeatDetect)
836 return xcvr100BaseTX;
837 outs(port+MediaStatus, x);
838 }
839
840 if(media & base10TAvailable){
841 if(rxstatus9 == 0){
842 COMMAND(port, SelectRegisterWindow, Wfifo);
843 x = inl(port+InternalConfig) & ~xcvrMask;
844 x |= xcvr10BaseT;
845 outl(port+InternalConfig, x);
846 }
847 else{
848 COMMAND(port, SelectRegisterWindow, Wsetup);
849 x = ins(port+AddressConfig) & ~xcvrMask9;
850 x |= (xcvr10BaseT>>20)<<14;
851 outs(port+AddressConfig, x);
852 }
853 COMMAND(port, TxReset, 0);
854 while(STATUS(port) & commandInProgress)
855 ;
856 COMMAND(port, RxReset, 0);
857 while(STATUS(port) & commandInProgress)
858 ;
859
860 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
861 x = ins(port+MediaStatus) & ~dcConverterEnabled;
862 outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
863 delay(10);
864
865 if(ins(port+MediaStatus) & linkBeatDetect)
866 return xcvr10BaseT;
867 outs(port+MediaStatus, x);
868 }
869
870 /*
871 * Botch.
872 */
873 return autoSelect;
874 }
875
876 static int
eepromdata(int port,int offset)877 eepromdata(int port, int offset)
878 {
879 COMMAND(port, SelectRegisterWindow, Wsetup);
880 while(EEPROMBUSY(port))
881 ;
882 EEPROMCMD(port, EepromReadRegister, offset);
883 while(EEPROMBUSY(port))
884 ;
885 return EEPROMDATA(port);
886 }
887
888 int
elnk3reset(Ether * ether)889 elnk3reset(Ether* ether)
890 {
891 int did, i, port, rxstatus9, x, xcvr;
892 Block *bp, **bpp;
893 Adapter *ap;
894 uchar ea[Eaddrlen];
895 Ctlr *ctlr;
896 #ifdef notjustpcmcia
897 static int scandone;
898
899 /*
900 * Scan for adapter on PCI, EISA and finally
901 * using the little ISA configuration dance.
902 */
903 if(scandone == 0){
904 tcm59Xpci();
905 tcm5XXeisa();
906 tcm509isa();
907 scandone = 1;
908 }
909 #endif /* notjustpcmcia */
910
911 /*
912 * Any adapter matches if no ether->port is supplied,
913 * otherwise the ports must match.
914 */
915 port = 0;
916 bpp = &adapter;
917 for(bp = *bpp; bp; bp = bp->next){
918 ap = (Adapter*)bp->rp;
919 if(ether->port == 0 || ether->port == ap->port){
920 port = ap->port;
921 ether->irq = ap->irq;
922 ether->tbdf = ap->tbdf;
923 *bpp = bp->next;
924 freeb(bp);
925 break;
926 }
927 bpp = &bp->next;
928 }
929 if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
930 return -1;
931
932 /*
933 * Read the DeviceID from the EEPROM, it's at offset 0x03,
934 * and do something depending on capabilities.
935 */
936 switch(did = eepromdata(port, 0x03)){
937
938 case 0x9000:
939 case 0x9001:
940 case 0x9050:
941 case 0x9051:
942 if(BUSTYPE(ether->tbdf) != BusPCI)
943 goto buggery;
944 goto vortex;
945
946 case 0x5900:
947 case 0x5920:
948 case 0x5950:
949 case 0x5951:
950 case 0x5952:
951 case 0x5970:
952 case 0x5971:
953 case 0x5972:
954 vortex:
955 COMMAND(port, SelectRegisterWindow, Wfifo);
956 xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
957 rxstatus9 = 0;
958 break;
959
960 buggery:
961 default:
962 COMMAND(port, SelectRegisterWindow, Wsetup);
963 x = ins(port+AddressConfig);
964 xcvr = ((x & xcvrMask9)>>14)<<20;
965 if(x & autoSelect9)
966 xcvr |= autoSelect;
967 rxstatus9 = 1;
968 break;
969 }
970 USED(did);
971
972 /*
973 * Check if the adapter's station address is to be overridden.
974 * If not, read it from the EEPROM and set in ether->ea prior to loading the
975 * station address in Wstation. The EEPROM returns 16-bits at a time.
976 */
977 memset(ea, 0, Eaddrlen);
978 if(memcmp(ea, ether->ea, Eaddrlen) == 0){
979 for(i = 0; i < Eaddrlen/2; i++){
980 x = eepromdata(port, i);
981 ether->ea[2*i] = x>>8;
982 ether->ea[2*i+1] = x;
983 }
984 }
985
986 COMMAND(port, SelectRegisterWindow, Wstation);
987 for(i = 0; i < Eaddrlen; i++)
988 outb(port+i, ether->ea[i]);
989
990 /*
991 * Enable the transceiver if necessary.
992 */
993 if(xcvr & autoSelect)
994 xcvr = autoselect(port, rxstatus9);
995 switch(xcvr){
996
997 case xcvrMii:
998 break;
999
1000 case xcvr100BaseTX:
1001 case xcvr100BaseFX:
1002 COMMAND(port, SelectRegisterWindow, Wfifo);
1003 x = inl(port+InternalConfig) & ~ramPartitionMask;
1004 outl(port+InternalConfig, x|ramPartition1to1);
1005
1006 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1007 x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
1008 x |= linkBeatEnable;
1009 outs(port+MediaStatus, x);
1010 break;
1011
1012 case xcvr10BaseT:
1013 /*
1014 * Enable Link Beat and Jabber to start the
1015 * transceiver.
1016 */
1017 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1018 x = ins(port+MediaStatus) & ~dcConverterEnabled;
1019 x |= linkBeatEnable|jabberGuardEnable;
1020 outs(port+MediaStatus, x);
1021 break;
1022
1023 case xcvr10Base2:
1024 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
1025 x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
1026 outs(port+MediaStatus, x);
1027
1028 /*
1029 * Start the DC-DC converter.
1030 * Wait > 800 microseconds.
1031 */
1032 COMMAND(port, EnableDcConverter, 0);
1033 delay(1);
1034 break;
1035 }
1036
1037 /*
1038 * Wop is the normal operating register set.
1039 * The 3C59[0257] adapters allow access to more than one register window
1040 * at a time, but there are situations where switching still needs to be
1041 * done, so just do it.
1042 * Clear out any lingering Tx status.
1043 */
1044 COMMAND(port, SelectRegisterWindow, Wop);
1045 while(inb(port+TxStatus))
1046 outb(port+TxStatus, 0);
1047
1048 /*
1049 * Allocate a controller structure and start
1050 * to initialise it.
1051 */
1052 ether->ctlr = malloc(sizeof(Ctlr));
1053 ctlr = ether->ctlr;
1054 memset(ctlr, 0, sizeof(Ctlr));
1055
1056 /*
1057 * Set a base TxStartThresh which will be incremented
1058 * if any txUnderrun errors occur and ensure no RxEarly
1059 * interrupts happen.
1060 */
1061 ctlr->txthreshold = ETHERMINTU;
1062 COMMAND(port, SetTxStartThresh, ETHERMINTU);
1063 COMMAND(port, SetRxEarlyThresh, ETHERMAXTU);
1064
1065 /*
1066 * Set up the software configuration.
1067 */
1068 ether->port = port;
1069 ether->attach = attach;
1070 ether->transmit = transmit;
1071 ether->interrupt = interrupt;
1072
1073 return 0;
1074 }
1075