diff options
Diffstat (limited to 'drivers/net/oaknet.c')
-rw-r--r-- | drivers/net/oaknet.c | 666 |
1 files changed, 0 insertions, 666 deletions
diff --git a/drivers/net/oaknet.c b/drivers/net/oaknet.c deleted file mode 100644 index 702e3e95612a..000000000000 --- a/drivers/net/oaknet.c +++ /dev/null | |||
@@ -1,666 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu> | ||
4 | * | ||
5 | * Module name: oaknet.c | ||
6 | * | ||
7 | * Description: | ||
8 | * Driver for the National Semiconductor DP83902AV Ethernet controller | ||
9 | * on-board the IBM PowerPC "Oak" evaluation board. Adapted from the | ||
10 | * various other 8390 drivers written by Donald Becker and Paul Gortmaker. | ||
11 | * | ||
12 | * Additional inspiration from the "tcd8390.c" driver from TiVo, Inc. | ||
13 | * and "enetLib.c" from IBM. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/etherdevice.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/jiffies.h> | ||
24 | |||
25 | #include <asm/board.h> | ||
26 | #include <asm/io.h> | ||
27 | |||
28 | #include "8390.h" | ||
29 | |||
30 | |||
31 | /* Preprocessor Defines */ | ||
32 | |||
33 | #if !defined(TRUE) || TRUE != 1 | ||
34 | #define TRUE 1 | ||
35 | #endif | ||
36 | |||
37 | #if !defined(FALSE) || FALSE != 0 | ||
38 | #define FALSE 0 | ||
39 | #endif | ||
40 | |||
41 | #define OAKNET_START_PG 0x20 /* First page of TX buffer */ | ||
42 | #define OAKNET_STOP_PG 0x40 /* Last pagge +1 of RX ring */ | ||
43 | |||
44 | #define OAKNET_WAIT (2 * HZ / 100) /* 20 ms */ | ||
45 | |||
46 | /* Experimenting with some fixes for a broken driver... */ | ||
47 | |||
48 | #define OAKNET_DISINT | ||
49 | #define OAKNET_HEADCHECK | ||
50 | #define OAKNET_RWFIX | ||
51 | |||
52 | |||
53 | /* Global Variables */ | ||
54 | |||
55 | static const char *name = "National DP83902AV"; | ||
56 | |||
57 | static struct net_device *oaknet_devs; | ||
58 | |||
59 | |||
60 | /* Function Prototypes */ | ||
61 | |||
62 | static int oaknet_open(struct net_device *dev); | ||
63 | static int oaknet_close(struct net_device *dev); | ||
64 | |||
65 | static void oaknet_reset_8390(struct net_device *dev); | ||
66 | static void oaknet_get_8390_hdr(struct net_device *dev, | ||
67 | struct e8390_pkt_hdr *hdr, int ring_page); | ||
68 | static void oaknet_block_input(struct net_device *dev, int count, | ||
69 | struct sk_buff *skb, int ring_offset); | ||
70 | static void oaknet_block_output(struct net_device *dev, int count, | ||
71 | const unsigned char *buf, int start_page); | ||
72 | |||
73 | static void oaknet_dma_error(struct net_device *dev, const char *name); | ||
74 | |||
75 | |||
76 | /* | ||
77 | * int oaknet_init() | ||
78 | * | ||
79 | * Description: | ||
80 | * This routine performs all the necessary platform-specific initiali- | ||
81 | * zation and set-up for the IBM "Oak" evaluation board's National | ||
82 | * Semiconductor DP83902AV "ST-NIC" Ethernet controller. | ||
83 | * | ||
84 | * Input(s): | ||
85 | * N/A | ||
86 | * | ||
87 | * Output(s): | ||
88 | * N/A | ||
89 | * | ||
90 | * Returns: | ||
91 | * 0 if OK, otherwise system error number on error. | ||
92 | * | ||
93 | */ | ||
94 | static int __init oaknet_init(void) | ||
95 | { | ||
96 | register int i; | ||
97 | int reg0, regd; | ||
98 | int ret = -ENOMEM; | ||
99 | struct net_device *dev; | ||
100 | #if 0 | ||
101 | unsigned long ioaddr = OAKNET_IO_BASE; | ||
102 | #else | ||
103 | unsigned long ioaddr = ioremap(OAKNET_IO_BASE, OAKNET_IO_SIZE); | ||
104 | #endif | ||
105 | bd_t *bip = (bd_t *)__res; | ||
106 | |||
107 | if (!ioaddr) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | dev = alloc_ei_netdev(); | ||
111 | if (!dev) | ||
112 | goto out_unmap; | ||
113 | |||
114 | ret = -EBUSY; | ||
115 | if (!request_region(OAKNET_IO_BASE, OAKNET_IO_SIZE, name)) | ||
116 | goto out_dev; | ||
117 | |||
118 | /* Quick register check to see if the device is really there. */ | ||
119 | |||
120 | ret = -ENODEV; | ||
121 | if ((reg0 = ei_ibp(ioaddr)) == 0xFF) | ||
122 | goto out_region; | ||
123 | |||
124 | /* | ||
125 | * That worked. Now a more thorough check, using the multicast | ||
126 | * address registers, that the device is definitely out there | ||
127 | * and semi-functional. | ||
128 | */ | ||
129 | |||
130 | ei_obp(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD); | ||
131 | regd = ei_ibp(ioaddr + 0x0D); | ||
132 | ei_obp(0xFF, ioaddr + 0x0D); | ||
133 | ei_obp(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD); | ||
134 | ei_ibp(ioaddr + EN0_COUNTER0); | ||
135 | |||
136 | /* It's no good. Fix things back up and leave. */ | ||
137 | |||
138 | ret = -ENODEV; | ||
139 | if (ei_ibp(ioaddr + EN0_COUNTER0) != 0) { | ||
140 | ei_obp(reg0, ioaddr); | ||
141 | ei_obp(regd, ioaddr + 0x0D); | ||
142 | goto out_region; | ||
143 | } | ||
144 | |||
145 | SET_MODULE_OWNER(dev); | ||
146 | |||
147 | /* | ||
148 | * This controller is on an embedded board, so the base address | ||
149 | * and interrupt assignments are pre-assigned and unchageable. | ||
150 | */ | ||
151 | |||
152 | dev->base_addr = ioaddr; | ||
153 | dev->irq = OAKNET_INT; | ||
154 | |||
155 | /* | ||
156 | * Disable all chip interrupts for now and ACK all pending | ||
157 | * interrupts. | ||
158 | */ | ||
159 | |||
160 | ei_obp(0x0, ioaddr + EN0_IMR); | ||
161 | ei_obp(0xFF, ioaddr + EN0_ISR); | ||
162 | |||
163 | /* Attempt to get the interrupt line */ | ||
164 | |||
165 | ret = -EAGAIN; | ||
166 | if (request_irq(dev->irq, ei_interrupt, 0, name, dev)) { | ||
167 | printk("%s: unable to request interrupt %d.\n", | ||
168 | name, dev->irq); | ||
169 | goto out_region; | ||
170 | } | ||
171 | |||
172 | /* Tell the world about what and where we've found. */ | ||
173 | |||
174 | printk("%s: %s at", dev->name, name); | ||
175 | for (i = 0; i < ETHER_ADDR_LEN; ++i) { | ||
176 | dev->dev_addr[i] = bip->bi_enetaddr[i]; | ||
177 | printk("%c%.2x", (i ? ':' : ' '), dev->dev_addr[i]); | ||
178 | } | ||
179 | printk(", found at %#lx, using IRQ %d.\n", dev->base_addr, dev->irq); | ||
180 | |||
181 | /* Set up some required driver fields and then we're done. */ | ||
182 | |||
183 | ei_status.name = name; | ||
184 | ei_status.word16 = FALSE; | ||
185 | ei_status.tx_start_page = OAKNET_START_PG; | ||
186 | ei_status.rx_start_page = OAKNET_START_PG + TX_PAGES; | ||
187 | ei_status.stop_page = OAKNET_STOP_PG; | ||
188 | |||
189 | ei_status.reset_8390 = &oaknet_reset_8390; | ||
190 | ei_status.block_input = &oaknet_block_input; | ||
191 | ei_status.block_output = &oaknet_block_output; | ||
192 | ei_status.get_8390_hdr = &oaknet_get_8390_hdr; | ||
193 | |||
194 | dev->open = oaknet_open; | ||
195 | dev->stop = oaknet_close; | ||
196 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
197 | dev->poll_controller = ei_poll; | ||
198 | #endif | ||
199 | |||
200 | NS8390_init(dev, FALSE); | ||
201 | ret = register_netdev(dev); | ||
202 | if (ret) | ||
203 | goto out_irq; | ||
204 | |||
205 | oaknet_devs = dev; | ||
206 | return 0; | ||
207 | |||
208 | out_irq; | ||
209 | free_irq(dev->irq, dev); | ||
210 | out_region: | ||
211 | release_region(OAKNET_IO_BASE, OAKNET_IO_SIZE); | ||
212 | out_dev: | ||
213 | free_netdev(dev); | ||
214 | out_unmap: | ||
215 | iounmap(ioaddr); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * static int oaknet_open() | ||
221 | * | ||
222 | * Description: | ||
223 | * This routine is a modest wrapper around ei_open, the 8390-generic, | ||
224 | * driver open routine. This just increments the module usage count | ||
225 | * and passes along the status from ei_open. | ||
226 | * | ||
227 | * Input(s): | ||
228 | * *dev - Pointer to the device structure for this driver. | ||
229 | * | ||
230 | * Output(s): | ||
231 | * *dev - Pointer to the device structure for this driver, potentially | ||
232 | * modified by ei_open. | ||
233 | * | ||
234 | * Returns: | ||
235 | * 0 if OK, otherwise < 0 on error. | ||
236 | * | ||
237 | */ | ||
238 | static int | ||
239 | oaknet_open(struct net_device *dev) | ||
240 | { | ||
241 | int status = ei_open(dev); | ||
242 | return (status); | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * static int oaknet_close() | ||
247 | * | ||
248 | * Description: | ||
249 | * This routine is a modest wrapper around ei_close, the 8390-generic, | ||
250 | * driver close routine. This just decrements the module usage count | ||
251 | * and passes along the status from ei_close. | ||
252 | * | ||
253 | * Input(s): | ||
254 | * *dev - Pointer to the device structure for this driver. | ||
255 | * | ||
256 | * Output(s): | ||
257 | * *dev - Pointer to the device structure for this driver, potentially | ||
258 | * modified by ei_close. | ||
259 | * | ||
260 | * Returns: | ||
261 | * 0 if OK, otherwise < 0 on error. | ||
262 | * | ||
263 | */ | ||
264 | static int | ||
265 | oaknet_close(struct net_device *dev) | ||
266 | { | ||
267 | int status = ei_close(dev); | ||
268 | return (status); | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * static void oaknet_reset_8390() | ||
273 | * | ||
274 | * Description: | ||
275 | * This routine resets the DP83902 chip. | ||
276 | * | ||
277 | * Input(s): | ||
278 | * *dev - Pointer to the device structure for this driver. | ||
279 | * | ||
280 | * Output(s): | ||
281 | * N/A | ||
282 | * | ||
283 | * Returns: | ||
284 | * N/A | ||
285 | * | ||
286 | */ | ||
287 | static void | ||
288 | oaknet_reset_8390(struct net_device *dev) | ||
289 | { | ||
290 | int base = E8390_BASE; | ||
291 | |||
292 | /* | ||
293 | * We have no provision of reseting the controller as is done | ||
294 | * in other drivers, such as "ne.c". However, the following | ||
295 | * seems to work well enough in the TiVo driver. | ||
296 | */ | ||
297 | |||
298 | printk("Resetting %s...\n", dev->name); | ||
299 | ei_obp(E8390_STOP | E8390_NODMA | E8390_PAGE0, base + E8390_CMD); | ||
300 | ei_status.txing = 0; | ||
301 | ei_status.dmaing = 0; | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * static void oaknet_get_8390_hdr() | ||
306 | * | ||
307 | * Description: | ||
308 | * This routine grabs the 8390-specific header. It's similar to the | ||
309 | * block input routine, but we don't need to be concerned with ring wrap | ||
310 | * as the header will be at the start of a page, so we optimize accordingly. | ||
311 | * | ||
312 | * Input(s): | ||
313 | * *dev - Pointer to the device structure for this driver. | ||
314 | * *hdr - Pointer to storage for the 8390-specific packet header. | ||
315 | * ring_page - ? | ||
316 | * | ||
317 | * Output(s): | ||
318 | * *hdr - Pointer to the 8390-specific packet header for the just- | ||
319 | * received frame. | ||
320 | * | ||
321 | * Returns: | ||
322 | * N/A | ||
323 | * | ||
324 | */ | ||
325 | static void | ||
326 | oaknet_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, | ||
327 | int ring_page) | ||
328 | { | ||
329 | int base = dev->base_addr; | ||
330 | |||
331 | /* | ||
332 | * This should NOT happen. If it does, it is the LAST thing you'll | ||
333 | * see. | ||
334 | */ | ||
335 | |||
336 | if (ei_status.dmaing) { | ||
337 | oaknet_dma_error(dev, "oaknet_get_8390_hdr"); | ||
338 | return; | ||
339 | } | ||
340 | |||
341 | ei_status.dmaing |= 0x01; | ||
342 | outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, base + OAKNET_CMD); | ||
343 | outb_p(sizeof(struct e8390_pkt_hdr), base + EN0_RCNTLO); | ||
344 | outb_p(0, base + EN0_RCNTHI); | ||
345 | outb_p(0, base + EN0_RSARLO); /* On page boundary */ | ||
346 | outb_p(ring_page, base + EN0_RSARHI); | ||
347 | outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD); | ||
348 | |||
349 | if (ei_status.word16) | ||
350 | insw(base + OAKNET_DATA, hdr, | ||
351 | sizeof(struct e8390_pkt_hdr) >> 1); | ||
352 | else | ||
353 | insb(base + OAKNET_DATA, hdr, | ||
354 | sizeof(struct e8390_pkt_hdr)); | ||
355 | |||
356 | /* Byte-swap the packet byte count */ | ||
357 | |||
358 | hdr->count = le16_to_cpu(hdr->count); | ||
359 | |||
360 | outb_p(ENISR_RDC, base + EN0_ISR); /* ACK Remote DMA interrupt */ | ||
361 | ei_status.dmaing &= ~0x01; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * XXX - Document me. | ||
366 | */ | ||
367 | static void | ||
368 | oaknet_block_input(struct net_device *dev, int count, struct sk_buff *skb, | ||
369 | int ring_offset) | ||
370 | { | ||
371 | int base = OAKNET_BASE; | ||
372 | char *buf = skb->data; | ||
373 | |||
374 | /* | ||
375 | * This should NOT happen. If it does, it is the LAST thing you'll | ||
376 | * see. | ||
377 | */ | ||
378 | |||
379 | if (ei_status.dmaing) { | ||
380 | oaknet_dma_error(dev, "oaknet_block_input"); | ||
381 | return; | ||
382 | } | ||
383 | |||
384 | #ifdef OAKNET_DISINT | ||
385 | save_flags(flags); | ||
386 | cli(); | ||
387 | #endif | ||
388 | |||
389 | ei_status.dmaing |= 0x01; | ||
390 | ei_obp(E8390_NODMA + E8390_PAGE0 + E8390_START, base + E8390_CMD); | ||
391 | ei_obp(count & 0xff, base + EN0_RCNTLO); | ||
392 | ei_obp(count >> 8, base + EN0_RCNTHI); | ||
393 | ei_obp(ring_offset & 0xff, base + EN0_RSARLO); | ||
394 | ei_obp(ring_offset >> 8, base + EN0_RSARHI); | ||
395 | ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD); | ||
396 | if (ei_status.word16) { | ||
397 | ei_isw(base + E8390_DATA, buf, count >> 1); | ||
398 | if (count & 0x01) { | ||
399 | buf[count - 1] = ei_ib(base + E8390_DATA); | ||
400 | #ifdef OAKNET_HEADCHECK | ||
401 | bytes++; | ||
402 | #endif | ||
403 | } | ||
404 | } else { | ||
405 | ei_isb(base + E8390_DATA, buf, count); | ||
406 | } | ||
407 | #ifdef OAKNET_HEADCHECK | ||
408 | /* | ||
409 | * This was for the ALPHA version only, but enough people have | ||
410 | * been encountering problems so it is still here. If you see | ||
411 | * this message you either 1) have a slightly incompatible clone | ||
412 | * or 2) have noise/speed problems with your bus. | ||
413 | */ | ||
414 | |||
415 | /* DMA termination address check... */ | ||
416 | { | ||
417 | int addr, tries = 20; | ||
418 | do { | ||
419 | /* DON'T check for 'ei_ibp(EN0_ISR) & ENISR_RDC' here | ||
420 | -- it's broken for Rx on some cards! */ | ||
421 | int high = ei_ibp(base + EN0_RSARHI); | ||
422 | int low = ei_ibp(base + EN0_RSARLO); | ||
423 | addr = (high << 8) + low; | ||
424 | if (((ring_offset + bytes) & 0xff) == low) | ||
425 | break; | ||
426 | } while (--tries > 0); | ||
427 | if (tries <= 0) | ||
428 | printk("%s: RX transfer address mismatch," | ||
429 | "%#4.4x (expected) vs. %#4.4x (actual).\n", | ||
430 | dev->name, ring_offset + bytes, addr); | ||
431 | } | ||
432 | #endif | ||
433 | ei_obp(ENISR_RDC, base + EN0_ISR); /* ACK Remote DMA interrupt */ | ||
434 | ei_status.dmaing &= ~0x01; | ||
435 | |||
436 | #ifdef OAKNET_DISINT | ||
437 | restore_flags(flags); | ||
438 | #endif | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * static void oaknet_block_output() | ||
443 | * | ||
444 | * Description: | ||
445 | * This routine... | ||
446 | * | ||
447 | * Input(s): | ||
448 | * *dev - Pointer to the device structure for this driver. | ||
449 | * count - Number of bytes to be transferred. | ||
450 | * *buf - | ||
451 | * start_page - | ||
452 | * | ||
453 | * Output(s): | ||
454 | * N/A | ||
455 | * | ||
456 | * Returns: | ||
457 | * N/A | ||
458 | * | ||
459 | */ | ||
460 | static void | ||
461 | oaknet_block_output(struct net_device *dev, int count, | ||
462 | const unsigned char *buf, int start_page) | ||
463 | { | ||
464 | int base = E8390_BASE; | ||
465 | #if 0 | ||
466 | int bug; | ||
467 | #endif | ||
468 | unsigned long start; | ||
469 | #ifdef OAKNET_DISINT | ||
470 | unsigned long flags; | ||
471 | #endif | ||
472 | #ifdef OAKNET_HEADCHECK | ||
473 | int retries = 0; | ||
474 | #endif | ||
475 | |||
476 | /* Round the count up for word writes. */ | ||
477 | |||
478 | if (ei_status.word16 && (count & 0x1)) | ||
479 | count++; | ||
480 | |||
481 | /* | ||
482 | * This should NOT happen. If it does, it is the LAST thing you'll | ||
483 | * see. | ||
484 | */ | ||
485 | |||
486 | if (ei_status.dmaing) { | ||
487 | oaknet_dma_error(dev, "oaknet_block_output"); | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | #ifdef OAKNET_DISINT | ||
492 | save_flags(flags); | ||
493 | cli(); | ||
494 | #endif | ||
495 | |||
496 | ei_status.dmaing |= 0x01; | ||
497 | |||
498 | /* Make sure we are in page 0. */ | ||
499 | |||
500 | ei_obp(E8390_PAGE0 + E8390_START + E8390_NODMA, base + E8390_CMD); | ||
501 | |||
502 | #ifdef OAKNET_HEADCHECK | ||
503 | retry: | ||
504 | #endif | ||
505 | |||
506 | #if 0 | ||
507 | /* | ||
508 | * The 83902 documentation states that the processor needs to | ||
509 | * do a "dummy read" before doing the remote write to work | ||
510 | * around a chip bug they don't feel like fixing. | ||
511 | */ | ||
512 | |||
513 | bug = 0; | ||
514 | while (1) { | ||
515 | unsigned int rdhi; | ||
516 | unsigned int rdlo; | ||
517 | |||
518 | /* Now the normal output. */ | ||
519 | ei_obp(ENISR_RDC, base + EN0_ISR); | ||
520 | ei_obp(count & 0xff, base + EN0_RCNTLO); | ||
521 | ei_obp(count >> 8, base + EN0_RCNTHI); | ||
522 | ei_obp(0x00, base + EN0_RSARLO); | ||
523 | ei_obp(start_page, base + EN0_RSARHI); | ||
524 | |||
525 | if (bug++) | ||
526 | break; | ||
527 | |||
528 | /* Perform the dummy read */ | ||
529 | rdhi = ei_ibp(base + EN0_CRDAHI); | ||
530 | rdlo = ei_ibp(base + EN0_CRDALO); | ||
531 | ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD); | ||
532 | |||
533 | while (1) { | ||
534 | unsigned int nrdhi; | ||
535 | unsigned int nrdlo; | ||
536 | nrdhi = ei_ibp(base + EN0_CRDAHI); | ||
537 | nrdlo = ei_ibp(base + EN0_CRDALO); | ||
538 | if ((rdhi != nrdhi) || (rdlo != nrdlo)) | ||
539 | break; | ||
540 | } | ||
541 | } | ||
542 | #else | ||
543 | #ifdef OAKNET_RWFIX | ||
544 | /* | ||
545 | * Handle the read-before-write bug the same way as the | ||
546 | * Crynwr packet driver -- the Nat'l Semi. method doesn't work. | ||
547 | * Actually this doesn't always work either, but if you have | ||
548 | * problems with your 83902 this is better than nothing! | ||
549 | */ | ||
550 | |||
551 | ei_obp(0x42, base + EN0_RCNTLO); | ||
552 | ei_obp(0x00, base + EN0_RCNTHI); | ||
553 | ei_obp(0x42, base + EN0_RSARLO); | ||
554 | ei_obp(0x00, base + EN0_RSARHI); | ||
555 | ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD); | ||
556 | /* Make certain that the dummy read has occurred. */ | ||
557 | udelay(6); | ||
558 | #endif | ||
559 | |||
560 | ei_obp(ENISR_RDC, base + EN0_ISR); | ||
561 | |||
562 | /* Now the normal output. */ | ||
563 | ei_obp(count & 0xff, base + EN0_RCNTLO); | ||
564 | ei_obp(count >> 8, base + EN0_RCNTHI); | ||
565 | ei_obp(0x00, base + EN0_RSARLO); | ||
566 | ei_obp(start_page, base + EN0_RSARHI); | ||
567 | #endif /* 0/1 */ | ||
568 | |||
569 | ei_obp(E8390_RWRITE + E8390_START, base + E8390_CMD); | ||
570 | if (ei_status.word16) { | ||
571 | ei_osw(E8390_BASE + E8390_DATA, buf, count >> 1); | ||
572 | } else { | ||
573 | ei_osb(E8390_BASE + E8390_DATA, buf, count); | ||
574 | } | ||
575 | |||
576 | #ifdef OAKNET_DISINT | ||
577 | restore_flags(flags); | ||
578 | #endif | ||
579 | |||
580 | start = jiffies; | ||
581 | |||
582 | #ifdef OAKNET_HEADCHECK | ||
583 | /* | ||
584 | * This was for the ALPHA version only, but enough people have | ||
585 | * been encountering problems so it is still here. | ||
586 | */ | ||
587 | |||
588 | { | ||
589 | /* DMA termination address check... */ | ||
590 | int addr, tries = 20; | ||
591 | do { | ||
592 | int high = ei_ibp(base + EN0_RSARHI); | ||
593 | int low = ei_ibp(base + EN0_RSARLO); | ||
594 | addr = (high << 8) + low; | ||
595 | if ((start_page << 8) + count == addr) | ||
596 | break; | ||
597 | } while (--tries > 0); | ||
598 | |||
599 | if (tries <= 0) { | ||
600 | printk("%s: Tx packet transfer address mismatch," | ||
601 | "%#4.4x (expected) vs. %#4.4x (actual).\n", | ||
602 | dev->name, (start_page << 8) + count, addr); | ||
603 | if (retries++ == 0) | ||
604 | goto retry; | ||
605 | } | ||
606 | } | ||
607 | #endif | ||
608 | |||
609 | while ((ei_ibp(base + EN0_ISR) & ENISR_RDC) == 0) { | ||
610 | if (time_after(jiffies, start + OAKNET_WAIT)) { | ||
611 | printk("%s: timeout waiting for Tx RDC.\n", dev->name); | ||
612 | oaknet_reset_8390(dev); | ||
613 | NS8390_init(dev, TRUE); | ||
614 | break; | ||
615 | } | ||
616 | } | ||
617 | |||
618 | ei_obp(ENISR_RDC, base + EN0_ISR); /* Ack intr. */ | ||
619 | ei_status.dmaing &= ~0x01; | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * static void oaknet_dma_error() | ||
624 | * | ||
625 | * Description: | ||
626 | * This routine prints out a last-ditch informative message to the console | ||
627 | * indicating that a DMA error occurred. If you see this, it's the last | ||
628 | * thing you'll see. | ||
629 | * | ||
630 | * Input(s): | ||
631 | * *dev - Pointer to the device structure for this driver. | ||
632 | * *name - Informative text (e.g. function name) indicating where the | ||
633 | * DMA error occurred. | ||
634 | * | ||
635 | * Output(s): | ||
636 | * N/A | ||
637 | * | ||
638 | * Returns: | ||
639 | * N/A | ||
640 | * | ||
641 | */ | ||
642 | static void | ||
643 | oaknet_dma_error(struct net_device *dev, const char *name) | ||
644 | { | ||
645 | printk(KERN_EMERG "%s: DMAing conflict in %s." | ||
646 | "[DMAstat:%d][irqlock:%d][intr:%ld]\n", | ||
647 | dev->name, name, ei_status.dmaing, ei_status.irqlock, | ||
648 | dev->interrupt); | ||
649 | } | ||
650 | |||
651 | /* | ||
652 | * Oak Ethernet module unload interface. | ||
653 | */ | ||
654 | static void __exit oaknet_cleanup_module (void) | ||
655 | { | ||
656 | /* Convert to loop once driver supports multiple devices. */ | ||
657 | unregister_netdev(oaknet_dev); | ||
658 | free_irq(oaknet_devs->irq, oaknet_devs); | ||
659 | release_region(oaknet_devs->base_addr, OAKNET_IO_SIZE); | ||
660 | iounmap(ioaddr); | ||
661 | free_netdev(oaknet_devs); | ||
662 | } | ||
663 | |||
664 | module_init(oaknet_init); | ||
665 | module_exit(oaknet_cleanup_module); | ||
666 | MODULE_LICENSE("GPL"); | ||