OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [fmv18x.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184.
2
 
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
9
 
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.
21
 
22
        This software may be used and distributed according to the terms
23
        of the GNU Public License, incorporated herein by reference.
24
 
25
        This is a device driver for the Fujitsu FMV-181/182/183/184, which
26
        is a straight-forward Fujitsu MB86965 implementation.
27
 
28
  Sources:
29
    at1700.c
30
    The Fujitsu MB86965 datasheet.
31
    The Fujitsu FMV-181/182 user's guide
32
*/
33
 
34
static const char *version =
35
        "fmv18x.c:v1.3.71e 03/04/96  Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
36
 
37
#include <linux/module.h>
38
 
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 <asm/system.h>
50
#include <asm/bitops.h>
51
#include <asm/io.h>
52
#include <asm/dma.h>
53
#include <linux/errno.h>
54
 
55
#include <linux/netdevice.h>
56
#include <linux/etherdevice.h>
57
#include <linux/skbuff.h>
58
#include <linux/delay.h>
59
 
60
static int fmv18x_probe_list[] =
61
{0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};
62
 
63
/* use 0 for production, 1 for verification, >2 for debug */
64
#ifndef NET_DEBUG
65
#define NET_DEBUG 1
66
#endif
67
static unsigned int net_debug = NET_DEBUG;
68
 
69
typedef unsigned char uchar;
70
 
71
/* Information that need to be kept for each board. */
72
struct net_local {
73
        struct enet_statistics stats;
74
        long open_time;                         /* Useless example local info. */
75
        uint tx_started:1;                      /* Number of packet on the Tx queue. */
76
        uchar tx_queue;                         /* Number of packet on the Tx queue. */
77
        ushort tx_queue_len;            /* Current length of the Tx queue. */
78
};
79
 
80
 
81
/* Offsets from the base address. */
82
#define STATUS                  0
83
#define TX_STATUS               0
84
#define RX_STATUS               1
85
#define TX_INTR                 2               /* Bit-mapped interrupt enable registers. */
86
#define RX_INTR                 3
87
#define TX_MODE                 4
88
#define RX_MODE                 5
89
#define CONFIG_0                6               /* Misc. configuration settings. */
90
#define CONFIG_1                7
91
/* Run-time register bank 2 definitions. */
92
#define DATAPORT                8               /* Word-wide DMA or programmed-I/O dataport. */
93
#define TX_START                10
94
#define COL16CNTL               11
95
#define MODE13                  13
96
/* Fujitsu FMV-18x Card Configuration */
97
#define FJ_STATUS0              0x10
98
#define FJ_STATUS1              0x11
99
#define FJ_CONFIG0              0x12
100
#define FJ_CONFIG1              0x13
101
#define FJ_MACADDR              0x14    /* 0x14 - 0x19 */
102
#define FJ_BUFCNTL              0x1A
103
#define FJ_BUFDATA              0x1C
104
#define FMV18X_IO_EXTENT        32
105
 
106
/* Index to functions, as function prototypes. */
107
 
108
extern int fmv18x_probe(struct device *dev);
109
 
110
static int fmv18x_probe1(struct device *dev, short ioaddr);
111
static int net_open(struct device *dev);
112
static int      net_send_packet(struct sk_buff *skb, struct device *dev);
113
static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
114
static void net_rx(struct device *dev);
115
static int net_close(struct device *dev);
116
static struct enet_statistics *net_get_stats(struct device *dev);
117
static void set_multicast_list(struct device *dev);
118
 
119
 
120
/* Check for a network adaptor of this type, and return '0' iff one exists.
121
   If dev->base_addr == 0, probe all likely locations.
122
   If dev->base_addr == 1, always return failure.
123
   If dev->base_addr == 2, allocate space for the device and return success
124
   (detachable devices only).
125
   */
126
#ifdef HAVE_DEVLIST
127
/* Support for a alternate probe manager, which will eliminate the
128
   boilerplate below. */
129
struct netdev_entry fmv18x_drv =
130
{"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
131
#else
132
int
133
fmv18x_probe(struct device *dev)
134
{
135
        int i;
136
        int base_addr = dev ? dev->base_addr : 0;
137
 
138
        if (base_addr > 0x1ff)          /* Check a single specified location. */
139
                return fmv18x_probe1(dev, base_addr);
140
        else if (base_addr != 0) /* Don't probe at all. */
141
                return ENXIO;
142
 
143
        for (i = 0; fmv18x_probe_list[i]; i++) {
144
                int ioaddr = fmv18x_probe_list[i];
145
                if (check_region(ioaddr, FMV18X_IO_EXTENT))
146
                        continue;
147
                if (fmv18x_probe1(dev, ioaddr) == 0)
148
                        return 0;
149
        }
150
 
151
        return ENODEV;
152
}
153
#endif
154
 
155
/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
156
   "signature", the default bit pattern after a reset.  This *doesn't* work --
157
   there is no way to reset the bus interface without a complete power-cycle!
158
 
159
   It turns out that ATI came to the same conclusion I did: the only thing
160
   that can be done is checking a few bits and then diving right into MAC
161
   address check. */
162
 
163
int fmv18x_probe1(struct device *dev, short ioaddr)
164
{
165
        char irqmap[4] = {3, 7, 10, 15};
166
        unsigned int i, irq;
167
 
168
        /* Resetting the chip doesn't reset the ISA interface, so don't bother.
169
           That means we have to be careful with the register values we probe for.
170
           */
171
 
172
        /* Check I/O address configuration and Fujitsu vendor code */
173
        if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr
174
        ||  inb(ioaddr+FJ_MACADDR  ) != 0x00
175
        ||  inb(ioaddr+FJ_MACADDR+1) != 0x00
176
        ||  inb(ioaddr+FJ_MACADDR+2) != 0x0e)
177
                return -ENODEV;
178
 
179
        irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
180
 
181
        /* Snarf the interrupt vector now. */
182
        if (request_irq(irq, &net_interrupt, 0, "fmv18x", NULL)) {
183
                printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
184
                                "IRQ %d.\n", ioaddr, irq);
185
                return EAGAIN;
186
        }
187
 
188
        /* Allocate a new 'dev' if needed. */
189
        if (dev == NULL)
190
                dev = init_etherdev(0, sizeof(struct net_local));
191
 
192
        /* Grab the region so that we can find another board if the IRQ request
193
           fails. */
194
        request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x");
195
 
196
        printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
197
                   ioaddr, irq);
198
 
199
        dev->base_addr = ioaddr;
200
        dev->irq = irq;
201
        irq2dev_map[irq] = dev;
202
 
203
        for(i = 0; i < 6; i++) {
204
                unsigned char val = inb(ioaddr + FJ_MACADDR + i);
205
                printk("%02x", val);
206
                dev->dev_addr[i] = val;
207
        }
208
 
209
        /* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
210
           rather than 150 ohm shielded twisted pair compensation.
211
           0x0000 == auto-sense the interface
212
           0x0800 == use TP interface
213
           0x1800 == use coax interface
214
           */
215
        {
216
                const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};
217
                ushort setup_value = inb(ioaddr + FJ_STATUS0);
218
 
219
                switch( setup_value & 0x07 ){
220
                case 0x01 /* 10base5 */:
221
                case 0x02 /* 10base2 */: dev->if_port = 0x18; break;
222
                case 0x04 /* 10baseT */: dev->if_port = 0x08; break;
223
                default /* auto-sense*/: dev->if_port = 0x00; break;
224
                }
225
                printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
226
        }
227
 
228
        /* Initialize LAN Controller and LAN Card */
229
        outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
230
        outb(0x00, ioaddr + CONFIG_1);   /* Stand by mode */
231
        outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
232
        outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */
233
 
234
        /* wait for a while */
235
        udelay(200);
236
 
237
        /* Set the station address in bank zero. */
238
        outb(0x00, ioaddr + CONFIG_1);
239
        for (i = 0; i < 6; i++)
240
                outb(dev->dev_addr[i], ioaddr + 8 + i);
241
 
242
        /* Switch to bank 1 and set the multicast table to accept none. */
243
        outb(0x04, ioaddr + CONFIG_1);
244
        for (i = 0; i < 8; i++)
245
                outb(0x00, ioaddr + 8 + i);
246
 
247
        /* Switch to bank 2 and lock our I/O address. */
248
        outb(0x08, ioaddr + CONFIG_1);
249
        outb(dev->if_port, ioaddr + MODE13);
250
 
251
        if (net_debug)
252
                printk(version);
253
 
254
        /* Initialize the device structure. */
255
        dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
256
        if (dev->priv == NULL)
257
                return -ENOMEM;
258
        memset(dev->priv, 0, sizeof(struct net_local));
259
 
260
        dev->open               = net_open;
261
        dev->stop               = net_close;
262
        dev->hard_start_xmit = net_send_packet;
263
        dev->get_stats  = net_get_stats;
264
        dev->set_multicast_list = &set_multicast_list;
265
 
266
        /* Fill in the fields of 'dev' with ethernet-generic values. */
267
 
268
        ether_setup(dev);
269
        return 0;
270
}
271
 
272
 
273
static int net_open(struct device *dev)
274
{
275
        struct net_local *lp = (struct net_local *)dev->priv;
276
        int ioaddr = dev->base_addr;
277
 
278
        /* Set the configuration register 0 to 32K 100ns. byte-wide memory,
279
           16 bit bus access, and two 4K Tx, enable the Rx and Tx. */
280
        outb(0x5a, ioaddr + CONFIG_0);
281
 
282
        /* Powerup and switch to register bank 2 for the run-time registers. */
283
        outb(0xe8, ioaddr + CONFIG_1);
284
 
285
        lp->tx_started = 0;
286
        lp->tx_queue = 0;
287
        lp->tx_queue_len = 0;
288
 
289
        /* Clear Tx and Rx Status */
290
        outb(0xff, ioaddr + TX_STATUS);
291
        outb(0xff, ioaddr + RX_STATUS);
292
        lp->open_time = jiffies;
293
 
294
        dev->tbusy = 0;
295
        dev->interrupt = 0;
296
        dev->start = 1;
297
 
298
        /* Enable the IRQ of the LAN Card */
299
        outb(0x80, ioaddr + FJ_CONFIG1);
300
 
301
        /* Enable both Tx and Rx interrupts */
302
        outw(0x8182, ioaddr+TX_INTR);
303
 
304
        MOD_INC_USE_COUNT;
305
 
306
        return 0;
307
}
308
 
309
static int
310
net_send_packet(struct sk_buff *skb, struct device *dev)
311
{
312
        struct net_local *lp = (struct net_local *)dev->priv;
313
        int ioaddr = dev->base_addr;
314
 
315
        if (dev->tbusy) {
316
                /* If we get here, some higher level has decided we are broken.
317
                   There should really be a "kick me" function call instead. */
318
                int tickssofar = jiffies - dev->trans_start;
319
                if (tickssofar < 10)
320
                        return 1;
321
                printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
322
                           htons(inw(ioaddr + TX_STATUS)),
323
                           inb(ioaddr + TX_STATUS) & 0x80
324
                           ? "IRQ conflict" : "network cable problem");
325
                printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
326
                           dev->name, htons(inw(ioaddr + 0)),
327
                           htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
328
                           htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
329
                           htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
330
                           htons(inw(ioaddr +14)));
331
                printk("eth card: %04x %04x\n",
332
                        htons(inw(ioaddr+FJ_STATUS0)),
333
                        htons(inw(ioaddr+FJ_CONFIG0)));
334
                lp->stats.tx_errors++;
335
                /* ToDo: We should try to restart the adaptor... */
336
                cli();
337
 
338
                /* Initialize LAN Controller and LAN Card */
339
                outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
340
                outb(0x00, ioaddr + CONFIG_1);   /* Stand by mode */
341
                outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
342
                outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
343
                net_open(dev);
344
 
345
                sti();
346
        }
347
 
348
        /* If some higher layer thinks we've missed an tx-done interrupt
349
           we are passed NULL. Caution: dev_tint() handles the cli()/sti()
350
           itself. */
351
        if (skb == NULL) {
352
                dev_tint(dev);
353
                return 0;
354
        }
355
 
356
        /* Block a timer-based transmit from overlapping.  This could better be
357
           done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
358
        if (set_bit(0, (void*)&dev->tbusy) != 0)
359
                printk("%s: Transmitter access conflict.\n", dev->name);
360
        else {
361
                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
362
                unsigned char *buf = skb->data;
363
 
364
                if (length > ETH_FRAME_LEN) {
365
                        if (net_debug)
366
                                printk("%s: Attempting to send a large packet (%d bytes).\n",
367
                                        dev->name, length);
368
                        return 1;
369
                }
370
 
371
                if (net_debug > 4)
372
                        printk("%s: Transmitting a packet of length %lu.\n", dev->name,
373
                                   (unsigned long)skb->len);
374
 
375
                /* Disable both interrupts. */
376
                outw(0x0000, ioaddr + TX_INTR);
377
 
378
                outw(length, ioaddr + DATAPORT);
379
                outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
380
 
381
                lp->tx_queue++;
382
                lp->tx_queue_len += length + 2;
383
 
384
                if (lp->tx_started == 0) {
385
                        /* If the Tx is idle, always trigger a transmit. */
386
                        outb(0x80 | lp->tx_queue, ioaddr + TX_START);
387
                        lp->tx_queue = 0;
388
                        lp->tx_queue_len = 0;
389
                        dev->trans_start = jiffies;
390
                        lp->tx_started = 1;
391
                        dev->tbusy = 0;
392
                } else if (lp->tx_queue_len < 4096 - 1502)
393
                        /* Yes, there is room for one more packet. */
394
                        dev->tbusy = 0;
395
 
396
                /* Re-enable interrupts */
397
                outw(0x8182, ioaddr + TX_INTR);
398
        }
399
        dev_kfree_skb (skb, FREE_WRITE);
400
 
401
        return 0;
402
}
403
 
404
/* The typical workload of the driver:
405
   Handle the network interface interrupts. */
406
static void
407
net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
408
{
409
        struct device *dev = (struct device *)(irq2dev_map[irq]);
410
        struct net_local *lp;
411
        int ioaddr, status;
412
 
413
        if (dev == NULL) {
414
                printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq);
415
                return;
416
        }
417
        dev->interrupt = 1;
418
 
419
        ioaddr = dev->base_addr;
420
        lp = (struct net_local *)dev->priv;
421
 
422
        /* Avoid multiple interrupts. */
423
        outw(0x0000, ioaddr + TX_INTR);
424
 
425
        status = inw(ioaddr + TX_STATUS);
426
        outw(status, ioaddr + TX_STATUS);
427
 
428
        if (net_debug > 4)
429
                printk("%s: Interrupt with status %04x.\n", dev->name, status);
430
        if (status & 0xff00
431
                ||  (inb(ioaddr + RX_MODE) & 0x40) == 0) {                       /* Got a packet(s). */
432
                net_rx(dev);
433
        }
434
        if (status & 0x00ff) {
435
                if (status & 0x80) {
436
                        lp->stats.tx_packets++;
437
                        if (lp->tx_queue) {
438
                                outb(0x80 | lp->tx_queue, ioaddr + TX_START);
439
                                lp->tx_queue = 0;
440
                                lp->tx_queue_len = 0;
441
                                dev->trans_start = jiffies;
442
                                dev->tbusy = 0;
443
                                mark_bh(NET_BH);        /* Inform upper layers. */
444
                        } else {
445
                                lp->tx_started = 0;
446
                                dev->tbusy = 0;
447
                                mark_bh(NET_BH);        /* Inform upper layers. */
448
                        }
449
                }
450
                if (status & 0x02 ) {
451
                        if (net_debug > 4)
452
                                printk("%s: 16 Collision occur during Txing.\n", dev->name);
453
                        /* Retry to send the packet */
454
                        outb(0x02, ioaddr + COL16CNTL);
455
                }
456
        }
457
 
458
        dev->interrupt = 0;
459
        outw(0x8182, ioaddr + TX_INTR);
460
        return;
461
}
462
 
463
/* We have a good packet(s), get it/them out of the buffers. */
464
static void
465
net_rx(struct device *dev)
466
{
467
        struct net_local *lp = (struct net_local *)dev->priv;
468
        int ioaddr = dev->base_addr;
469
        int boguscount = 10;    /* 5 -> 10: by agy 19940922 */
470
 
471
        while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
472
                /* Clear PKT_RDY bit: by agy 19940922 */
473
                /* outb(0x80, ioaddr + RX_STATUS); */
474
                ushort status = inw(ioaddr + DATAPORT);
475
 
476
                if (net_debug > 4)
477
                        printk("%s: Rxing packet mode %02x status %04x.\n",
478
                                   dev->name, inb(ioaddr + RX_MODE), status);
479
#ifndef final_version
480
                if (status == 0) {
481
                        outb(0x05, ioaddr + 14);
482
                        break;
483
                }
484
#endif
485
 
486
                if ((status & 0xF0) != 0x20) {  /* There was an error. */
487
                        lp->stats.rx_errors++;
488
                        if (status & 0x08) lp->stats.rx_length_errors++;
489
                        if (status & 0x04) lp->stats.rx_frame_errors++;
490
                        if (status & 0x02) lp->stats.rx_crc_errors++;
491
                        if (status & 0x01) lp->stats.rx_over_errors++;
492
                } else {
493
                        ushort pkt_len = inw(ioaddr + DATAPORT);
494
                        /* Malloc up new buffer. */
495
                        struct sk_buff *skb;
496
 
497
                        if (pkt_len > 1550) {
498
                                printk("%s: The FMV-18x claimed a very large packet, size %d.\n",
499
                                           dev->name, pkt_len);
500
                                outb(0x05, ioaddr + 14);
501
                                lp->stats.rx_errors++;
502
                                break;
503
                        }
504
                        skb = dev_alloc_skb(pkt_len+3);
505
                        if (skb == NULL) {
506
                                printk("%s: Memory squeeze, dropping packet (len %d).\n",
507
                                           dev->name, pkt_len);
508
                                outb(0x05, ioaddr + 14);
509
                                lp->stats.rx_dropped++;
510
                                break;
511
                        }
512
                        skb->dev = dev;
513
                        skb_reserve(skb,2);
514
 
515
                        insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
516
 
517
                        if (net_debug > 5) {
518
                                int i;
519
                                printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
520
                                for (i = 0; i < 14; i++)
521
                                        printk(" %02x", skb->data[i]);
522
                                printk(".\n");
523
                        }
524
 
525
                        skb->protocol=eth_type_trans(skb, dev);
526
                        netif_rx(skb);
527
                        lp->stats.rx_packets++;
528
                }
529
                if (--boguscount <= 0)
530
                        break;
531
        }
532
 
533
        /* If any worth-while packets have been received, dev_rint()
534
           has done a mark_bh(NET_BH) for us and will work on them
535
           when we get to the bottom-half routine. */
536
        {
537
                int i;
538
                for (i = 0; i < 20; i++) {
539
                        if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
540
                                break;
541
                        (void)inw(ioaddr + DATAPORT);                           /* dummy status read */
542
                        outb(0x05, ioaddr + 14);
543
                }
544
 
545
                if (net_debug > 5 && i > 0)
546
                        printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
547
                                   dev->name, inb(ioaddr + RX_MODE), i);
548
        }
549
 
550
        return;
551
}
552
 
553
/* The inverse routine to net_open(). */
554
static int net_close(struct device *dev)
555
{
556
        int ioaddr = dev->base_addr;
557
 
558
        ((struct net_local *)dev->priv)->open_time = 0;
559
 
560
        dev->tbusy = 1;
561
        dev->start = 0;
562
 
563
        /* Set configuration register 0 to disable Tx and Rx. */
564
        outb(0xda, ioaddr + CONFIG_0);
565
 
566
        /* Update the statistics -- ToDo. */
567
 
568
        /* Power-down the chip.  Green, green, green! */
569
        outb(0x00, ioaddr + CONFIG_1);
570
 
571
        MOD_DEC_USE_COUNT;
572
 
573
        /* Set the ethernet adaptor disable IRQ */
574
        outb(0x00, ioaddr + FJ_CONFIG1);
575
 
576
        return 0;
577
}
578
 
579
/* Get the current statistics.  This may be called with the card open or
580
   closed. */
581
static struct enet_statistics *
582
net_get_stats(struct device *dev)
583
{
584
        struct net_local *lp = (struct net_local *)dev->priv;
585
 
586
        cli();
587
        /* ToDo: Update the statistics from the device registers. */
588
        sti();
589
 
590
        return &lp->stats;
591
}
592
 
593
/* Set or clear the multicast filter for this adaptor.
594
   num_addrs == -1      Promiscuous mode, receive all packets
595
   num_addrs == 0       Normal mode, clear multicast list
596
   num_addrs > 0        Multicast mode, receive normal and MC packets, and do
597
                        best-effort filtering.
598
 */
599
static void
600
set_multicast_list(struct device *dev)
601
{
602
        short ioaddr = dev->base_addr;
603
        if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
604
        {
605
                /*
606
                 *      We must make the kernel realise we had to move
607
                 *      into promisc mode or we start all out war on
608
                 *      the cable. - AC
609
                 */
610
                dev->flags|=IFF_PROMISC;
611
 
612
                outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
613
        }
614
        else
615
                outb(2, ioaddr + RX_MODE);      /* Disable promiscuous, use normal mode */
616
}
617
 
618
#ifdef MODULE
619
static char devicename[9] = { 0, };
620
static struct device dev_fmv18x = {
621
        devicename, /* device name is inserted by linux/drivers/net/net_init.c */
622
        0, 0, 0, 0,
623
        0, 0,
624
        0, 0, 0, NULL, fmv18x_probe };
625
 
626
static int io = 0x220;
627
static int irq = 0;
628
 
629
int init_module(void)
630
{
631
        if (io == 0)
632
                printk("fmv18x: You should not use auto-probing with insmod!\n");
633
        dev_fmv18x.base_addr = io;
634
        dev_fmv18x.irq       = irq;
635
        if (register_netdev(&dev_fmv18x) != 0) {
636
                printk("fmv18x: register_netdev() returned non-zero.\n");
637
                return -EIO;
638
        }
639
        return 0;
640
}
641
 
642
void
643
cleanup_module(void)
644
{
645
        unregister_netdev(&dev_fmv18x);
646
        kfree(dev_fmv18x.priv);
647
        dev_fmv18x.priv = NULL;
648
 
649
        /* If we don't do this, we can't re-insmod it later. */
650
        free_irq(dev_fmv18x.irq, NULL);
651
        irq2dev_map[dev_fmv18x.irq] = NULL;
652
        release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT);
653
}
654
#endif /* MODULE */
655
 
656
/*
657
 * Local variables:
658
 *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c"
659
 *  version-control: t
660
 *  kept-new-versions: 5
661
 *  tab-width: 4
662
 *  c-indent-level: 4
663
 * End:
664
 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.