4 * check xcvr10Base2 still works (is GlobalReset necessary?).
7 #include "../port/lib.h"
12 #include "../port/error.h"
13 #include "../port/netif.h"
14 #include "../port/etherif.h"
16 enum { /* all windows */
23 SelectRegisterWindow = 0x0001,
26 AcknowledgeInterrupt = 0x000D,
29 enum { /* IntStatus bits */
30 commandInProgress = 0x1000,
33 #define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
34 #define STATUS(port) ins((port)+IntStatusR)
36 enum { /* Window 0 - setup */
39 ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
40 ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
41 ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
42 AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
43 ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
44 EepromCommand = 0x000A,
46 /* AddressConfig Bits */
49 /* ConfigControl bits */
51 base10TAvailable9 = 0x0200,
52 coaxAvailable9 = 0x1000,
53 auiAvailable9 = 0x2000,
54 /* EepromCommand bits */
55 EepromReadRegister = 0x0080,
59 enum { /* Window 1 - operating set */
63 enum { /* Window 3 - FIFO management */
66 InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
67 /* InternalConfig bits */
68 xcvr10BaseT = 0x00000000,
69 xcvr10Base2 = 0x00300000,
72 enum { /* Window 4 - diagnostic */
76 /* MediaStatus bits */
77 linkBeatDetect = 0x0800,
80 extern int etherelnk3reset(Ether*);
82 static char *tcmpcmcia[] = {
83 "3C589", /* 3COM 589[ABCD] */
84 "3C562", /* 3COM 562 */
85 "589E", /* 3COM Megahertz 589E */
90 configASIC(Ether* ether, int port, int xcvr)
94 /* set Window 0 configuration registers */
95 COMMAND(port, SelectRegisterWindow, Wsetup);
96 outs(port+ConfigControl, Ena);
98 /* IRQ must be 3 on 3C589/3C562 */
99 outs(port + ResourceConfig, 0x3F00);
101 x = ins(port+AddressConfig) & ~xcvrMask9;
103 outs(port+AddressConfig, x);
105 COMMAND(port, TxReset, 0);
106 while(STATUS(port) & commandInProgress)
108 COMMAND(port, RxReset, 0);
109 while(STATUS(port) & commandInProgress)
112 return etherelnk3reset(ether);
121 enum { WantAny, Want10BT, Want10B2 };
132 if(ioalloc(port, 0x10, 0, "3C589") < 0)
137 for(i = 0; tcmpcmcia[i] != nil; i++){
139 if((slot = pcmspecial(type, ether)) >= 0)
142 ether->type = type; /* must be set before calling configASIC */
149 * Read Ethernet address from card memory
150 * on 3C562, but only if the user has not
153 memset(ea, 0, sizeof ea);
154 if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) {
155 if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) {
156 for(i = 0; i < 6; i += 2){
161 memmove(ether->ea, ea, 6);
165 * Allow user to specify desired media in plan9.ini
168 for(i = 0; i < ether->nopt; i++){
169 if(cistrncmp(ether->opt[i], "media=", 6) != 0)
172 if(cistrcmp(p, "10base2") == 0)
174 else if(cistrcmp(p, "10baseT") == 0)
178 /* try configuring as a 10BaseT */
179 if(want==WantAny || want==Want10BT){
180 if(configASIC(ether, port, xcvr10BaseT) < 0){
181 pcmspecialclose(slot);
186 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
187 if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){
188 COMMAND(port, SelectRegisterWindow, Wop);
189 print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, type);
194 /* try configuring as a 10base2 */
195 if(want==WantAny || want==Want10B2){
196 COMMAND(port, GlobalReset, 0);
197 if(configASIC(ether, port, xcvr10Base2) < 0){
198 pcmspecialclose(slot);
202 print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, type);
205 return -1; /* not reached */
211 addethercard("3C589", reset);
212 addethercard("3C562", reset);
213 addethercard("589E", reset);