Subversion Repositories shark

Rev

Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed

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