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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [net/] [net_init.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* netdrv_init.c: Initialization for network devices. */
2
/*
3
        Written 1993,1994,1995 by Donald Becker.
4
 
5
        The author may be reached as becker@cesdis.gsfc.nasa.gov or
6
        C/O Center of Excellence in Space Data and Information Sciences
7
                Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
8
 
9
        This file contains the initialization for the "pl14+" style ethernet
10
        drivers.  It should eventually replace most of drivers/net/Space.c.
11
        It's primary advantage is that it's able to allocate low-memory buffers.
12
        A secondary advantage is that the dangerous NE*000 netcards can reserve
13
        their I/O port region before the SCSI probes start.
14
 
15
        Modifications/additions by Bjorn Ekwall <bj0rn@blox.se>:
16
                ethdev_index[MAX_ETH_CARDS]
17
                register_netdev() / unregister_netdev()
18
 
19
        Modifications by Wolfgang Walter
20
                Use dev_close cleanly so we always shut things down tidily.
21
 
22
        Changed 29/10/95, Alan Cox to pass sockaddr's around for mac addresses.
23
 
24
        14/06/96 - Paul Gortmaker:      Add generic eth_change_mtu() function.
25
 
26
        August 12, 1996 - Lawrence V. Stefani: Added fddi_change_mtu() and
27
                                          fddi_setup() functions.
28
        Sept. 10, 1996  - Lawrence V. Stefani: Increased hard_header_len to
29
                                          include 3 pad bytes.
30
*/
31
 
32
#include <linux/config.h>
33
#include <linux/kernel.h>
34
#include <linux/sched.h>
35
#include <linux/types.h>
36
#include <linux/fs.h>
37
#include <linux/malloc.h>
38
#include <linux/if_ether.h>
39
#include <linux/string.h>
40
#include <linux/netdevice.h>
41
#include <linux/etherdevice.h>
42
#include <linux/fddidevice.h>
43
#include <linux/trdevice.h>
44
#include <linux/if_arp.h>
45
#ifdef CONFIG_NET_ALIAS
46
#include <linux/net_alias.h>
47
#endif
48
 
49
/* The network devices currently exist only in the socket namespace, so these
50
   entries are unused.  The only ones that make sense are
51
    open        start the ethercard
52
    close       stop  the ethercard
53
    ioctl       To get statistics, perhaps set the interface port (AUI, BNC, etc.)
54
   One can also imagine getting raw packets using
55
    read & write
56
   but this is probably better handled by a raw packet socket.
57
 
58
   Given that almost all of these functions are handled in the current
59
   socket-based scheme, putting ethercard devices in /dev/ seems pointless.
60
 
61
   [Removed all support for /dev network devices. When someone adds
62
    streams then by magic we get them, but otherwise they are un-needed
63
        and a space waste]
64
*/
65
 
66
/* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */
67
#define MAX_ETH_CARDS 16 /* same as the number if irq's in irq2dev[] */
68
static struct device *ethdev_index[MAX_ETH_CARDS];
69
 
70
 
71
/* Fill in the fields of the device structure with ethernet-generic values.
72
 
73
   If no device structure is passed, a new one is constructed, complete with
74
   a SIZEOF_PRIVATE private data area.
75
 
76
   If an empty string area is passed as dev->name, or a new structure is made,
77
   a new name string is constructed.  The passed string area should be 8 bytes
78
   long.
79
 */
80
 
81
struct device *
82
init_etherdev(struct device *dev, int sizeof_priv)
83
{
84
        int new_device = 0;
85
        int i;
86
 
87
        /* Use an existing correctly named device in Space.c:dev_base. */
88
        if (dev == NULL) {
89
                int alloc_size = sizeof(struct device) + sizeof("eth%d  ")
90
                        + sizeof_priv + 3;
91
                struct device *cur_dev;
92
                char pname[8];          /* Putative name for the device.  */
93
 
94
                for (i = 0; i < MAX_ETH_CARDS; ++i)
95
                        if (ethdev_index[i] == NULL) {
96
                                sprintf(pname, "eth%d", i);
97
                                for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
98
                                        if (strcmp(pname, cur_dev->name) == 0) {
99
                                                dev = cur_dev;
100
                                                dev->init = NULL;
101
                                                sizeof_priv = (sizeof_priv + 3) & ~3;
102
                                                dev->priv = sizeof_priv
103
                                                          ? kmalloc(sizeof_priv, GFP_KERNEL)
104
                                                          :     NULL;
105
                                                if (dev->priv) memset(dev->priv, 0, sizeof_priv);
106
                                                goto found;
107
                                        }
108
                        }
109
 
110
                alloc_size &= ~3;               /* Round to dword boundary. */
111
 
112
                dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
113
                memset(dev, 0, alloc_size);
114
                if (sizeof_priv)
115
                        dev->priv = (void *) (dev + 1);
116
                dev->name = sizeof_priv + (char *)(dev + 1);
117
                new_device = 1;
118
        }
119
 
120
        found:                                          /* From the double loop above. */
121
 
122
        if (dev->name &&
123
                ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
124
                for (i = 0; i < MAX_ETH_CARDS; ++i)
125
                        if (ethdev_index[i] == NULL) {
126
                                sprintf(dev->name, "eth%d", i);
127
                                ethdev_index[i] = dev;
128
                                break;
129
                        }
130
        }
131
 
132
        ether_setup(dev);       /* Hmmm, should this be called here? */
133
 
134
        if (new_device) {
135
                /* Append the device to the device queue. */
136
                struct device **old_devp = &dev_base;
137
                while ((*old_devp)->next)
138
                        old_devp = & (*old_devp)->next;
139
                (*old_devp)->next = dev;
140
                dev->next = 0;
141
        }
142
        return dev;
143
}
144
 
145
 
146
static int eth_mac_addr(struct device *dev, void *p)
147
{
148
        struct sockaddr *addr=p;
149
        if(dev->start)
150
                return -EBUSY;
151
        memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
152
        return 0;
153
}
154
 
155
static int eth_change_mtu(struct device *dev, int new_mtu)
156
{
157
        if ((new_mtu < 68) || (new_mtu > 1500))
158
                return -EINVAL;
159
        dev->mtu = new_mtu;
160
        return 0;
161
}
162
 
163
#ifdef CONFIG_FDDI
164
 
165
static int fddi_change_mtu(struct device *dev, int new_mtu)
166
{
167
        if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN))
168
                return(-EINVAL);
169
        dev->mtu = new_mtu;
170
        return(0);
171
}
172
 
173
#endif
174
 
175
void ether_setup(struct device *dev)
176
{
177
        int i;
178
        /* Fill in the fields of the device structure with ethernet-generic values.
179
           This should be in a common file instead of per-driver.  */
180
        for (i = 0; i < DEV_NUMBUFFS; i++)
181
                skb_queue_head_init(&dev->buffs[i]);
182
 
183
        /* register boot-defined "eth" devices */
184
        if (dev->name && (strncmp(dev->name, "eth", 3) == 0)) {
185
                i = simple_strtoul(dev->name + 3, NULL, 0);
186
                if (ethdev_index[i] == NULL) {
187
                        ethdev_index[i] = dev;
188
                }
189
                else if (dev != ethdev_index[i]) {
190
                        /* Really shouldn't happen! */
191
                        printk("ether_setup: Ouch! Someone else took %s\n",
192
                                dev->name);
193
                }
194
        }
195
 
196
        dev->change_mtu         = eth_change_mtu;
197
        dev->hard_header        = eth_header;
198
        dev->rebuild_header     = eth_rebuild_header;
199
        dev->set_mac_address    = eth_mac_addr;
200
        dev->header_cache_bind  = eth_header_cache_bind;
201
        dev->header_cache_update= eth_header_cache_update;
202
 
203
        dev->type               = ARPHRD_ETHER;
204
        dev->hard_header_len    = ETH_HLEN;
205
        dev->mtu                = 1500; /* eth_mtu */
206
        dev->addr_len           = ETH_ALEN;
207
        dev->tx_queue_len       = 100;  /* Ethernet wants good queues */
208
 
209
        memset(dev->broadcast,0xFF, ETH_ALEN);
210
 
211
        /* New-style flags. */
212
        dev->flags              = IFF_BROADCAST|IFF_MULTICAST;
213
        dev->family             = AF_INET;
214
        dev->pa_addr    = 0;
215
        dev->pa_brdaddr = 0;
216
        dev->pa_mask    = 0;
217
        dev->pa_alen    = 4;
218
}
219
 
220
#ifdef CONFIG_TR
221
 
222
void tr_setup(struct device *dev)
223
{
224
        int i;
225
        /* Fill in the fields of the device structure with ethernet-generic values.
226
           This should be in a common file instead of per-driver.  */
227
        for (i = 0; i < DEV_NUMBUFFS; i++)
228
                skb_queue_head_init(&dev->buffs[i]);
229
 
230
        dev->hard_header        = tr_header;
231
        dev->rebuild_header     = tr_rebuild_header;
232
 
233
        dev->type               = ARPHRD_IEEE802;
234
        dev->hard_header_len    = TR_HLEN;
235
        dev->mtu                = 2000; /* bug in fragmenter...*/
236
        dev->addr_len           = TR_ALEN;
237
        dev->tx_queue_len       = 100;  /* Long queues on tr */
238
 
239
        memset(dev->broadcast,0xFF, TR_ALEN);
240
 
241
        /* New-style flags. */
242
        dev->flags              = IFF_BROADCAST;
243
        dev->family             = AF_INET;
244
        dev->pa_addr    = 0;
245
        dev->pa_brdaddr = 0;
246
        dev->pa_mask    = 0;
247
        dev->pa_alen    = 4;
248
}
249
 
250
#endif
251
 
252
#ifdef CONFIG_FDDI
253
 
254
void fddi_setup(struct device *dev)
255
        {
256
        int i;
257
 
258
        /*
259
         * Fill in the fields of the device structure with FDDI-generic values.
260
         * This should be in a common file instead of per-driver.
261
         */
262
        for (i=0; i < DEV_NUMBUFFS; i++)
263
                skb_queue_head_init(&dev->buffs[i]);
264
 
265
        dev->change_mtu                 = fddi_change_mtu;
266
        dev->hard_header                = fddi_header;
267
        dev->rebuild_header             = fddi_rebuild_header;
268
 
269
        dev->type                               = ARPHRD_FDDI;
270
        dev->hard_header_len    = FDDI_K_SNAP_HLEN+3;   /* Assume 802.2 SNAP hdr len + 3 pad bytes */
271
        dev->mtu                                = FDDI_K_SNAP_DLEN;             /* Assume max payload of 802.2 SNAP frame */
272
        dev->addr_len                   = FDDI_K_ALEN;
273
        dev->tx_queue_len               = 100;  /* Long queues on FDDI */
274
 
275
        memset(dev->broadcast, 0xFF, FDDI_K_ALEN);
276
 
277
        /* New-style flags */
278
        dev->flags              = IFF_BROADCAST | IFF_MULTICAST;
279
        dev->family             = AF_INET;
280
        dev->pa_addr    = 0;
281
        dev->pa_brdaddr = 0;
282
        dev->pa_mask    = 0;
283
        dev->pa_alen    = 4;
284
        return;
285
        }
286
 
287
#endif
288
 
289
int ether_config(struct device *dev, struct ifmap *map)
290
{
291
        if (map->mem_start != (u_long)(-1))
292
                dev->mem_start = map->mem_start;
293
        if (map->mem_end != (u_long)(-1))
294
                dev->mem_end = map->mem_end;
295
        if (map->base_addr != (u_short)(-1))
296
                dev->base_addr = map->base_addr;
297
        if (map->irq != (u_char)(-1))
298
                dev->irq = map->irq;
299
        if (map->dma != (u_char)(-1))
300
                dev->dma = map->dma;
301
        if (map->port != (u_char)(-1))
302
                dev->if_port = map->port;
303
        return 0;
304
}
305
 
306
int register_netdev(struct device *dev)
307
{
308
        struct device *d = dev_base;
309
        unsigned long flags;
310
        int i=MAX_ETH_CARDS;
311
 
312
        save_flags(flags);
313
        cli();
314
 
315
        if (dev && dev->init) {
316
                if (dev->name &&
317
                        ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
318
                        for (i = 0; i < MAX_ETH_CARDS; ++i)
319
                                if (ethdev_index[i] == NULL) {
320
                                        sprintf(dev->name, "eth%d", i);
321
/*                                      printk("loading device '%s'...\n", dev->name);*/
322
                                        ethdev_index[i] = dev;
323
                                        break;
324
                                }
325
                }
326
 
327
                sti();  /* device probes assume interrupts enabled */
328
                if (dev->init(dev) != 0) {
329
                    if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL;
330
                        restore_flags(flags);
331
                        return -EIO;
332
                }
333
                cli();
334
 
335
                /* Add device to end of chain */
336
                if (dev_base) {
337
                        while (d->next)
338
                                d = d->next;
339
                        d->next = dev;
340
                }
341
                else
342
                        dev_base = dev;
343
                dev->next = NULL;
344
        }
345
        restore_flags(flags);
346
        return 0;
347
}
348
 
349
void unregister_netdev(struct device *dev)
350
{
351
        struct device *d = dev_base;
352
        unsigned long flags;
353
        int i;
354
 
355
        save_flags(flags);
356
        cli();
357
 
358
        if (dev == NULL)
359
        {
360
                printk("was NULL\n");
361
                restore_flags(flags);
362
                return;
363
        }
364
        /* else */
365
        if (dev->start)
366
                printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
367
 
368
        /*
369
         *      must jump over main_device+aliases
370
         *      avoid alias devices unregistration so that only
371
         *      net_alias module manages them
372
         */
373
#ifdef CONFIG_NET_ALIAS         
374
        if (dev_base == dev)
375
                dev_base = net_alias_nextdev(dev);
376
        else
377
        {
378
                while(d && (net_alias_nextdev(d) != dev)) /* skip aliases */
379
                        d = net_alias_nextdev(d);
380
 
381
                if (d && (net_alias_nextdev(d) == dev))
382
                {
383
                        /*
384
                         *      Critical: Bypass by consider devices as blocks (maindev+aliases)
385
                         */
386
                        net_alias_nextdev_set(d, net_alias_nextdev(dev));
387
                }
388
#else
389
        if (dev_base == dev)
390
                dev_base = dev->next;
391
        else
392
        {
393
                while (d && (d->next != dev))
394
                        d = d->next;
395
 
396
                if (d && (d->next == dev))
397
                {
398
                        d->next = dev->next;
399
                }
400
#endif
401
                else
402
                {
403
                        printk("unregister_netdev: '%s' not found\n", dev->name);
404
                        restore_flags(flags);
405
                        return;
406
                }
407
        }
408
        for (i = 0; i < MAX_ETH_CARDS; ++i)
409
        {
410
                if (ethdev_index[i] == dev)
411
                {
412
                        ethdev_index[i] = NULL;
413
                        break;
414
                }
415
        }
416
 
417
        restore_flags(flags);
418
 
419
        /*
420
         *      You can i.e use a interfaces in a route though it is not up.
421
         *      We call close_dev (which is changed: it will down a device even if
422
         *      dev->flags==0 (but it will not call dev->stop if IFF_UP
423
         *      is not set).
424
         *      This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev),
425
         *      dev_mc_discard(dev), ....
426
         */
427
 
428
        dev_close(dev);
429
}
430
 
431
 
432
/*
433
 * Local variables:
434
 *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
435
 *  version-control: t
436
 *  kept-new-versions: 5
437
 *  tab-width: 4
438
 * End:
439
 */

powered by: WebSVN 2.1.0

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