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