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