File: /usr/src/linux/drivers/net/mac89x0.c
1 /* mac89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
2 /*
3 Written 1996 by Russell Nelson, with reference to skeleton.c
4 written 1993-1994 by Donald Becker.
5
6 This software may be used and distributed according to the terms
7 of the GNU General Public License, incorporated herein by reference.
8
9 The author may be reached at nelson@crynwr.com, Crynwr
10 Software, 11 Grant St., Potsdam, NY 13676
11
12 Changelog:
13
14 Mike Cruse : mcruse@cti-ltd.com
15 : Changes for Linux 2.0 compatibility.
16 : Added dev_id parameter in net_interrupt(),
17 : request_irq() and free_irq(). Just NULL for now.
18
19 Mike Cruse : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
20 : in net_open() and net_close() so kerneld would know
21 : that the module is in use and wouldn't eject the
22 : driver prematurely.
23
24 Mike Cruse : Rewrote init_module() and cleanup_module using 8390.c
25 : as an example. Disabled autoprobing in init_module(),
26 : not a good thing to do to other devices while Linux
27 : is running from all accounts.
28
29 Alan Cox : Removed 1.2 support, added 2.1 extra counters.
30
31 David Huggins-Daines <dhd@debian.org>
32
33 Split this off into mac89x0.c, and gutted it of all parts which are
34 not relevant to the existing CS8900 cards on the Macintosh
35 (i.e. basically the Daynaport CS and LC cards). To be precise:
36
37 * Removed all the media-detection stuff, because these cards are
38 TP-only.
39
40 * Lobotomized the ISA interrupt bogosity, because these cards use
41 a hardwired NuBus interrupt and a magic ISAIRQ value in the card.
42
43 * Basically eliminated everything not relevant to getting the
44 cards minimally functioning on the Macintosh.
45
46 I might add that these cards are badly designed even from the Mac
47 standpoint, in that Dayna, in their infinite wisdom, used NuBus slot
48 I/O space and NuBus interrupts for these cards, but neglected to
49 provide anything even remotely resembling a NuBus ROM. Therefore we
50 have to probe for them in a brain-damaged ISA-like fashion.
51
52 Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 11/01/2001
53 check kmalloc and release the allocated memory on failure in
54 mac89x0_probe and in init_module
55 use save_flags/restore_flags in net_get_stat, not just cli/sti
56 */
57
58 static char *version =
59 "cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\n";
60
61 /* ======================= configure the driver here ======================= */
62
63 /* use 0 for production, 1 for verification, >2 for debug */
64 #ifndef NET_DEBUG
65 #define NET_DEBUG 0
66 #endif
67
68 /* ======================= end of configuration ======================= */
69
70
71 /* Always include 'config.h' first in case the user wants to turn on
72 or override something. */
73 #include <linux/module.h>
74
75 #define PRINTK(x) printk x
76
77 /*
78 Sources:
79
80 Crynwr packet driver epktisa.
81
82 Crystal Semiconductor data sheets.
83
84 */
85
86 #include <linux/kernel.h>
87 #include <linux/sched.h>
88 #include <linux/types.h>
89 #include <linux/fcntl.h>
90 #include <linux/interrupt.h>
91 #include <linux/ptrace.h>
92 #include <linux/ioport.h>
93 #include <linux/in.h>
94 #include <linux/slab.h>
95 #include <linux/string.h>
96 #include <linux/nubus.h>
97 #include <asm/system.h>
98 #include <asm/bitops.h>
99 #include <asm/io.h>
100 #include <asm/hwtest.h>
101 #include <asm/macints.h>
102 #include <linux/errno.h>
103 #include <linux/init.h>
104
105 #include <linux/netdevice.h>
106 #include <linux/etherdevice.h>
107 #include <linux/skbuff.h>
108 #include "cs89x0.h"
109
110 static unsigned int net_debug = NET_DEBUG;
111
112 /* Information that need to be kept for each board. */
113 struct net_local {
114 struct net_device_stats stats;
115 int chip_type; /* one of: CS8900, CS8920, CS8920M */
116 char chip_revision; /* revision letter of the chip ('A'...) */
117 int send_cmd; /* the propercommand used to send a packet. */
118 int rx_mode;
119 int curr_rx_cfg;
120 int send_underrun; /* keep track of how many underruns in a row we get */
121 struct sk_buff *skb;
122 };
123
124 /* Index to functions, as function prototypes. */
125
126 extern int mac89x0_probe(struct net_device *dev);
127 #if 0
128 extern void reset_chip(struct net_device *dev);
129 #endif
130 static int net_open(struct net_device *dev);
131 static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
132 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
133 static void set_multicast_list(struct net_device *dev);
134 static void net_rx(struct net_device *dev);
135 static int net_close(struct net_device *dev);
136 static struct net_device_stats *net_get_stats(struct net_device *dev);
137 static int set_mac_address(struct net_device *dev, void *addr);
138
139
140 /* Example routines you must write ;->. */
141 #define tx_done(dev) 1
142
143 /* For reading/writing registers ISA-style */
144 static int inline
145 readreg_io(struct net_device *dev, int portno)
146 {
147 writew(swab16(portno), dev->base_addr + ADD_PORT);
148 return swab16(readw(dev->base_addr + DATA_PORT));
149 }
150
151 static void inline
152 writereg_io(struct net_device *dev, int portno, int value)
153 {
154 writew(swab16(portno), dev->base_addr + ADD_PORT);
155 writew(swab16(value), dev->base_addr + DATA_PORT);
156 }
157
158 /* These are for reading/writing registers in shared memory */
159 static int inline
160 readreg(struct net_device *dev, int portno)
161 {
162 return swab16(readw(dev->mem_start + portno));
163 }
164
165 static void inline
166 writereg(struct net_device *dev, int portno, int value)
167 {
168 writew(swab16(value), dev->mem_start + portno);
169 }
170
171 /* Probe for the CS8900 card in slot E. We won't bother looking
172 anywhere else until we have a really good reason to do so. */
173 int __init mac89x0_probe(struct net_device *dev)
174 {
175 static int once_is_enough;
176 struct net_local *lp;
177 static unsigned version_printed;
178 int i, slot;
179 unsigned rev_type = 0;
180 unsigned long ioaddr;
181 unsigned short sig;
182
183 SET_MODULE_OWNER(dev);
184
185 if (once_is_enough)
186 return -ENODEV;
187 once_is_enough = 1;
188
189 /* We might have to parameterize this later */
190 slot = 0xE;
191 /* Get out now if there's a real NuBus card in slot E */
192 if (nubus_find_slot(slot, NULL) != NULL)
193 return -ENODEV;
194
195 /* The pseudo-ISA bits always live at offset 0x300 (gee,
196 wonder why...) */
197 ioaddr = (unsigned long)
198 nubus_slot_addr(slot) | (((slot&0xf) << 20) + DEFAULTIOBASE);
199 {
200 unsigned long flags;
201 int card_present;
202
203 save_flags(flags);
204 cli();
205 card_present = hwreg_present((void*) ioaddr+4)
206 && hwreg_present((void*) ioaddr + DATA_PORT);
207 restore_flags(flags);
208
209 if (!card_present)
210 return -ENODEV;
211 }
212
213 writew(0, ioaddr + ADD_PORT);
214 sig = readw(ioaddr + DATA_PORT);
215 if (sig != swab16(CHIP_EISA_ID_SIG))
216 return -ENODEV;
217
218 /* Initialize the net_device structure. */
219 if (dev->priv == NULL) {
220 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
221 if (!dev->priv)
222 return -ENOMEM;
223 memset(dev->priv, 0, sizeof(struct net_local));
224 }
225 lp = (struct net_local *)dev->priv;
226
227 /* Fill in the 'dev' fields. */
228 dev->base_addr = ioaddr;
229 dev->mem_start = (unsigned long)
230 nubus_slot_addr(slot) | (((slot&0xf) << 20) + MMIOBASE);
231 dev->mem_end = dev->mem_start + 0x1000;
232
233 /* Turn on shared memory */
234 writereg_io(dev, PP_BusCTL, MEMORY_ON);
235
236 /* get the chip type */
237 rev_type = readreg(dev, PRODUCT_ID_ADD);
238 lp->chip_type = rev_type &~ REVISON_BITS;
239 lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
240
241 /* Check the chip type and revision in order to set the correct send command
242 CS8920 revision C and CS8900 revision F can use the faster send. */
243 lp->send_cmd = TX_AFTER_381;
244 if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
245 lp->send_cmd = TX_NOW;
246 if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
247 lp->send_cmd = TX_NOW;
248
249 if (net_debug && version_printed++ == 0)
250 printk(version);
251
252 printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#8lx",
253 dev->name,
254 lp->chip_type==CS8900?'0':'2',
255 lp->chip_type==CS8920M?"M":"",
256 lp->chip_revision,
257 dev->base_addr);
258
259 /* Try to read the MAC address */
260 if ((readreg(dev, PP_SelfST) & (EEPROM_PRESENT | EEPROM_OK)) == 0) {
261 printk("\nmac89x0: No EEPROM, giving up now.\n");
262 kfree(dev->priv);
263 dev->priv = NULL;
264 return -ENODEV;
265 } else {
266 for (i = 0; i < ETH_ALEN; i += 2) {
267 /* Big-endian (why??!) */
268 unsigned short s = readreg(dev, PP_IA + i);
269 dev->dev_addr[i] = s >> 8;
270 dev->dev_addr[i+1] = s & 0xff;
271 }
272 }
273
274 dev->irq = SLOT2IRQ(slot);
275 printk(" IRQ %d ADDR ", dev->irq);
276
277 /* print the ethernet address. */
278 for (i = 0; i < ETH_ALEN; i++)
279 printk("%2.2x%s", dev->dev_addr[i],
280 ((i < ETH_ALEN-1) ? ":" : ""));
281
282 dev->open = net_open;
283 dev->stop = net_close;
284 dev->hard_start_xmit = net_send_packet;
285 dev->get_stats = net_get_stats;
286 dev->set_multicast_list = &set_multicast_list;
287 dev->set_mac_address = &set_mac_address;
288
289 /* Fill in the fields of the net_device structure with ethernet values. */
290 ether_setup(dev);
291
292 printk("\n");
293 return 0;
294 }
295
296 #if 0
297 /* This is useful for something, but I don't know what yet. */
298 void __init reset_chip(struct net_device *dev)
299 {
300 int reset_start_time;
301
302 writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
303
304 /* wait 30 ms */
305 current->state = TASK_INTERRUPTIBLE;
306 schedule_timeout(30*HZ/1000);
307
308 /* Wait until the chip is reset */
309 reset_start_time = jiffies;
310 while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
311 ;
312 }
313 #endif
314
315 /* Open/initialize the board. This is called (in the current kernel)
316 sometime after booting when the 'ifconfig' program is run.
317
318 This routine should set everything up anew at each open, even
319 registers that "should" only need to be set once at boot, so that
320 there is non-reboot way to recover if something goes wrong.
321 */
322 static int
323 net_open(struct net_device *dev)
324 {
325 struct net_local *lp = (struct net_local *)dev->priv;
326 int i;
327
328 /* Disable the interrupt for now */
329 writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) & ~ENABLE_IRQ);
330
331 /* Grab the interrupt */
332 if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev))
333 return -EAGAIN;
334
335 /* Set up the IRQ - Apparently magic */
336 if (lp->chip_type == CS8900)
337 writereg(dev, PP_CS8900_ISAINT, 0);
338 else
339 writereg(dev, PP_CS8920_ISAINT, 0);
340
341 /* set the Ethernet address */
342 for (i=0; i < ETH_ALEN/2; i++)
343 writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
344
345 /* Turn on both receive and transmit operations */
346 writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
347
348 /* Receive only error free packets addressed to this card */
349 lp->rx_mode = 0;
350 writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
351
352 lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
353
354 writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
355
356 writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
357 TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
358
359 writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
360 TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
361
362 /* now that we've got our act together, enable everything */
363 writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
364 netif_start_queue(dev);
365 return 0;
366 }
367
368 static int
369 net_send_packet(struct sk_buff *skb, struct net_device *dev)
370 {
371 if (dev->tbusy) {
372 /* If we get here, some higher level has decided we are broken.
373 There should really be a "kick me" function call instead. */
374 int tickssofar = jiffies - dev->trans_start;
375 if (tickssofar < 5)
376 return 1;
377 if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
378 tx_done(dev) ? "IRQ conflict" : "network cable problem");
379 /* Try to restart the adaptor. */
380 dev->tbusy=0;
381 dev->trans_start = jiffies;
382 }
383
384 /* Block a timer-based transmit from overlapping. This could better be
385 done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
386 if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
387 printk("%s: Transmitter access conflict.\n", dev->name);
388 else {
389 struct net_local *lp = (struct net_local *)dev->priv;
390 unsigned long flags;
391
392 if (net_debug > 3)
393 printk("%s: sent %d byte packet of type %x\n",
394 dev->name, skb->len,
395 (skb->data[ETH_ALEN+ETH_ALEN] << 8)
396 | skb->data[ETH_ALEN+ETH_ALEN+1]);
397
398 /* keep the upload from being interrupted, since we
399 ask the chip to start transmitting before the
400 whole packet has been completely uploaded. */
401 save_flags(flags);
402 cli();
403
404 /* initiate a transmit sequence */
405 writereg(dev, PP_TxCMD, lp->send_cmd);
406 writereg(dev, PP_TxLength, skb->len);
407
408 /* Test to see if the chip has allocated memory for the packet */
409 if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
410 /* Gasp! It hasn't. But that shouldn't happen since
411 we're waiting for TxOk, so return 1 and requeue this packet. */
412 restore_flags(flags);
413 return 1;
414 }
415
416 /* Write the contents of the packet */
417 memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
418
419 restore_flags(flags);
420 dev->trans_start = jiffies;
421 }
422 dev_kfree_skb (skb);
423
424 return 0;
425 }
426
427 /* The typical workload of the driver:
428 Handle the network interface interrupts. */
429 static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
430 {
431 struct net_device *dev = dev_id;
432 struct net_local *lp;
433 int ioaddr, status;
434
435 if (dev == NULL) {
436 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
437 return;
438 }
439 if (dev->interrupt)
440 printk("%s: Re-entering the interrupt handler.\n", dev->name);
441 dev->interrupt = 1;
442
443 ioaddr = dev->base_addr;
444 lp = (struct net_local *)dev->priv;
445
446 /* we MUST read all the events out of the ISQ, otherwise we'll never
447 get interrupted again. As a consequence, we can't have any limit
448 on the number of times we loop in the interrupt handler. The
449 hardware guarantees that eventually we'll run out of events. Of
450 course, if you're on a slow machine, and packets are arriving
451 faster than you can read them off, you're screwed. Hasta la
452 vista, baby! */
453 while ((status = swab16(readw(dev->base_addr + ISQ_PORT)))) {
454 if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
455 switch(status & ISQ_EVENT_MASK) {
456 case ISQ_RECEIVER_EVENT:
457 /* Got a packet(s). */
458 net_rx(dev);
459 break;
460 case ISQ_TRANSMITTER_EVENT:
461 lp->stats.tx_packets++;
462 dev->tbusy = 0;
463 mark_bh(NET_BH); /* Inform upper layers. */
464 if ((status & TX_OK) == 0) lp->stats.tx_errors++;
465 if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
466 if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
467 if (status & TX_LATE_COL) lp->stats.tx_window_errors++;
468 if (status & TX_16_COL) lp->stats.tx_aborted_errors++;
469 break;
470 case ISQ_BUFFER_EVENT:
471 if (status & READY_FOR_TX) {
472 /* we tried to transmit a packet earlier,
473 but inexplicably ran out of buffers.
474 That shouldn't happen since we only ever
475 load one packet. Shrug. Do the right
476 thing anyway. */
477 dev->tbusy = 0;
478 mark_bh(NET_BH); /* Inform upper layers. */
479 }
480 if (status & TX_UNDERRUN) {
481 if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
482 lp->send_underrun++;
483 if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
484 else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
485 }
486 break;
487 case ISQ_RX_MISS_EVENT:
488 lp->stats.rx_missed_errors += (status >>6);
489 break;
490 case ISQ_TX_COL_EVENT:
491 lp->stats.collisions += (status >>6);
492 break;
493 }
494 }
495 dev->interrupt = 0;
496 return;
497 }
498
499 /* We have a good packet(s), get it/them out of the buffers. */
500 static void
501 net_rx(struct net_device *dev)
502 {
503 struct net_local *lp = (struct net_local *)dev->priv;
504 struct sk_buff *skb;
505 int status, length;
506
507 status = readreg(dev, PP_RxStatus);
508 if ((status & RX_OK) == 0) {
509 lp->stats.rx_errors++;
510 if (status & RX_RUNT) lp->stats.rx_length_errors++;
511 if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++;
512 if (status & RX_CRC_ERROR) if (!(status & (RX_EXTRA_DATA|RX_RUNT)))
513 /* per str 172 */
514 lp->stats.rx_crc_errors++;
515 if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++;
516 return;
517 }
518
519 length = readreg(dev, PP_RxLength);
520 /* Malloc up new buffer. */
521 skb = alloc_skb(length, GFP_ATOMIC);
522 if (skb == NULL) {
523 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
524 lp->stats.rx_dropped++;
525 return;
526 }
527 skb->len = length;
528 skb->dev = dev;
529
530 memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
531
532 if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
533 dev->name, length,
534 (skb->data[ETH_ALEN+ETH_ALEN] << 8)
535 | skb->data[ETH_ALEN+ETH_ALEN+1]);
536
537 skb->protocol=eth_type_trans(skb,dev);
538 netif_rx(skb);
539 dev->last_rx = jiffies;
540 lp->stats.rx_packets++;
541 lp->stats.rx_bytes += length;
542 }
543
544 /* The inverse routine to net_open(). */
545 static int
546 net_close(struct net_device *dev)
547 {
548
549 writereg(dev, PP_RxCFG, 0);
550 writereg(dev, PP_TxCFG, 0);
551 writereg(dev, PP_BufCFG, 0);
552 writereg(dev, PP_BusCTL, 0);
553
554 netif_stop_queue(dev);
555
556 free_irq(dev->irq, dev);
557
558 /* Update the statistics here. */
559
560 return 0;
561
562 }
563
564 /* Get the current statistics. This may be called with the card open or
565 closed. */
566 static struct net_device_stats *
567 net_get_stats(struct net_device *dev)
568 {
569 struct net_local *lp = (struct net_local *)dev->priv;
570 unsigned long flags;
571
572 save_flags(flags);
573 cli();
574 /* Update the statistics from the device registers. */
575 lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
576 lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
577 restore_flags(flags);
578
579 return &lp->stats;
580 }
581
582 static void set_multicast_list(struct net_device *dev)
583 {
584 struct net_local *lp = (struct net_local *)dev->priv;
585
586 if(dev->flags&IFF_PROMISC)
587 {
588 lp->rx_mode = RX_ALL_ACCEPT;
589 }
590 else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
591 {
592 /* The multicast-accept list is initialized to accept-all, and we
593 rely on higher-level filtering for now. */
594 lp->rx_mode = RX_MULTCAST_ACCEPT;
595 }
596 else
597 lp->rx_mode = 0;
598
599 writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
600
601 /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
602 writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
603 (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
604 }
605
606
607 static int set_mac_address(struct net_device *dev, void *addr)
608 {
609 int i;
610 if (dev->start)
611 return -EBUSY;
612 printk("%s: Setting MAC address to ", dev->name);
613 for (i = 0; i < 6; i++)
614 printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
615 printk(".\n");
616 /* set the Ethernet address */
617 for (i=0; i < ETH_ALEN/2; i++)
618 writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
619
620 return 0;
621 }
622
623 #ifdef MODULE
624
625 static struct net_device dev_cs89x0;
626 static int debug;
627
628 MODULE_PARM(debug, "i");
629 MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)");
630
631 EXPORT_NO_SYMBOLS;
632
633 int
634 init_module(void)
635 {
636 net_debug = debug;
637 dev_cs89x0.init = mac89x0_probe;
638 dev_cs89x0.priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
639 if (!dev_cs89x0.priv)
640 return -ENOMEM;
641 memset(dev_cs89x0.priv, 0, sizeof(struct net_local));
642
643 if (register_netdev(&dev_cs89x0) != 0) {
644 printk(KERN_WARNING "mac89x0.c: No card found\n");
645 kfree(dev_cs89x0.priv);
646 return -ENXIO;
647 }
648 return 0;
649 }
650
651 void
652 cleanup_module(void)
653 {
654
655 #endif
656 #ifdef MODULE
657 writew(0, dev_cs89x0.base_addr + ADD_PORT);
658 #endif
659 #ifdef MODULE
660
661 if (dev_cs89x0.priv != NULL) {
662 /* Free up the private structure, or leak memory :-) */
663 unregister_netdev(&dev_cs89x0);
664 kfree(dev_cs89x0.priv);
665 dev_cs89x0.priv = NULL; /* gets re-allocated by cs89x0_probe1 */
666 }
667 }
668 #endif /* MODULE */
669
670 /*
671 * Local variables:
672 * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o mac89x0.o mac89x0.c"
673 * version-control: t
674 * kept-new-versions: 5
675 * c-indent-level: 8
676 * tab-width: 8
677 * End:
678 *
679 */
680