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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [net/] [skeleton.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
/* skeleton.c: A network driver outline for linux.
2
 *
3
 *      Written 1993-94 by Donald Becker.
4
 *
5
 *      Copyright 1993 United States Government as represented by the
6
 *      Director, National Security Agency.
7
 *
8
 *      This software may be used and distributed according to the terms
9
 *      of the GNU Public License, incorporated herein by reference.
10
 *
11
 *      The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
12
 *      Center of Excellence in Space Data and Information Sciences
13
 *         Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
14
 *
15
 *      This file is an outline for writing a network device driver for the
16
 *      the Linux operating system.
17
 *
18
 *      To write (or understand) a driver, have a look at the "loopback.c" file to
19
 *      get a feel of what is going on, and then use the code below as a skeleton
20
 *      for the new driver.
21
 *
22
 */
23
 
24
static const char *version =
25
        "skeleton.c:v1.51 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
26
 
27
/*
28
 *  Sources:
29
 *      List your sources of programming information to document that
30
 *      the driver is your own creation, and give due credit to others
31
 *      that contributed to the work. Remember that GNU project code
32
 *      cannot use proprietary or trade secret information. Interface
33
 *      definitions are generally considered non-copyrightable to the
34
 *      extent that the same names and structures must be used to be
35
 *      compatible.
36
 *
37
 *      Finally, keep in mind that the Linux kernel is has an API, not
38
 *      ABI. Proprietary object-code-only distributions are not permitted
39
 *      under the GPL.
40
 */
41
 
42
#include <linux/module.h>
43
 
44
#include <linux/kernel.h>
45
#include <linux/sched.h>
46
#include <linux/types.h>
47
#include <linux/fcntl.h>
48
#include <linux/interrupt.h>
49
#include <linux/ptrace.h>
50
#include <linux/ioport.h>
51
#include <linux/in.h>
52
#include <linux/malloc.h>
53
#include <linux/string.h>
54
#include <asm/system.h>
55
#include <asm/bitops.h>
56
#include <asm/io.h>
57
#include <asm/dma.h>
58
#include <linux/errno.h>
59
 
60
#include <linux/netdevice.h>
61
#include <linux/etherdevice.h>
62
#include <linux/skbuff.h>
63
 
64
/*
65
 * The name of the card. Is used for messages and in the requests for
66
 * io regions, irqs and dma channels
67
 */
68
static const char* cardname = "netcard";
69
 
70
/* First, a few definitions that the brave might change. */
71
 
72
/* A zero-terminated list of I/O addresses to be probed. */
73
static unsigned int netcard_portlist[] =
74
   { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
75
 
76
/* use 0 for production, 1 for verification, >2 for debug */
77
#ifndef NET_DEBUG
78
#define NET_DEBUG 2
79
#endif
80
static unsigned int net_debug = NET_DEBUG;
81
 
82
/* The number of low I/O ports used by the ethercard. */
83
#define NETCARD_IO_EXTENT       32
84
 
85
/* Information that need to be kept for each board. */
86
struct net_local {
87
        struct enet_statistics stats;
88
        long open_time;                 /* Useless example local info. */
89
};
90
 
91
/* The station (ethernet) address prefix, used for IDing the board. */
92
#define SA_ADDR0 0x00
93
#define SA_ADDR1 0x42
94
#define SA_ADDR2 0x65
95
 
96
/* Index to functions, as function prototypes. */
97
 
98
extern int netcard_probe(struct device *dev);
99
 
100
static int netcard_probe1(struct device *dev, int ioaddr);
101
static int net_open(struct device *dev);
102
static int      net_send_packet(struct sk_buff *skb, struct device *dev);
103
static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
104
static void net_rx(struct device *dev);
105
static int net_close(struct device *dev);
106
static struct enet_statistics *net_get_stats(struct device *dev);
107
static void set_multicast_list(struct device *dev);
108
 
109
/* Example routines you must write ;->. */
110
#define tx_done(dev) 1
111
extern void     hardware_send_packet(short ioaddr, char *buf, int length);
112
extern void chipset_init(struct device *dev, int startp);
113
 
114
/*
115
 * Check for a network adaptor of this type, and return '0' iff one exists.
116
 * If dev->base_addr == 0, probe all likely locations.
117
 * If dev->base_addr == 1, always return failure.
118
 * If dev->base_addr == 2, allocate space for the device and return success
119
 * (detachable devices only).
120
 */
121
#ifdef HAVE_DEVLIST
122
/*
123
 * Support for a alternate probe manager,
124
 * which will eliminate the boilerplate below.
125
 */
126
struct netdev_entry netcard_drv =
127
{cardname, netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist};
128
#else
129
int
130
netcard_probe(struct device *dev)
131
{
132
        int i;
133
        int base_addr = dev ? dev->base_addr : 0;
134
 
135
        if (base_addr > 0x1ff)    /* Check a single specified location. */
136
                return netcard_probe1(dev, base_addr);
137
        else if (base_addr != 0)  /* Don't probe at all. */
138
                return -ENXIO;
139
 
140
        for (i = 0; netcard_portlist[i]; i++) {
141
                int ioaddr = netcard_portlist[i];
142
                if (check_region(ioaddr, NETCARD_IO_EXTENT))
143
                        continue;
144
                if (netcard_probe1(dev, ioaddr) == 0)
145
                        return 0;
146
        }
147
 
148
        return -ENODEV;
149
}
150
#endif
151
 
152
/*
153
 * This is the real probe routine. Linux has a history of friendly device
154
 * probes on the ISA bus. A good device probes avoids doing writes, and
155
 * verifies that the correct device exists and functions.
156
 */
157
static int netcard_probe1(struct device *dev, int ioaddr)
158
{
159
        static unsigned version_printed = 0;
160
        int i;
161
 
162
        /*
163
         * For ethernet adaptors the first three octets of the station address
164
         * contains the manufacturer's unique code. That might be a good probe
165
         * method. Ideally you would add additional checks.
166
         */
167
        if (inb(ioaddr + 0) != SA_ADDR0
168
                ||       inb(ioaddr + 1) != SA_ADDR1
169
                ||       inb(ioaddr + 2) != SA_ADDR2) {
170
                return -ENODEV;
171
        }
172
 
173
        /* Allocate a new 'dev' if needed. */
174
        if (dev == NULL) {
175
                /*
176
                 * Don't allocate the private data here, it is done later
177
                 * This makes it easier to free the memory when this driver
178
                 * is used as a module.
179
                 */
180
                dev = init_etherdev(0, 0);
181
                if (dev == NULL)
182
                        return -ENOMEM;
183
        }
184
 
185
        if (net_debug  &&  version_printed++ == 0)
186
                printk(KERN_DEBUG "%s", version);
187
 
188
        printk(KERN_INFO "%s: %s found at %#3x, ", dev->name, cardname, ioaddr);
189
 
190
        /* Fill in the 'dev' fields. */
191
        dev->base_addr = ioaddr;
192
 
193
        /* Retrieve and print the ethernet address. */
194
        for (i = 0; i < 6; i++)
195
                printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
196
 
197
#ifdef jumpered_interrupts
198
        /*
199
         * If this board has jumpered interrupts, allocate the interrupt
200
         * vector now. There is no point in waiting since no other device
201
         * can use the interrupt, and this marks the irq as busy. Jumpered
202
         * interrupts are typically not reported by the boards, and we must
203
         * used autoIRQ to find them.
204
         */
205
 
206
        if (dev->irq == -1)
207
                ;       /* Do nothing: a user-level program will set it. */
208
        else if (dev->irq < 2) {        /* "Auto-IRQ" */
209
                autoirq_setup(0);
210
                /* Trigger an interrupt here. */
211
 
212
                dev->irq = autoirq_report(0);
213
                if (net_debug >= 2)
214
                        printk(" autoirq is %d", dev->irq);
215
        } else if (dev->irq == 2)
216
                /*
217
                 * Fixup for users that don't know that IRQ 2 is really
218
                 * IRQ9, or don't know which one to set.
219
                 */
220
                dev->irq = 9;
221
 
222
        {
223
                int irqval = request_irq(dev->irq, &net_interrupt, 0, cardname, NULL);
224
                if (irqval) {
225
                        printk("%s: unable to get IRQ %d (irqval=%d).\n",
226
                                   dev->name, dev->irq, irqval);
227
                        return -EAGAIN;
228
                }
229
        }
230
#endif  /* jumpered interrupt */
231
#ifdef jumpered_dma
232
        /*
233
         * If we use a jumpered DMA channel, that should be probed for and
234
         * allocated here as well. See lance.c for an example.
235
         */
236
        if (dev->dma == 0) {
237
                if (request_dma(dev->dma, cardname)) {
238
                        printk("DMA %d allocation failed.\n", dev->dma);
239
                        return -EAGAIN;
240
                } else
241
                        printk(", assigned DMA %d.\n", dev->dma);
242
        } else {
243
                short dma_status, new_dma_status;
244
 
245
                /* Read the DMA channel status registers. */
246
                dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
247
                        (inb(DMA2_STAT_REG) & 0xf0);
248
                /* Trigger a DMA request, perhaps pause a bit. */
249
                outw(0x1234, ioaddr + 8);
250
                /* Re-read the DMA status registers. */
251
                new_dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
252
                        (inb(DMA2_STAT_REG) & 0xf0);
253
                /*
254
                 * Eliminate the old and floating requests,
255
                 * and DMA4 the cascade.
256
                 */
257
                new_dma_status ^= dma_status;
258
                new_dma_status &= ~0x10;
259
                for (i = 7; i > 0; i--)
260
                        if (test_bit(i, &new_dma_status)) {
261
                                dev->dma = i;
262
                                break;
263
                        }
264
                if (i <= 0) {
265
                        printk("DMA probe failed.\n");
266
                        return -EAGAIN;
267
                }
268
                if (request_dma(dev->dma, cardname)) {
269
                        printk("probed DMA %d allocation failed.\n", dev->dma);
270
                        return -EAGAIN;
271
                }
272
        }
273
#endif  /* jumpered DMA */
274
 
275
        /* Initialize the device structure. */
276
        if (dev->priv == NULL) {
277
                dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
278
                if (dev->priv == NULL)
279
                        return -ENOMEM;
280
        }
281
 
282
        memset(dev->priv, 0, sizeof(struct net_local));
283
 
284
        /* Grab the region so that no one else tries to probe our ioports. */
285
        request_region(ioaddr, NETCARD_IO_EXTENT, cardname);
286
 
287
        dev->open               = net_open;
288
        dev->stop               = net_close;
289
        dev->hard_start_xmit = net_send_packet;
290
        dev->get_stats  = net_get_stats;
291
        dev->set_multicast_list = &set_multicast_list;
292
 
293
        /* Fill in the fields of the device structure with ethernet values. */
294
        ether_setup(dev);
295
 
296
        return 0;
297
}
298
 
299
/*
300
 * Open/initialize the board. This is called (in the current kernel)
301
 * sometime after booting when the 'ifconfig' program is run.
302
 *
303
 * This routine should set everything up anew at each open, even
304
 * registers that "should" only need to be set once at boot, so that
305
 * there is non-reboot way to recover if something goes wrong.
306
 */
307
static int
308
net_open(struct device *dev)
309
{
310
        struct net_local *lp = (struct net_local *)dev->priv;
311
        int ioaddr = dev->base_addr;
312
        /*
313
         * This is used if the interrupt line can turned off (shared).
314
         * See 3c503.c for an example of selecting the IRQ at config-time.
315
         */
316
        if (request_irq(dev->irq, &net_interrupt, 0, cardname, NULL)) {
317
                return -EAGAIN;
318
        }
319
        /*
320
         * Always allocate the DMA channel after the IRQ,
321
         * and clean up on failure.
322
         */
323
        if (request_dma(dev->dma, cardname)) {
324
                free_irq(dev->irq, NULL);
325
                return -EAGAIN;
326
        }
327
        irq2dev_map[dev->irq] = dev;
328
 
329
        /* Reset the hardware here. Don't forget to set the station address. */
330
        /*chipset_init(dev, 1);*/
331
        outb(0x00, ioaddr);
332
        lp->open_time = jiffies;
333
 
334
        dev->tbusy = 0;
335
        dev->interrupt = 0;
336
        dev->start = 1;
337
 
338
        MOD_INC_USE_COUNT;
339
 
340
        return 0;
341
}
342
 
343
static int
344
net_send_packet(struct sk_buff *skb, struct device *dev)
345
{
346
        struct net_local *lp = (struct net_local *)dev->priv;
347
        int ioaddr = dev->base_addr;
348
 
349
        if (dev->tbusy) {
350
                /*
351
                 * If we get here, some higher level has decided we are broken.
352
                 * There should really be a "kick me" function call instead.
353
                 */
354
                int tickssofar = jiffies - dev->trans_start;
355
                if (tickssofar < 5)
356
                        return 1;
357
                printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
358
                           tx_done(dev) ? "IRQ conflict" : "network cable problem");
359
                /* Try to restart the adaptor. */
360
                chipset_init(dev, 1);
361
                dev->tbusy=0;
362
                dev->trans_start = jiffies;
363
        }
364
        /*
365
         * Block a timer-based transmit from overlapping. This could better be
366
         * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
367
         */
368
        if (set_bit(0, (void*)&dev->tbusy) != 0)
369
                printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
370
        else {
371
                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
372
                unsigned char *buf = skb->data;
373
 
374
                hardware_send_packet(ioaddr, buf, length);
375
                dev->trans_start = jiffies;
376
        }
377
        dev_kfree_skb (skb, FREE_WRITE);
378
 
379
        /* You might need to clean up and record Tx statistics here. */
380
        if (inw(ioaddr) == /*RU*/81)
381
                lp->stats.tx_aborted_errors++;
382
 
383
        return 0;
384
}
385
 
386
/*
387
 * The typical workload of the driver:
388
 *   Handle the network interface interrupts.
389
 */
390
static void
391
net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
392
{
393
        struct device *dev = (struct device *)(irq2dev_map[irq]);
394
        struct net_local *lp;
395
        int ioaddr, status, boguscount = 0;
396
 
397
        if (dev == NULL) {
398
                printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
399
                return;
400
        }
401
        dev->interrupt = 1;
402
 
403
        ioaddr = dev->base_addr;
404
        lp = (struct net_local *)dev->priv;
405
        status = inw(ioaddr + 0);
406
 
407
        do {
408
                if (status /*& RX_INTR*/) {
409
                        /* Got a packet(s). */
410
                        net_rx(dev);
411
                }
412
                if (status /*& TX_INTR*/) {
413
                        lp->stats.tx_packets++;
414
                        dev->tbusy = 0;
415
                        mark_bh(NET_BH);        /* Inform upper layers. */
416
                }
417
                if (status /*& COUNTERS_INTR*/) {
418
                        /* Increment the appropriate 'localstats' field. */
419
                        lp->stats.tx_window_errors++;
420
                }
421
        } while (++boguscount < 20) ;
422
 
423
        dev->interrupt = 0;
424
        return;
425
}
426
 
427
/* We have a good packet(s), get it/them out of the buffers. */
428
static void
429
net_rx(struct device *dev)
430
{
431
        struct net_local *lp = (struct net_local *)dev->priv;
432
        int ioaddr = dev->base_addr;
433
        int boguscount = 10;
434
 
435
        do {
436
                int status = inw(ioaddr);
437
                int pkt_len = inw(ioaddr);
438
 
439
                if (pkt_len == 0)                /* Read all the frames? */
440
                        break;                  /* Done for now */
441
 
442
                if (status & 0x40) {    /* There was an error. */
443
                        lp->stats.rx_errors++;
444
                        if (status & 0x20) lp->stats.rx_frame_errors++;
445
                        if (status & 0x10) lp->stats.rx_over_errors++;
446
                        if (status & 0x08) lp->stats.rx_crc_errors++;
447
                        if (status & 0x04) lp->stats.rx_fifo_errors++;
448
                } else {
449
                        /* Malloc up new buffer. */
450
                        struct sk_buff *skb;
451
 
452
                        skb = dev_alloc_skb(pkt_len);
453
                        if (skb == NULL) {
454
                                printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
455
                                           dev->name);
456
                                lp->stats.rx_dropped++;
457
                                break;
458
                        }
459
                        skb->dev = dev;
460
 
461
                        /* 'skb->data' points to the start of sk_buff data area. */
462
                        memcpy(skb_put(skb,pkt_len), (void*)dev->rmem_start,
463
                                   pkt_len);
464
                        /* or */
465
                        insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
466
 
467
                        netif_rx(skb);
468
                        lp->stats.rx_packets++;
469
                }
470
        } while (--boguscount);
471
 
472
        /*
473
         * If any worth-while packets have been received, dev_rint()
474
         * has done a mark_bh(NET_BH) for us and will work on them
475
         * when we get to the bottom-half routine.
476
         */
477
        return;
478
}
479
 
480
/* The inverse routine to net_open(). */
481
static int
482
net_close(struct device *dev)
483
{
484
        struct net_local *lp = (struct net_local *)dev->priv;
485
        int ioaddr = dev->base_addr;
486
 
487
        lp->open_time = 0;
488
 
489
        dev->tbusy = 1;
490
        dev->start = 0;
491
 
492
        /* Flush the Tx and disable Rx here. */
493
 
494
        disable_dma(dev->dma);
495
 
496
        /* If not IRQ or DMA jumpered, free up the line. */
497
        outw(0x00, ioaddr+0);    /* Release the physical interrupt line. */
498
 
499
        free_irq(dev->irq, NULL);
500
        free_dma(dev->dma);
501
 
502
        irq2dev_map[dev->irq] = 0;
503
 
504
        /* Update the statistics here. */
505
 
506
        MOD_DEC_USE_COUNT;
507
 
508
        return 0;
509
 
510
}
511
 
512
/*
513
 * Get the current statistics.
514
 * This may be called with the card open or closed.
515
 */
516
static struct enet_statistics *
517
net_get_stats(struct device *dev)
518
{
519
        struct net_local *lp = (struct net_local *)dev->priv;
520
        short ioaddr = dev->base_addr;
521
 
522
        cli();
523
        /* Update the statistics from the device registers. */
524
        lp->stats.rx_missed_errors = inw(ioaddr+1);
525
        sti();
526
 
527
        return &lp->stats;
528
}
529
 
530
/*
531
 * Set or clear the multicast filter for this adaptor.
532
 * num_addrs == -1      Promiscuous mode, receive all packets
533
 * num_addrs == 0       Normal mode, clear multicast list
534
 * num_addrs > 0        Multicast mode, receive normal and MC packets,
535
 *                      and do best-effort filtering.
536
 */
537
static void
538
set_multicast_list(struct device *dev)
539
{
540
        short ioaddr = dev->base_addr;
541
        if (dev->flags&IFF_PROMISC)
542
        {
543
                /* Enable promiscuous mode */
544
                outw(MULTICAST|PROMISC, ioaddr);
545
        }
546
        else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS)
547
        {
548
                /* Disable promiscuous mode, use normal mode. */
549
                hardware_set_filter(NULL);
550
 
551
                outw(MULTICAST, ioaddr);
552
        }
553
        else if(dev->mc_count)
554
        {
555
                /* Walk the address list, and load the filter */
556
                hardware_set_filter(dev->mc_list);
557
 
558
                outw(MULTICAST, ioaddr);
559
        }
560
        else
561
                outw(0, ioaddr);
562
}
563
 
564
#ifdef MODULE
565
 
566
static char devicename[9] = { 0, };
567
static struct device this_device = {
568
        devicename, /* will be inserted by linux/drivers/net/net_init.c */
569
        0, 0, 0, 0,
570
        0, 0,  /* I/O address, IRQ */
571
        0, 0, 0, NULL, netcard_probe };
572
 
573
static int io = 0x300;
574
static int irq = 0;
575
static int dma = 0;
576
static int mem = 0;
577
 
578
int init_module(void)
579
{
580
        int result;
581
 
582
        if (io == 0)
583
                printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n",
584
                           cardname);
585
 
586
        /* Copy the parameters from insmod into the device structure. */
587
        this_device.base_addr = io;
588
        this_device.irq       = irq;
589
        this_device.dma       = dma;
590
        this_device.mem_start = mem;
591
 
592
        if ((result = register_netdev(&this_device)) != 0)
593
                return result;
594
 
595
        return 0;
596
}
597
 
598
void
599
cleanup_module(void)
600
{
601
        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
602
        unregister_netdev(&this_device);
603
        /*
604
         * If we don't do this, we can't re-insmod it later.
605
         * Release irq/dma here, when you have jumpered versions and
606
         * allocate them in net_probe1().
607
         */
608
        /*
609
           free_irq(this_device.irq, NULL);
610
           free_dma(this_device.dma);
611
        */
612
        release_region(this_device.base_addr, NETCARD_IO_EXTENT);
613
 
614
        if (this_device.priv)
615
                kfree_s(this_device.priv, sizeof(struct net_local));
616
}
617
 
618
#endif /* MODULE */
619
 
620
/*
621
 * Local variables:
622
 *  compile-command:
623
 *      gcc -D__KERNEL__ -Wall -Wstrict-prototypes -Wwrite-strings
624
 *      -Wredundant-decls -O2 -m486 -c skeleton.c
625
 *  version-control: t
626
 *  kept-new-versions: 5
627
 *  tab-width: 4
628
 *  c-indent-level: 4
629
 * End:
630
 */

powered by: WebSVN 2.1.0

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