|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7: #include "io.h"
8: #include "devtab.h"
9:
10: #include "ether.h"
11:
12: /*
13: * 3Com 503 (EtherLink II).
14: * This driver doesn't work under load, the card gets blasted by
15: * overwrite-warning interrupts and eventually just hangs. Always clearing
16: * the Ovw bit in the DP8390 Isr along with the Rxe and Prx bits stops
17: * the overwrite-warning interrupts, but the card eventually hangs anyway.
18: * I really don't understand why this card doesn't work,
19: * there is plenty of evidence that other systems manage to use it.
20: * The only good thing about this driver is that both shared
21: * memory and polled I/O work (given the above restraints), although
22: * the polled I/O should be tuned.
23: */
24: enum { /* Gate Array Registers */
25: Pstr = 0x400, /* Page Start Register */
26: Pspr = 0x401, /* Page Stop Register */
27: Dqtr = 0x402, /* Drq Timer Register */
28: Bcfr = 0x403, /* Base Configuration Register */
29: Pcfr = 0x404, /* EPROM Configuration Register */
30: Gacfr = 0x405, /* GA Configuration Register */
31: Ctrl = 0x406, /* Control Register */
32: Streg = 0x407, /* Status Register */
33: Idcfr = 0x408, /* Interrupt/DMA Configuration Register */
34: Damsb = 0x409, /* DMA Address Register MSB */
35: Dalsb = 0x40A, /* DMA Address Register LSB */
36: Vptr2 = 0x40B, /* Vector Pointer Register 2 */
37: Vptr1 = 0x40C, /* Vector Pointer Register 1 */
38: Vptr0 = 0x40D, /* Vector Pointer Register 0 */
39: Rfmsb = 0x40E, /* Register File Access MSB */
40: Rflsb = 0x40F, /* Register File Access LSB */
41: };
42:
43: enum { /* Pcfr */
44: C8xxx = 0x10, /* memory address 0xC8000 */
45: CCxxx = 0x20, /* memory address 0xCC000 */
46: D8xxx = 0x40, /* memory address 0xD8000 */
47: DCxxx = 0x80, /* memory address 0xDC000 */
48: };
49:
50: enum { /* Gacfr */
51: Mbs0 = 0x01, /* memory bank select 0 */
52: Mbs1 = 0x02, /* memory bank select 1 */
53: Mbs2 = 0x04, /* memory bank select 2 */
54: Rsel = 0x08, /* RAM select */
55: Test = 0x10, /* test */
56: Ows = 0x20, /* 0 wait state */
57: Tcm = 0x40, /* terminal count mask */
58: Nim = 0x80, /* MIC interrupt mask */
59: };
60:
61: enum { /* Ctrl */
62: Rst = 0x01, /* software reset */
63: Xsel = 0x02, /* transceiver select (BNC = 1, AUI = 0) */
64: Ealo = 0x04, /* ethernet address low */
65: Eahi = 0x08, /* ethernet address high */
66: Share = 0x10, /* interrupt share */
67: Dbsel = 0x20, /* double buffer select */
68: Ddir = 0x40, /* DMA direction */
69: Start = 0x80, /* DMA start */
70: };
71:
72: enum { /* Streg */
73: Rev0 = 0x01, /* gate array revision bit 0 */
74: Rev1 = 0x02, /* gate array revision bit 1 */
75: Rev2 = 0x04, /* gate array revision bit 2 */
76: Dip = 0x08, /* DMA in progress */
77: Dtc = 0x10, /* DMA terminal count */
78: Oflw = 0x20, /* overflow */
79: Uflw = 0x40, /* underflow */
80: Dprdy = 0x80, /* data port ready */
81: };
82:
83: enum { /* Idcfr */
84: Drq1 = 0x01, /* DMA request 1 */
85: Drq2 = 0x02, /* DMA request 2 */
86: Drq3 = 0x04, /* DMA request 3 */
87: Irq2 = 0x10, /* interrupt request 2 */
88: Irq3 = 0x20, /* interrupt request 3 */
89: Irq4 = 0x40, /* interrupt request 4 */
90: Irq5 = 0x80, /* interrupt request 5 */
91: };
92:
93: enum {
94: RamOffset = 0x2000, /* where the card sees the shared memory */
95: };
96:
97: typedef struct {
98: ulong io; /* I/O base address */
99: uchar irq; /* interrupt level */
100: uchar bnc; /* use BNC connector */
101: } Table;
102:
103: /*
104: * The only configuration info we can get from the card is the
105: * I/O base address and the shared-memory address. So let's make
106: * a little hard-wired configuration table.
107: */
108: static Table table[] = {
109: { 0x300, Irq2, 0, }, /* external transceiver */
110: { 0x310, Irq3, 0, },
111: { 0x330, Irq4, 0, },
112: { 0x350, Irq5, 0, },
113:
114: { 0x250, Irq2, Xsel, }, /* BNC */
115: { 0x280, Irq3, Xsel, },
116: { 0x2A0, Irq4, Xsel, },
117: { 0x2E0, Irq5, Xsel, },
118:
119: { 0 },
120: };
121:
122:
123: static int
124: reset(Ctlr *ctlr)
125: {
126: Table *tp;
127: int i;
128: uchar cfr;
129:
130: /*
131: * The Gate Array Ctrl register bits <3,2> determine what is
132: * mapped at the I/O base address. The options are the DP8390,
133: * PROM bytes 0-15 or PROM bytes 16-31.
134: * At power-on, the I/O base address contains PROM bytes 16-31.
135: */
136: for(tp = table; ctlr->card.io = tp->io; tp++){
137: /*
138: * Toggle the software reset bit, this should initialise the
139: * Ctrl register to 0x0A (Eahi|Xsel).
140: * Hopefully there is no other card at the gate-array address.
141: */
142: outb(ctlr->card.io+Ctrl, Rst);
143: delay(1);
144: outb(ctlr->card.io+Ctrl, 0);
145: if(inb(ctlr->card.io+Ctrl) == (Eahi|Xsel))
146: break;
147: }
148: if(ctlr->card.io == 0)
149: return -1;
150:
151: /*
152: * Map PROM bytes 0-15 to the I/O base address
153: * and read the ethernet address.
154: * When done, map the DP8390 at the I/O base address
155: * and set the transceiver type and irq.
156: */
157: outb(ctlr->card.io+Ctrl, Ealo|Xsel);
158: for(i = 0; i < sizeof(ctlr->ea); i++)
159: ctlr->ea[i] = inb(ctlr->card.io+i);
160:
161: outb(ctlr->card.io+Gacfr, Nim|Tcm);
162:
163: outb(ctlr->card.io+Ctrl, 0|tp->bnc);
164: outb(ctlr->card.io+Idcfr, tp->irq);
165:
166: if(tp->irq == Irq2)
167: ctlr->card.irq = 2;
168: else if(tp->irq == Irq3)
169: ctlr->card.irq = 3;
170: else if(tp->irq == Irq4)
171: ctlr->card.irq = 4;
172: else if(tp->irq == Irq5)
173: ctlr->card.irq = 5;
174: else
175: return -1;
176:
177: /*
178: * Try to configure the shared memory.
179: * Assume this is an 8K card.
180: */
181: ctlr->card.ram = 1;
182: cfr = inb(ctlr->card.io+Pcfr);
183: if(cfr & C8xxx)
184: ctlr->card.ramstart = KZERO|0xC8000;
185: else if(cfr & CCxxx)
186: ctlr->card.ramstart = KZERO|0xCC000;
187: else if(cfr & D8xxx)
188: ctlr->card.ramstart = KZERO|0xD8000;
189: else if(cfr & DCxxx)
190: ctlr->card.ramstart = KZERO|0xDC000;
191: else
192: ctlr->card.ram = 0;
193:
194: ctlr->card.ramstop = ctlr->card.ramstart + 8*1024;
195:
196: /*
197: * Finish initialising the gate-array.
198: * The Pstr and Pspr registers must be the same as those
199: * given to the DP8390.
200: * Gacfr is set to enable shared memory and block DMA
201: * interrupts.
202: */
203: outb(ctlr->card.io+Pstr, ctlr->card.pstart);
204: outb(ctlr->card.io+Pspr, ctlr->card.pstop);
205:
206: outb(ctlr->card.io+Dqtr, 8);
207: outb(ctlr->card.io+Damsb, ctlr->card.tstart);
208: outb(ctlr->card.io+Dalsb, 0);
209:
210: outb(ctlr->card.io+Vptr2, 0xFF);
211: outb(ctlr->card.io+Vptr1, 0xFF);
212: outb(ctlr->card.io+Vptr0, 0x00);
213:
214: /*
215: * Finally, init the 8390, set the ethernet address
216: * and turn on the shared memory if any.
217: */
218: ctlr->card.dp8390 = ctlr->card.io;
219: dp8390reset(ctlr);
220: dp8390setea(ctlr);
221:
222: if(ctlr->card.ram)
223: outb(ctlr->card.io+Gacfr, Tcm|Rsel|Mbs0);
224: else
225: outb(ctlr->card.io+Gacfr, Tcm);
226:
227: return 0;
228: }
229:
230: static void*
231: read(Ctlr *ctlr, void *to, ulong from, ulong len)
232: {
233: uchar *addr, ctrl;
234:
235: /*
236: * If the interface has shared memory, just do a memmove.
237: * In this case, 'from' is an index into the shared memory.
238: * Due to 'hardware considerations', the memory is seen by
239: * the adapter at RamOffset, so we have to adjust.
240: */
241: if(ctlr->card.ram)
242: return memmove(to, (void*)(ctlr->card.ramstart+from-RamOffset), len);
243:
244: /*
245: * Polled I/O. This should be tuned.
246: * Set up the dma registers and pump the fifo.
247: */
248: outb(ctlr->card.io+Dalsb, from & 0xFF);
249: outb(ctlr->card.io+Damsb, (from>>8) & 0xFF);
250: ctrl = inb(ctlr->card.io+Ctrl);
251: outb(ctlr->card.io+Ctrl, Start|ctrl);
252: addr = to;
253: while(len){
254: /*
255: * The fifo is 8 bytes deep, we have to wait
256: * until it's ready before stuffing it.
257: * The fifo is in its default configuration,
258: * so we can do word accesses.
259: */
260: while((inb(ctlr->card.io+Streg) & Dprdy) == 0)
261: ;
262: if(len >= 8){
263: inss(ctlr->card.io+Rfmsb, addr, 4);
264: addr += 8;
265: len -= 8;
266: }
267: else{
268: insb(ctlr->card.io+Rfmsb, addr, len);
269: break;
270: }
271: }
272: outb(ctlr->card.io+Ctrl, ctrl);
273: return to;
274: }
275:
276: static void*
277: write(Ctlr *ctlr, ulong to, void *from, ulong len)
278: {
279: uchar *addr, ctrl;
280:
281: /*
282: * See the comments in 'read()' above.
283: */
284: if(ctlr->card.ram)
285: return memmove((void*)(ctlr->card.ramstart+to-RamOffset), from, len);
286:
287: outb(ctlr->card.io+Dalsb, to & 0xFF);
288: outb(ctlr->card.io+Damsb, (to>>8) & 0xFF);
289: ctrl = inb(ctlr->card.io+Ctrl);
290: outb(ctlr->card.io+Ctrl, Start|Ddir|ctrl);
291: addr = from;
292: while(len){
293: while((inb(ctlr->card.io+Streg) & Dprdy) == 0)
294: ;
295: if(len >= 8){
296: outss(ctlr->card.io+Rfmsb, addr, 4);
297: addr += 8;
298: len -= 8;
299: }
300: else{
301: outsb(ctlr->card.io+Rfmsb, addr, len);
302: break;
303: }
304: }
305: outb(ctlr->card.io+Ctrl, ctrl);
306: return (void*)to;
307: }
308:
309: Card ether503 = {
310: "3Com503", /* ident */
311:
312: reset, /* reset */
313: 0, /* init */
314: dp8390attach, /* attach */
315: dp8390mode, /* mode */
316:
317: read, /* read */
318: write, /* write */
319:
320: dp8390receive, /* receive */
321: dp8390transmit, /* transmit */
322: dp8390intr, /* interrupt */
323: dp8390watch, /* watch */
324: dp8390overflow, /* overflow */
325:
326: 0, /* io */
327: 0, /* irq */
328: 0, /* bit16 */
329:
330: 0, /* ram */
331: 0, /* ramstart */
332: 0, /* ramstop */
333:
334: 0, /* dp8390 */
335: 0, /* data */
336: 0, /* software bndry */
337: RamOffset/Dp8390BufSz, /* tstart */
338: (RamOffset+0x600)/Dp8390BufSz, /* pstart */
339: (RamOffset+8*1024)/Dp8390BufSz, /* pstop */
340: };
341:
342: void
343: ether503link(void)
344: {
345: addethercard("3C503", ccc503reset);
346: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.