2.2.0-final
[davej-history.git] / drivers / net / fmv18x.c
blob749e1f1239c2a858eca2302cb68c1ed7d9c07a4d
1 /* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184.
3 Original: at1700.c (1993-94 by Donald Becker).
4 Copyright 1993 United States Government as represented by the
5 Director, National Security Agency.
6 The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
7 Center of Excellence in Space Data and Information Sciences
8 Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
10 Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)
11 Copyright 1994 Fujitsu Laboratories Ltd.
12 Special thanks to:
13 Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp)
14 for testing this driver.
15 H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp)
16 for suggestion of some program modification.
17 Masahiro SEKIGUCHI <seki@sysrap.cs.fujitsu.co.jp>
18 for suggestion of some program modification.
19 Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp)
20 for testing this driver.
22 This software may be used and distributed according to the terms
23 of the GNU Public License, incorporated herein by reference.
25 This is a device driver for the Fujitsu FMV-181/182/183/184, which
26 is a straight-forward Fujitsu MB86965 implementation.
28 Sources:
29 at1700.c
30 The Fujitsu MB86965 datasheet.
31 The Fujitsu FMV-181/182 user's guide
34 static const char *version =
35 "fmv18x.c:v2.2.0 09/24/98 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
37 #include <linux/module.h>
39 #include <linux/kernel.h>
40 #include <linux/sched.h>
41 #include <linux/types.h>
42 #include <linux/fcntl.h>
43 #include <linux/interrupt.h>
44 #include <linux/ptrace.h>
45 #include <linux/ioport.h>
46 #include <linux/in.h>
47 #include <linux/malloc.h>
48 #include <linux/string.h>
49 #include <linux/init.h>
50 #include <asm/system.h>
51 #include <asm/bitops.h>
52 #include <asm/io.h>
53 #include <asm/dma.h>
54 #include <linux/errno.h>
56 #include <linux/netdevice.h>
57 #include <linux/etherdevice.h>
58 #include <linux/skbuff.h>
59 #include <linux/delay.h>
61 static int fmv18x_probe_list[] __initdata =
62 {0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};
64 /* use 0 for production, 1 for verification, >2 for debug */
65 #ifndef NET_DEBUG
66 #define NET_DEBUG 1
67 #endif
68 static unsigned int net_debug = NET_DEBUG;
70 typedef unsigned char uchar;
72 /* Information that need to be kept for each board. */
73 struct net_local {
74 struct net_device_stats stats;
75 long open_time; /* Useless example local info. */
76 uint tx_started:1; /* Number of packet on the Tx queue. */
77 uint tx_queue_ready:1; /* Tx queue is ready to be sent. */
78 uint rx_started:1; /* Packets are Rxing. */
79 uchar tx_queue; /* Number of packet on the Tx queue. */
80 ushort tx_queue_len; /* Current length of the Tx queue. */
84 /* Offsets from the base address. */
85 #define STATUS 0
86 #define TX_STATUS 0
87 #define RX_STATUS 1
88 #define TX_INTR 2 /* Bit-mapped interrupt enable registers. */
89 #define RX_INTR 3
90 #define TX_MODE 4
91 #define RX_MODE 5
92 #define CONFIG_0 6 /* Misc. configuration settings. */
93 #define CONFIG_1 7
94 /* Run-time register bank 2 definitions. */
95 #define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */
96 #define TX_START 10
97 #define COL16CNTL 11 /* Controll Reg for 16 collisions */
98 #define MODE13 13
99 /* Fujitsu FMV-18x Card Configuration */
100 #define FJ_STATUS0 0x10
101 #define FJ_STATUS1 0x11
102 #define FJ_CONFIG0 0x12
103 #define FJ_CONFIG1 0x13
104 #define FJ_MACADDR 0x14 /* 0x14 - 0x19 */
105 #define FJ_BUFCNTL 0x1A
106 #define FJ_BUFDATA 0x1C
107 #define FMV18X_IO_EXTENT 32
109 /* Index to functions, as function prototypes. */
111 extern int fmv18x_probe(struct device *dev);
113 static int fmv18x_probe1(struct device *dev, short ioaddr);
114 static int net_open(struct device *dev);
115 static int net_send_packet(struct sk_buff *skb, struct device *dev);
116 static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
117 static void net_rx(struct device *dev);
118 static int net_close(struct device *dev);
119 static struct net_device_stats *net_get_stats(struct device *dev);
120 static void set_multicast_list(struct device *dev);
123 /* Check for a network adaptor of this type, and return '0' iff one exists.
124 If dev->base_addr == 0, probe all likely locations.
125 If dev->base_addr == 1, always return failure.
126 If dev->base_addr == 2, allocate space for the device and return success
127 (detachable devices only).
129 #ifdef HAVE_DEVLIST
130 /* Support for an alternate probe manager, which will eliminate the
131 boilerplate below. */
132 struct netdev_entry fmv18x_drv =
133 {"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
134 #else
135 __initfunc(int
136 fmv18x_probe(struct device *dev))
138 int i;
139 int base_addr = dev ? dev->base_addr : 0;
141 if (base_addr > 0x1ff) /* Check a single specified location. */
142 return fmv18x_probe1(dev, base_addr);
143 else if (base_addr != 0) /* Don't probe at all. */
144 return ENXIO;
146 for (i = 0; fmv18x_probe_list[i]; i++) {
147 int ioaddr = fmv18x_probe_list[i];
148 if (check_region(ioaddr, FMV18X_IO_EXTENT))
149 continue;
150 if (fmv18x_probe1(dev, ioaddr) == 0)
151 return 0;
154 return ENODEV;
156 #endif
158 /* The Fujitsu datasheet suggests that the NIC be probed for by checking its
159 "signature", the default bit pattern after a reset. This *doesn't* work --
160 there is no way to reset the bus interface without a complete power-cycle!
162 It turns out that ATI came to the same conclusion I did: the only thing
163 that can be done is checking a few bits and then diving right into MAC
164 address check. */
166 __initfunc(int fmv18x_probe1(struct device *dev, short ioaddr))
168 char irqmap[4] = {3, 7, 10, 15};
169 char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
170 unsigned int i, irq;
172 /* Resetting the chip doesn't reset the ISA interface, so don't bother.
173 That means we have to be careful with the register values we probe for.
176 /* Check I/O address configuration and Fujitsu vendor code */
177 if (inb(ioaddr+FJ_MACADDR ) != 0x00
178 || inb(ioaddr+FJ_MACADDR+1) != 0x00
179 || inb(ioaddr+FJ_MACADDR+2) != 0x0e)
180 return -ENODEV;
182 /* Check PnP mode for FMV-183/184/183A/184A. */
183 /* This PnP routine is very poor. IO and IRQ should be known. */
184 if (inb(ioaddr + FJ_STATUS1) & 0x20) {
185 irq = dev->irq;
186 for (i = 0; i < 8; i++) {
187 if (irq == irqmap_pnp[i])
188 break;
190 if (i == 8)
191 return -ENODEV;
192 } else {
193 if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr)
194 return -ENODEV;
195 irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
198 /* Snarf the interrupt vector now. */
199 if (request_irq(irq, &net_interrupt, 0, "fmv18x", dev)) {
200 printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
201 "IRQ %d.\n", ioaddr, irq);
202 return EAGAIN;
205 /* Allocate a new 'dev' if needed. */
206 if (dev == NULL)
207 dev = init_etherdev(0, sizeof(struct net_local));
209 /* Grab the region so that we can find another board if the IRQ request
210 fails. */
211 request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x");
213 printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
214 ioaddr, irq);
216 dev->base_addr = ioaddr;
217 dev->irq = irq;
219 for(i = 0; i < 6; i++) {
220 unsigned char val = inb(ioaddr + FJ_MACADDR + i);
221 printk("%02x", val);
222 dev->dev_addr[i] = val;
225 /* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
226 rather than 150 ohm shielded twisted pair compensation.
227 0x0000 == auto-sense the interface
228 0x0800 == use TP interface
229 0x1800 == use coax interface
232 const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};
233 ushort setup_value = inb(ioaddr + FJ_STATUS0);
235 switch( setup_value & 0x07 ){
236 case 0x01 /* 10base5 */:
237 case 0x02 /* 10base2 */: dev->if_port = 0x18; break;
238 case 0x04 /* 10baseT */: dev->if_port = 0x08; break;
239 default /* auto-sense*/: dev->if_port = 0x00; break;
241 printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
244 /* Initialize LAN Controller and LAN Card */
245 outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */
246 outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */
247 outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
248 outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */
250 /* wait for a while */
251 udelay(200);
253 /* Set the station address in bank zero. */
254 outb(0x00, ioaddr + CONFIG_1);
255 for (i = 0; i < 6; i++)
256 outb(dev->dev_addr[i], ioaddr + 8 + i);
258 /* Switch to bank 1 and set the multicast table to accept none. */
259 outb(0x04, ioaddr + CONFIG_1);
260 for (i = 0; i < 8; i++)
261 outb(0x00, ioaddr + 8 + i);
263 /* Switch to bank 2 and lock our I/O address. */
264 outb(0x08, ioaddr + CONFIG_1);
265 outb(dev->if_port, ioaddr + MODE13);
266 outb(0x00, ioaddr + COL16CNTL);
268 if (net_debug)
269 printk(version);
271 /* Initialize the device structure. */
272 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
273 if (dev->priv == NULL)
274 return -ENOMEM;
275 memset(dev->priv, 0, sizeof(struct net_local));
277 dev->open = net_open;
278 dev->stop = net_close;
279 dev->hard_start_xmit = net_send_packet;
280 dev->get_stats = net_get_stats;
281 dev->set_multicast_list = &set_multicast_list;
283 /* Fill in the fields of 'dev' with ethernet-generic values. */
285 ether_setup(dev);
286 return 0;
290 static int net_open(struct device *dev)
292 struct net_local *lp = (struct net_local *)dev->priv;
293 int ioaddr = dev->base_addr;
295 /* Set the configuration register 0 to 32K 100ns. byte-wide memory,
296 16 bit bus access, and two 4K Tx, enable the Rx and Tx. */
297 outb(0x5a, ioaddr + CONFIG_0);
299 /* Powerup and switch to register bank 2 for the run-time registers. */
300 outb(0xe8, ioaddr + CONFIG_1);
302 lp->tx_started = 0;
303 lp->tx_queue_ready = 1;
304 lp->rx_started = 0;
305 lp->tx_queue = 0;
306 lp->tx_queue_len = 0;
308 /* Clear Tx and Rx Status */
309 outb(0xff, ioaddr + TX_STATUS);
310 outb(0xff, ioaddr + RX_STATUS);
311 lp->open_time = jiffies;
313 dev->tbusy = 0;
314 dev->interrupt = 0;
315 dev->start = 1;
317 /* Enable the IRQ of the LAN Card */
318 outb(0x80, ioaddr + FJ_CONFIG1);
320 /* Enable both Tx and Rx interrupts */
321 outw(0x8182, ioaddr+TX_INTR);
323 MOD_INC_USE_COUNT;
325 return 0;
328 static int
329 net_send_packet(struct sk_buff *skb, struct device *dev)
331 struct net_local *lp = (struct net_local *)dev->priv;
332 int ioaddr = dev->base_addr;
334 if (dev->tbusy) {
335 /* If we get here, some higher level has decided we are broken.
336 There should really be a "kick me" function call instead. */
337 int tickssofar = jiffies - dev->trans_start;
338 if (tickssofar < 10)
339 return 1;
340 printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
341 htons(inw(ioaddr + TX_STATUS)),
342 inb(ioaddr + TX_STATUS) & 0x80
343 ? "IRQ conflict" : "network cable problem");
344 printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
345 dev->name, htons(inw(ioaddr + 0)),
346 htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
347 htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
348 htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
349 htons(inw(ioaddr +14)));
350 printk("eth card: %04x %04x\n",
351 htons(inw(ioaddr+FJ_STATUS0)),
352 htons(inw(ioaddr+FJ_CONFIG0)));
353 lp->stats.tx_errors++;
354 /* ToDo: We should try to restart the adaptor... */
355 cli();
357 /* Initialize LAN Controller and LAN Card */
358 outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */
359 outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */
360 outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
361 outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
362 net_open(dev);
364 sti();
367 /* Block a timer-based transmit from overlapping. This could better be
368 done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
369 if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
370 printk("%s: Transmitter access conflict.\n", dev->name);
371 else {
372 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
373 unsigned char *buf = skb->data;
375 if (length > ETH_FRAME_LEN) {
376 if (net_debug)
377 printk("%s: Attempting to send a large packet (%d bytes).\n",
378 dev->name, length);
379 return 1;
382 if (net_debug > 4)
383 printk("%s: Transmitting a packet of length %lu.\n", dev->name,
384 (unsigned long)skb->len);
386 /* We may not start transmitting unless we finish transferring
387 a packet into the Tx queue. During executing the following
388 codes we possibly catch a Tx interrupt. Thus we flag off
389 tx_queue_ready, so that we prevent the interrupt routine
390 (net_interrupt) to start transmitting. */
391 lp->tx_queue_ready = 0;
393 outw(length, ioaddr + DATAPORT);
394 outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
396 lp->tx_queue++;
397 lp->tx_queue_len += length + 2;
399 lp->tx_queue_ready = 1;
401 if (lp->tx_started == 0) {
402 /* If the Tx is idle, always trigger a transmit. */
403 outb(0x80 | lp->tx_queue, ioaddr + TX_START);
404 lp->tx_queue = 0;
405 lp->tx_queue_len = 0;
406 dev->trans_start = jiffies;
407 lp->tx_started = 1;
408 dev->tbusy = 0;
409 } else if (lp->tx_queue_len < 4096 - 1502)
410 /* Yes, there is room for one more packet. */
411 dev->tbusy = 0;
413 dev_kfree_skb (skb);
415 return 0;
418 /* The typical workload of the driver:
419 Handle the network interface interrupts. */
420 static void
421 net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
423 struct device *dev = dev_id;
424 struct net_local *lp;
425 int ioaddr, status;
427 if (dev == NULL) {
428 printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq);
429 return;
431 dev->interrupt = 1;
433 ioaddr = dev->base_addr;
434 lp = (struct net_local *)dev->priv;
435 status = inw(ioaddr + TX_STATUS);
436 outw(status, ioaddr + TX_STATUS);
438 if (net_debug > 4)
439 printk("%s: Interrupt with status %04x.\n", dev->name, status);
440 if (lp->rx_started == 0 &&
441 (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
442 /* Got a packet(s).
443 We cannot execute net_rx more than once at the same time for
444 the same device. During executing net_rx, we possibly catch a
445 Tx interrupt. Thus we flag on rx_started, so that we prevent
446 the interrupt routine (net_interrupt) to dive into net_rx
447 again. */
448 lp->rx_started = 1;
449 outb(0x00, ioaddr + RX_INTR); /* Disable RX intr. */
450 net_rx(dev);
451 outb(0x81, ioaddr + RX_INTR); /* Enable RX intr. */
452 lp->rx_started = 0;
454 if (status & 0x00ff) {
455 if (status & 0x02) {
456 /* More than 16 collisions occurred */
457 if (net_debug > 4)
458 printk("%s: 16 Collision occur during Txing.\n", dev->name);
459 /* Cancel sending a packet. */
460 outb(0x03, ioaddr + COL16CNTL);
461 lp->stats.collisions++;
463 if (status & 0x82) {
464 lp->stats.tx_packets++;
465 if (lp->tx_queue && lp->tx_queue_ready) {
466 outb(0x80 | lp->tx_queue, ioaddr + TX_START);
467 lp->tx_queue = 0;
468 lp->tx_queue_len = 0;
469 dev->trans_start = jiffies;
470 dev->tbusy = 0;
471 mark_bh(NET_BH); /* Inform upper layers. */
472 } else {
473 lp->tx_started = 0;
474 dev->tbusy = 0;
475 mark_bh(NET_BH); /* Inform upper layers. */
480 dev->interrupt = 0;
481 return;
484 /* We have a good packet(s), get it/them out of the buffers. */
485 static void
486 net_rx(struct device *dev)
488 struct net_local *lp = (struct net_local *)dev->priv;
489 int ioaddr = dev->base_addr;
490 int boguscount = 5;
492 while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
493 /* Clear PKT_RDY bit: by agy 19940922 */
494 /* outb(0x80, ioaddr + RX_STATUS); */
495 ushort status = inw(ioaddr + DATAPORT);
497 if (net_debug > 4)
498 printk("%s: Rxing packet mode %02x status %04x.\n",
499 dev->name, inb(ioaddr + RX_MODE), status);
500 #ifndef final_version
501 if (status == 0) {
502 outb(0x05, ioaddr + 14);
503 break;
505 #endif
507 if ((status & 0xF0) != 0x20) { /* There was an error. */
508 lp->stats.rx_errors++;
509 if (status & 0x08) lp->stats.rx_length_errors++;
510 if (status & 0x04) lp->stats.rx_frame_errors++;
511 if (status & 0x02) lp->stats.rx_crc_errors++;
512 if (status & 0x01) lp->stats.rx_over_errors++;
513 } else {
514 ushort pkt_len = inw(ioaddr + DATAPORT);
515 /* Malloc up new buffer. */
516 struct sk_buff *skb;
518 if (pkt_len > 1550) {
519 printk("%s: The FMV-18x claimed a very large packet, size %d.\n",
520 dev->name, pkt_len);
521 outb(0x05, ioaddr + 14);
522 lp->stats.rx_errors++;
523 break;
525 skb = dev_alloc_skb(pkt_len+3);
526 if (skb == NULL) {
527 printk("%s: Memory squeeze, dropping packet (len %d).\n",
528 dev->name, pkt_len);
529 outb(0x05, ioaddr + 14);
530 lp->stats.rx_dropped++;
531 break;
533 skb->dev = dev;
534 skb_reserve(skb,2);
536 insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
538 if (net_debug > 5) {
539 int i;
540 printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
541 for (i = 0; i < 14; i++)
542 printk(" %02x", skb->data[i]);
543 printk(".\n");
546 skb->protocol=eth_type_trans(skb, dev);
547 netif_rx(skb);
548 lp->stats.rx_packets++;
550 if (--boguscount <= 0)
551 break;
554 /* If any worth-while packets have been received, dev_rint()
555 has done a mark_bh(NET_BH) for us and will work on them
556 when we get to the bottom-half routine. */
558 int i;
559 for (i = 0; i < 20; i++) {
560 if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
561 break;
562 (void)inw(ioaddr + DATAPORT); /* dummy status read */
563 outb(0x05, ioaddr + 14);
566 if (net_debug > 5 && i > 0)
567 printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
568 dev->name, inb(ioaddr + RX_MODE), i);
571 return;
574 /* The inverse routine to net_open(). */
575 static int net_close(struct device *dev)
577 int ioaddr = dev->base_addr;
579 ((struct net_local *)dev->priv)->open_time = 0;
581 dev->tbusy = 1;
582 dev->start = 0;
584 /* Set configuration register 0 to disable Tx and Rx. */
585 outb(0xda, ioaddr + CONFIG_0);
587 /* Update the statistics -- ToDo. */
589 /* Power-down the chip. Green, green, green! */
590 outb(0x00, ioaddr + CONFIG_1);
592 MOD_DEC_USE_COUNT;
594 /* Set the ethernet adaptor disable IRQ */
595 outb(0x00, ioaddr + FJ_CONFIG1);
597 return 0;
600 /* Get the current statistics. This may be called with the card open or
601 closed. */
602 static struct net_device_stats *net_get_stats(struct device *dev)
604 struct net_local *lp = (struct net_local *)dev->priv;
606 cli();
607 /* ToDo: Update the statistics from the device registers. */
608 sti();
610 return &lp->stats;
613 /* Set or clear the multicast filter for this adaptor.
614 num_addrs == -1 Promiscuous mode, receive all packets
615 num_addrs == 0 Normal mode, clear multicast list
616 num_addrs > 0 Multicast mode, receive normal and MC packets, and do
617 best-effort filtering.
620 static void set_multicast_list(struct device *dev)
622 short ioaddr = dev->base_addr;
623 if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
626 * We must make the kernel realise we had to move
627 * into promisc mode or we start all out war on
628 * the cable. - AC
630 dev->flags|=IFF_PROMISC;
632 outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */
634 else
635 outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */
638 #ifdef MODULE
639 static char devicename[9] = { 0, };
640 static struct device dev_fmv18x = {
641 devicename, /* device name is inserted by linux/drivers/net/net_init.c */
642 0, 0, 0, 0,
643 0, 0,
644 0, 0, 0, NULL, fmv18x_probe };
646 static int io = 0x220;
647 static int irq = 0;
649 MODULE_PARM(io, "i");
650 MODULE_PARM(irq, "i");
651 MODULE_PARM(net_debug, "i");
653 int init_module(void)
655 if (io == 0)
656 printk("fmv18x: You should not use auto-probing with insmod!\n");
657 dev_fmv18x.base_addr = io;
658 dev_fmv18x.irq = irq;
659 if (register_netdev(&dev_fmv18x) != 0) {
660 printk("fmv18x: register_netdev() returned non-zero.\n");
661 return -EIO;
663 return 0;
666 void
667 cleanup_module(void)
669 unregister_netdev(&dev_fmv18x);
670 kfree(dev_fmv18x.priv);
671 dev_fmv18x.priv = NULL;
673 /* If we don't do this, we can't re-insmod it later. */
674 free_irq(dev_fmv18x.irq, &dev_fmv18x);
675 release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT);
677 #endif /* MODULE */
680 * Local variables:
681 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c"
682 * version-control: t
683 * kept-new-versions: 5
684 * tab-width: 4
685 * c-indent-level: 4
686 * End: