This source file includes following definitions.
- wdprobe
- wdprobe1
- wd_reset_8390
- wd_block_input
- wd_block_output
- wd_close_card
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 static char *version =
18 "wd.c:v0.99-10 5/28/93 Donald Becker (becker@super.org)\n";
19
20 #include <linux/config.h>
21 #include <linux/kernel.h>
22 #include <linux/sched.h>
23 #include <asm/io.h>
24 #include <asm/system.h>
25 #include <memory.h>
26
27 #include "dev.h"
28 #include "8390.h"
29
30
31 extern void NS8390_init(struct device *dev, int startp);
32 extern int ei_debug;
33 extern struct sigaction ei_sigaction;
34
35 int wdprobe(int ioaddr, struct device *dev);
36 int wdprobe1(int ioaddr, struct device *dev);
37
38 static void wd_reset_8390(struct device *dev);
39 static int wd_block_input(struct device *dev, int count,
40 char *buf, int ring_offset);
41 static void wd_block_output(struct device *dev, int count,
42 const unsigned char *buf, const start_page);
43 static int wd_close_card(struct device *dev);
44
45
46 #define WD_START_PG 0x00
47 #define WD03_STOP_PG 0x20
48 #define WD13_STOP_PG 0x40
49
50 #define WD_CMDREG 0
51 #define WD_RESET 0x80
52 #define WD_MEMENB 0x40
53 #define WD_CMDREG5 5
54 #define ISA16 0x80
55 #define NIC16 0x40
56 #define WD_NIC_OFFSET 16
57
58
59
60
61
62
63
64
65
66 int wdprobe(int ioaddr, struct device *dev)
67 {
68 int *port, ports[] = {0x300, 0x280, 0x380, 0x240, 0};
69
70 if (ioaddr > 0x100)
71 return wdprobe1(ioaddr, dev);
72
73 for (port = &ports[0]; *port; port++)
74 if (inb(*port + 8) != 0xff
75 && inb(*port + 9) != 0xff
76 && wdprobe1(*port, dev))
77 return *port;
78 return 0;
79 }
80
81 int wdprobe1(int ioaddr, struct device *dev)
82 {
83 int i;
84 unsigned char *station_addr = dev->dev_addr;
85 int checksum = 0;
86 int ancient = 0;
87
88 #if defined(EI_DEBUG) && EI_DEBUG > 2
89 printk("WD80x3 ethercard at %#3x:", ioaddr);
90 for (i = 0; i < 16; i++) {
91 printk(" %2.2X", inb(ioaddr+i));
92 }
93 printk("\n");
94 printk("WD80x3 ethercard at %#3x:", ioaddr+i);
95 for (;i < 33; i++) {
96 printk(" %2.2X", inb(ioaddr+i));
97 }
98 printk("\n");
99 #endif
100 printk("WD80x3 ethercard probe at %#3x:", ioaddr);
101 for (i = 0; i < 8; i++) {
102 int inval = inb(ioaddr + 8 + i);
103 checksum += inval;
104 if (i < 6)
105 printk(" %2.2X", (station_addr[i] = inval));
106 }
107
108 if ((checksum & 0xff) != 0xFF) {
109 printk(" not found (%#2.2x).\n", checksum);
110 return 0;
111 }
112
113 ei_status.name = "WD8003";
114 ei_status.word16 = 0;
115
116
117
118
119
120
121 if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
122 ei_status.name = "PDI8023";
123
124
125
126
127
128 switch (inb(ioaddr+2)) {
129 case 0x03:
130 ei_status.word16 = 0;
131 ei_status.name = "PDI8023-8";
132 break;
133
134 case 0x05:
135
136 ei_status.word16 = 0;
137 ei_status.name = "PDUC8023";
138 break;
139
140 case 0x0a:
141 ei_status.word16 = 1;
142 ei_status.name = "PDI8023-16";
143 break;
144
145 default:
146
147 ei_status.word16 = 0;
148 ei_status.name = "PDI8023";
149 break;
150 }
151 dev->mem_start = ((inb(ioaddr+5) & 0x1c) + 0xc0) << 12;
152 dev->irq = (inb(ioaddr+5) >> 5) & 0x07;
153 if (dev->irq == 7)
154 dev->irq = 10;
155 else
156 dev->irq++;
157 }
158
159
160
161
162
163 #ifndef FORCE_8BIT
164
165
166 for (i = 0; i < 6; i++)
167 if (inb(ioaddr+i) != inb(ioaddr+8+i))
168 break;
169 if (i >= 6) {
170 ancient = 1;
171 ei_status.name = "WD8003-old";
172 } else {
173 int tmp = inb(ioaddr+1);
174 outb( tmp ^ 0x01, ioaddr+1 );
175 if (((inb( ioaddr+1) & 0x01) == 0x01)
176 && (tmp & 0x01) == 0x01 ) {
177 int asic_reg5 = inb(ioaddr+WD_CMDREG5);
178
179 outb( ISA16 | NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
180 outb(tmp, ioaddr+1);
181 ei_status.name = "WD8013";
182 ei_status.word16 = 1;
183 }
184 outb(tmp, ioaddr+1);
185 }
186 #endif
187
188 #ifndef final_version
189 if ( !ancient && (inb(ioaddr+1) & 0x01) != (ei_status.word16 & 0x01))
190 printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
191 ei_status.word16 ? 16:8, (inb(ioaddr+1) & 0x01) ? 16 : 8);
192 #endif
193
194 #if defined(WD_SHMEM) && WD_SHMEM > 0x80000
195
196 dev->mem_start = WD_SHMEM;
197 #else
198 if (dev->mem_start == 0) {
199
200 int reg0 = inb(ioaddr);
201 if (reg0 == 0xff) {
202
203 dev->mem_start = 0xd0000;
204 printk(" assigning address %#x", dev->mem_start);
205 } else {
206 int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
207
208 if (high_addr_bits == 0x1f || ei_status.word16 == 0)
209 high_addr_bits = 0x01;
210 dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19);
211 }
212 }
213 #endif
214
215
216 dev->base_addr = ioaddr+WD_NIC_OFFSET;
217
218 ei_status.tx_start_page = WD_START_PG;
219 ei_status.rx_start_page = WD_START_PG + TX_PAGES;
220 ei_status.stop_page = ei_status.word16 ? WD13_STOP_PG : WD03_STOP_PG;
221
222 dev->rmem_start = dev->mem_start + TX_PAGES*256;
223 dev->mem_end = dev->rmem_end
224 = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
225
226 if (dev->irq < 2) {
227 int irqmap[] = {9,3,5,7,10,11,15,4};
228 int reg1 = inb(ioaddr+1);
229 int reg4 = inb(ioaddr+4);
230 if (reg1 == 0xff){
231 dev->irq = ei_status.word16 ? 10 : 5;
232 } else
233 dev->irq = irqmap[((reg4 >> 5) & 0x03)
234 + (reg1 & 0x04)];
235 } else if (dev->irq == 2)
236
237
238 dev->irq = 9;
239
240
241
242 { int irqval = irqaction (dev->irq, &ei_sigaction);
243 if (irqval) {
244 printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
245 return 0;
246 }
247 }
248
249 printk("\n%s: %s using IRQ %d with shared memory at %#x-%#x.\n",
250 dev->name, ei_status.name, dev->irq, dev->mem_start, dev->mem_end-1);
251 if (ei_debug > 1)
252 printk(version);
253
254 #if defined(EI_DEBUG) && EI_DEBUG > 2
255 printk("%s: Address read from register is %#x, setting address %#x\n",
256 ei_status.name,
257 ((inb(ioaddr+WD_CMDREG5)&0x1f)<<19) + ((inb(ioaddr)&0x3f) << 13),
258 dev->mem_start);
259 #endif
260
261
262
263 if (ei_status.word16)
264 outb( ISA16 | NIC16 | ((dev->mem_start>>19) & 0x1f), ioaddr+WD_CMDREG5);
265 outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), ioaddr);
266
267 ei_status.reset_8390 = &wd_reset_8390;
268 ei_status.block_input = &wd_block_input;
269 ei_status.block_output = &wd_block_output;
270 dev->stop = &wd_close_card;
271 NS8390_init(dev, 0);
272
273 return dev->base_addr;
274 }
275
276 static void
277 wd_reset_8390(struct device *dev)
278 {
279 int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET;
280 int reset_start_time = jiffies;
281
282 outb(WD_RESET, wd_cmd_port);
283 if (ei_debug > 1) printk("resetting the WD80x3 t=%d...", jiffies);
284 ei_status.txing = 0;
285
286 sti();
287
288
289 {
290 int boguscount = 150000;
291 while(jiffies - reset_start_time < 2)
292 if (boguscount-- < 0) {
293 printk("jiffy failure (t=%d)...", jiffies);
294 break;
295 }
296 }
297
298
299 if (ei_status.word16)
300 outb(NIC16 | ((dev->mem_start>>19) & 0x1f),
301 wd_cmd_port+WD_CMDREG5);
302 outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port);
303
304 while ((inb(dev->base_addr+EN0_ISR) & ENISR_RESET) == 0)
305 if (jiffies - reset_start_time > 2) {
306 printk("%s: wd_reset_8390() did not complete.\n", dev->name);
307 break;
308 }
309 #if defined(EI_DEBUG) && EI_DEBUG > 2
310 {
311 int i;
312 printk("\nWD80x3 ethercard at %#3x:", wd_cmd_port);
313 for (i = 0; i < 16; i++) {
314 printk(" %2.2X", inb(wd_cmd_port+i));
315 }
316 printk("\nWD80x3 ethercard at %#3x:", wd_cmd_port+i);
317 for (;i < 33; i++) {
318 printk(" %2.2X", inb(wd_cmd_port+i));
319 }
320 printk("\n");
321 }
322 #endif
323 }
324
325
326
327
328 static int
329 wd_block_input(struct device *dev, int count, char *buf, int ring_offset)
330 {
331 void *xfer_start = (void *)(dev->mem_start + ring_offset - (WD_START_PG<<8));
332 #if !defined(WD_no_mapout)
333 int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET;
334 int reg5_val = ((dev->mem_start>>19) & 0x1f) | NIC16;
335
336
337 if (ei_status.word16)
338 outb(ISA16 | reg5_val, wd_cmdreg + WD_CMDREG5 );
339 outb((((dev->mem_start>>13) & 0x3f) | WD_MEMENB), wd_cmdreg);
340 #endif
341 if (xfer_start + count > (void*) dev->rmem_end) {
342
343 int semi_count = (void*)dev->rmem_end - xfer_start;
344 memcpy(buf, xfer_start, semi_count);
345 count -= semi_count;
346 memcpy(buf + semi_count, (char *)dev->rmem_start, count);
347 return dev->rmem_start + count;
348 }
349 memcpy(buf, xfer_start, count);
350 if (ei_debug > 4) {
351 unsigned short *board = (unsigned short *) xfer_start;
352 printk("%s: wd8013 block_input(cnt=%d offset=%3x addr=%#x) = %2x %2x %2x...\n",
353 dev->name, count, ring_offset, xfer_start,
354 board[-1], board[0], board[1]);
355 }
356 #if !defined(WD_no_mapout)
357
358 if (ei_status.word16)
359 outb(reg5_val, wd_cmdreg + WD_CMDREG5 );
360 #endif
361 return ring_offset + count;
362 }
363
364
365
366 static void
367 wd_block_output(struct device *dev, int count, const unsigned char *buf,
368 int start_page)
369 {
370 unsigned char *shmem
371 = (unsigned char *)dev->mem_start + ((start_page - WD_START_PG)<<8);
372 #if !defined(WD_no_mapout)
373 int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET;
374 int reg5_val = ((dev->mem_start>>19) & 0x1f) | NIC16;
375
376
377 if (ei_status.word16)
378 outb(ISA16 | reg5_val, wd_cmdreg + WD_CMDREG5 );
379 outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmdreg);
380 #endif
381 memcpy(shmem, buf, count);
382 if (ei_debug > 4)
383 printk("%s: wd80*3 block_output(addr=%#x cnt=%d) -> %2x=%2x %2x=%2x %d...\n",
384 shmem, count, shmem[23], buf[23], shmem[24], buf[24], memcmp(shmem,buf,count));
385 #if !defined(WD_no_mapout)
386
387 if (ei_status.word16)
388 outb(reg5_val, wd_cmdreg + WD_CMDREG5 );
389 #endif
390 }
391
392
393 static int
394 wd_close_card(struct device *dev)
395 {
396 int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET;
397
398 if (ei_debug > 1)
399 printk("%s: Shutting down ethercard.\n", dev->name);
400 NS8390_init(dev, 0);
401
402
403 outb(((dev->mem_start>>19) & 0x1f) | NIC16, wd_cmdreg + WD_CMDREG5 );
404 outb((((dev->mem_start>>13) & 0x3f)), wd_cmdreg);
405
406 return 0;
407 }
408
409
410
411
412
413
414
415
416