1 /* netdrv_init.c: Initialization for network devices. */
3 Written 1993,1994,1995 by Donald Becker.
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
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.
15 Modifications/additions by Bjorn Ekwall <bj0rn@blox.se>:
16 ethdev_index[MAX_ETH_CARDS]
17 register_netdev() / unregister_netdev()
19 Modifications by Wolfgang Walter
20 Use dev_close cleanly so we always shut things down tidily.
22 Changed 29/10/95, Alan Cox to pass sockaddr's around for mac addresses.
24 14/06/96 - Paul Gortmaker: Add generic eth_change_mtu() function.
25 24/09/96 - Paul Norton: Add token-ring variants of the netdev functions.
28 #include <linux/config.h>
29 #include <linux/kernel.h>
30 #include <linux/sched.h>
31 #include <linux/types.h>
33 #include <linux/malloc.h>
34 #include <linux/if_ether.h>
35 #include <linux/string.h>
36 #include <linux/netdevice.h>
37 #include <linux/etherdevice.h>
38 #include <linux/fddidevice.h>
39 #include <linux/hippidevice.h>
40 #include <linux/trdevice.h>
41 #include <linux/fcdevice.h>
42 #include <linux/if_arp.h>
43 #include <linux/if_ltalk.h>
44 #include <linux/rtnetlink.h>
45 #include <net/neighbour.h>
47 /* The network devices currently exist only in the socket namespace, so these
48 entries are unused. The only ones that make sense are
49 open start the ethercard
50 close stop the ethercard
51 ioctl To get statistics, perhaps set the interface port (AUI, BNC, etc.)
52 One can also imagine getting raw packets using
54 but this is probably better handled by a raw packet socket.
56 Given that almost all of these functions are handled in the current
57 socket-based scheme, putting ethercard devices in /dev/ seems pointless.
59 [Removed all support for /dev network devices. When someone adds
60 streams then by magic we get them, but otherwise they are un-needed
64 /* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */
65 #define MAX_ETH_CARDS 16
66 static struct net_device
*ethdev_index
[MAX_ETH_CARDS
];
69 /* Fill in the fields of the device structure with ethernet-generic values.
71 If no device structure is passed, a new one is constructed, complete with
72 a SIZEOF_PRIVATE private data area.
74 If an empty string area is passed as dev->name, or a new structure is made,
75 a new name string is constructed. The passed string area should be 8 bytes
80 init_etherdev(struct net_device
*dev
, int sizeof_priv
)
85 /* Use an existing correctly named device in Space.c:dev_base. */
87 int alloc_size
= sizeof(struct net_device
) + IFNAMSIZ
89 struct net_device
*cur_dev
;
90 char pname
[8]; /* Putative name for the device. */
92 for (i
= 0; i
< MAX_ETH_CARDS
; ++i
)
93 if (ethdev_index
[i
] == NULL
) {
94 sprintf(pname
, "eth%d", i
);
95 read_lock_bh(&dev_base_lock
);
96 for (cur_dev
= dev_base
; cur_dev
; cur_dev
= cur_dev
->next
) {
97 if (strcmp(pname
, cur_dev
->name
) == 0) {
99 read_unlock_bh(&dev_base_lock
);
101 sizeof_priv
= (sizeof_priv
+ 3) & ~3;
102 dev
->priv
= sizeof_priv
103 ? kmalloc(sizeof_priv
, GFP_KERNEL
)
105 if (dev
->priv
) memset(dev
->priv
, 0, sizeof_priv
);
109 read_unlock_bh(&dev_base_lock
);
112 alloc_size
&= ~3; /* Round to dword boundary. */
114 dev
= (struct net_device
*)kmalloc(alloc_size
, GFP_KERNEL
);
117 memset(dev
, 0, alloc_size
);
119 dev
->priv
= (void *) (dev
+ 1);
120 dev
->name
= sizeof_priv
+ (char *)(dev
+ 1);
124 found
: /* From the double loop above. */
127 ((dev
->name
[0] == '\0') || (dev
->name
[0] == ' '))) {
128 for (i
= 0; i
< MAX_ETH_CARDS
; ++i
)
129 if (ethdev_index
[i
] == NULL
) {
130 sprintf(dev
->name
, "eth%d", i
);
131 ethdev_index
[i
] = dev
;
136 ether_setup(dev
); /* Hmmm, should this be called here? */
140 register_netdevice(dev
);
147 static int eth_mac_addr(struct net_device
*dev
, void *p
)
149 struct sockaddr
*addr
=p
;
152 memcpy(dev
->dev_addr
, addr
->sa_data
,dev
->addr_len
);
156 static int eth_change_mtu(struct net_device
*dev
, int new_mtu
)
158 if ((new_mtu
< 68) || (new_mtu
> 1500))
166 static int fddi_change_mtu(struct net_device
*dev
, int new_mtu
)
168 if ((new_mtu
< FDDI_K_SNAP_HLEN
) || (new_mtu
> FDDI_K_SNAP_DLEN
))
177 #define MAX_HIP_CARDS 4
178 static struct net_device
*hipdev_index
[MAX_HIP_CARDS
];
180 static int hippi_change_mtu(struct net_device
*dev
, int new_mtu
)
183 * HIPPI's got these nice large MTUs.
185 if ((new_mtu
< 68) || (new_mtu
> 65280))
193 * For HIPPI we will actually use the lower 4 bytes of the hardware
194 * address as the I-FIELD rather than the actual hardware address.
196 static int hippi_mac_addr(struct net_device
*dev
, void *p
)
198 struct sockaddr
*addr
= p
;
201 memcpy(dev
->dev_addr
, addr
->sa_data
, dev
->addr_len
);
206 struct net_device
*init_hippi_dev(struct net_device
*dev
, int sizeof_priv
)
211 /* Use an existing correctly named device in Space.c:dev_base. */
213 int alloc_size
= sizeof(struct net_device
) + IFNAMSIZ
215 struct net_device
*cur_dev
;
218 for (i
= 0; i
< MAX_HIP_CARDS
; ++i
)
219 if (hipdev_index
[i
] == NULL
) {
220 sprintf(pname
, "hip%d", i
);
221 read_lock_bh(&dev_base_lock
);
222 for (cur_dev
= dev_base
; cur_dev
; cur_dev
= cur_dev
->next
) {
223 if (strcmp(pname
, cur_dev
->name
) == 0) {
225 read_unlock_bh(&dev_base_lock
);
227 sizeof_priv
= (sizeof_priv
+ 3) & ~3;
228 dev
->priv
= sizeof_priv
229 ? kmalloc(sizeof_priv
, GFP_KERNEL
)
231 if (dev
->priv
) memset(dev
->priv
, 0, sizeof_priv
);
235 read_unlock_bh(&dev_base_lock
);
238 alloc_size
&= ~3; /* Round to dword boundary. */
240 dev
= (struct net_device
*)kmalloc(alloc_size
, GFP_KERNEL
);
243 memset(dev
, 0, alloc_size
);
245 dev
->priv
= (void *) (dev
+ 1);
246 dev
->name
= sizeof_priv
+ (char *)(dev
+ 1);
250 hipfound
: /* From the double loop above. */
253 ((dev
->name
[0] == '\0') || (dev
->name
[0] == ' '))) {
254 for (i
= 0; i
< MAX_HIP_CARDS
; ++i
)
255 if (hipdev_index
[i
] == NULL
) {
256 sprintf(dev
->name
, "hip%d", i
);
257 hipdev_index
[i
] = dev
;
266 register_netdevice(dev
);
273 void unregister_hipdev(struct net_device
*dev
)
277 unregister_netdevice(dev
);
278 for (i
= 0; i
< MAX_HIP_CARDS
; ++i
) {
279 if (hipdev_index
[i
] == dev
) {
280 hipdev_index
[i
] = NULL
;
288 static int hippi_neigh_setup_dev(struct net_device
*dev
, struct neigh_parms
*p
)
290 /* Never send broadcast/multicast ARP messages */
293 /* In IPv6 unicast probes are valid even on NBMA,
294 * because they are encapsulated in normal IPv6 protocol.
295 * Should be a generic flag.
297 if (p
->tbl
->family
!= AF_INET6
)
304 void ether_setup(struct net_device
*dev
)
307 /* Fill in the fields of the device structure with ethernet-generic values.
308 This should be in a common file instead of per-driver. */
310 /* register boot-defined "eth" devices */
311 if (dev
->name
&& (strncmp(dev
->name
, "eth", 3) == 0)) {
312 i
= simple_strtoul(dev
->name
+ 3, NULL
, 0);
313 if (ethdev_index
[i
] == NULL
) {
314 ethdev_index
[i
] = dev
;
316 else if (dev
!= ethdev_index
[i
]) {
317 /* Really shouldn't happen! */
318 printk("ether_setup: Ouch! Someone else took %s\n",
323 dev
->change_mtu
= eth_change_mtu
;
324 dev
->hard_header
= eth_header
;
325 dev
->rebuild_header
= eth_rebuild_header
;
326 dev
->set_mac_address
= eth_mac_addr
;
327 dev
->hard_header_cache
= eth_header_cache
;
328 dev
->header_cache_update
= eth_header_cache_update
;
329 dev
->hard_header_parse
= eth_header_parse
;
331 dev
->type
= ARPHRD_ETHER
;
332 dev
->hard_header_len
= ETH_HLEN
;
333 dev
->mtu
= 1500; /* eth_mtu */
334 dev
->addr_len
= ETH_ALEN
;
335 dev
->tx_queue_len
= 100; /* Ethernet wants good queues */
337 memset(dev
->broadcast
,0xFF, ETH_ALEN
);
339 /* New-style flags. */
340 dev
->flags
= IFF_BROADCAST
|IFF_MULTICAST
;
342 dev_init_buffers(dev
);
347 void fddi_setup(struct net_device
*dev
)
350 * Fill in the fields of the device structure with FDDI-generic values.
351 * This should be in a common file instead of per-driver.
354 dev
->change_mtu
= fddi_change_mtu
;
355 dev
->hard_header
= fddi_header
;
356 dev
->rebuild_header
= fddi_rebuild_header
;
358 dev
->type
= ARPHRD_FDDI
;
359 dev
->hard_header_len
= FDDI_K_SNAP_HLEN
+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */
360 dev
->mtu
= FDDI_K_SNAP_DLEN
; /* Assume max payload of 802.2 SNAP frame */
361 dev
->addr_len
= FDDI_K_ALEN
;
362 dev
->tx_queue_len
= 100; /* Long queues on FDDI */
364 memset(dev
->broadcast
, 0xFF, FDDI_K_ALEN
);
366 /* New-style flags */
367 dev
->flags
= IFF_BROADCAST
| IFF_MULTICAST
;
369 dev_init_buffers(dev
);
377 void hippi_setup(struct net_device
*dev
)
381 if (dev
->name
&& (strncmp(dev
->name
, "hip", 3) == 0)) {
382 i
= simple_strtoul(dev
->name
+ 3, NULL
, 0);
383 if (hipdev_index
[i
] == NULL
) {
384 hipdev_index
[i
] = dev
;
386 else if (dev
!= hipdev_index
[i
]) {
387 printk("hippi_setup: Ouch! Someone else took %s\n",
392 dev
->set_multicast_list
= NULL
;
393 dev
->change_mtu
= hippi_change_mtu
;
394 dev
->hard_header
= hippi_header
;
395 dev
->rebuild_header
= hippi_rebuild_header
;
396 dev
->set_mac_address
= hippi_mac_addr
;
397 dev
->hard_header_parse
= NULL
;
398 dev
->hard_header_cache
= NULL
;
399 dev
->header_cache_update
= NULL
;
400 dev
->neigh_setup
= hippi_neigh_setup_dev
;
403 * We don't support HIPPI `ARP' for the time being, and probably
404 * never will unless someone else implements it. However we
405 * still need a fake ARPHRD to make ifconfig and friends play ball.
407 dev
->type
= ARPHRD_HIPPI
;
408 dev
->hard_header_len
= HIPPI_HLEN
;
410 dev
->addr_len
= HIPPI_ALEN
;
411 dev
->tx_queue_len
= 25 /* 5 */;
412 memset(dev
->broadcast
, 0xFF, HIPPI_ALEN
);
416 * HIPPI doesn't support broadcast+multicast and we only use
417 * static ARP tables. ARP is disabled by hippi_neigh_setup_dev.
421 dev_init_buffers(dev
);
425 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
427 static int ltalk_change_mtu(struct net_device
*dev
, int mtu
)
432 static int ltalk_mac_addr(struct net_device
*dev
, void *addr
)
438 void ltalk_setup(struct net_device
*dev
)
440 /* Fill in the fields of the device structure with localtalk-generic values. */
442 dev
->change_mtu
= ltalk_change_mtu
;
443 dev
->hard_header
= NULL
;
444 dev
->rebuild_header
= NULL
;
445 dev
->set_mac_address
= ltalk_mac_addr
;
446 dev
->hard_header_cache
= NULL
;
447 dev
->header_cache_update
= NULL
;
449 dev
->type
= ARPHRD_LOCALTLK
;
450 dev
->hard_header_len
= LTALK_HLEN
;
451 dev
->mtu
= LTALK_MTU
;
452 dev
->addr_len
= LTALK_ALEN
;
453 dev
->tx_queue_len
= 10;
455 dev
->broadcast
[0] = 0xFF;
457 dev
->flags
= IFF_BROADCAST
|IFF_MULTICAST
|IFF_NOARP
;
459 dev_init_buffers(dev
);
464 int ether_config(struct net_device
*dev
, struct ifmap
*map
)
466 if (map
->mem_start
!= (u_long
)(-1))
467 dev
->mem_start
= map
->mem_start
;
468 if (map
->mem_end
!= (u_long
)(-1))
469 dev
->mem_end
= map
->mem_end
;
470 if (map
->base_addr
!= (u_short
)(-1))
471 dev
->base_addr
= map
->base_addr
;
472 if (map
->irq
!= (u_char
)(-1))
474 if (map
->dma
!= (u_char
)(-1))
476 if (map
->port
!= (u_char
)(-1))
477 dev
->if_port
= map
->port
;
481 static int etherdev_get_index(struct net_device
*dev
)
485 for (i
= 0; i
< MAX_ETH_CARDS
; ++i
) {
486 if (ethdev_index
[i
] == NULL
) {
487 sprintf(dev
->name
, "eth%d", i
);
488 /* printk("loading device '%s'...\n", dev->name);*/
489 ethdev_index
[i
] = dev
;
496 static void etherdev_put_index(struct net_device
*dev
)
499 for (i
= 0; i
< MAX_ETH_CARDS
; ++i
) {
500 if (ethdev_index
[i
] == dev
) {
501 ethdev_index
[i
] = NULL
;
507 int register_netdev(struct net_device
*dev
)
514 (dev
->name
[0] == '\0' || dev
->name
[0] == ' '))
515 i
= etherdev_get_index(dev
);
517 if (register_netdevice(dev
)) {
519 etherdev_put_index(dev
);
527 void unregister_netdev(struct net_device
*dev
)
530 unregister_netdevice(dev
);
531 etherdev_put_index(dev
);
537 /* The list of used and available "tr" slots */
538 #define MAX_TR_CARDS 16
539 static struct net_device
*trdev_index
[MAX_TR_CARDS
];
541 struct net_device
*init_trdev(struct net_device
*dev
, int sizeof_priv
)
546 /* Use an existing correctly named device in Space.c:dev_base. */
548 int alloc_size
= sizeof(struct net_device
) + IFNAMSIZ
550 struct net_device
*cur_dev
;
551 char pname
[8]; /* Putative name for the device. */
553 for (i
= 0; i
< MAX_TR_CARDS
; ++i
)
554 if (trdev_index
[i
] == NULL
) {
555 sprintf(pname
, "tr%d", i
);
556 read_lock_bh(&dev_base_lock
);
557 for (cur_dev
= dev_base
; cur_dev
; cur_dev
= cur_dev
->next
) {
558 if (strcmp(pname
, cur_dev
->name
) == 0) {
560 read_unlock_bh(&dev_base_lock
);
562 sizeof_priv
= (sizeof_priv
+ 3) & ~3;
563 dev
->priv
= sizeof_priv
564 ? kmalloc(sizeof_priv
, GFP_KERNEL
)
566 if (dev
->priv
) memset(dev
->priv
, 0, sizeof_priv
);
570 read_unlock_bh(&dev_base_lock
);
573 alloc_size
&= ~3; /* Round to dword boundary. */
574 dev
= (struct net_device
*)kmalloc(alloc_size
, GFP_KERNEL
);
577 memset(dev
, 0, alloc_size
);
579 dev
->priv
= (void *) (dev
+ 1);
580 dev
->name
= sizeof_priv
+ (char *)(dev
+ 1);
584 trfound
: /* From the double loop above. */
586 for (i
= 0; i
< MAX_TR_CARDS
; ++i
)
587 if (trdev_index
[i
] == NULL
) {
588 sprintf(dev
->name
, "tr%d", i
);
589 trdev_index
[i
] = dev
;
594 dev
->hard_header
= tr_header
;
595 dev
->rebuild_header
= tr_rebuild_header
;
597 dev
->type
= ARPHRD_IEEE802
;
598 dev
->hard_header_len
= TR_HLEN
;
599 dev
->mtu
= 2000; /* bug in fragmenter...*/
600 dev
->addr_len
= TR_ALEN
;
601 dev
->tx_queue_len
= 100; /* Long queues on tr */
603 memset(dev
->broadcast
,0xFF, TR_ALEN
);
605 /* New-style flags. */
606 dev
->flags
= IFF_BROADCAST
;
610 register_netdevice(dev
);
616 void tr_setup(struct net_device
*dev
)
620 /* register boot-defined "tr" devices */
621 if (dev
->name
&& (strncmp(dev
->name
, "tr", 2) == 0)) {
622 i
= simple_strtoul(dev
->name
+ 2, NULL
, 0);
623 if (trdev_index
[i
] == NULL
) {
624 trdev_index
[i
] = dev
;
626 else if (dev
!= trdev_index
[i
]) {
627 /* Really shouldn't happen! */
628 printk("tr_setup: Ouch! Someone else took %s\n",
634 void tr_freedev(struct net_device
*dev
)
637 for (i
= 0; i
< MAX_TR_CARDS
; ++i
)
639 if (trdev_index
[i
] == dev
)
641 trdev_index
[i
] = NULL
;
647 int register_trdev(struct net_device
*dev
)
649 dev_init_buffers(dev
);
651 if (dev
->init
&& dev
->init(dev
) != 0) {
652 unregister_trdev(dev
);
658 void unregister_trdev(struct net_device
*dev
)
661 unregister_netdevice(dev
);
670 #define MAX_FC_CARDS 2
671 static struct net_device
*fcdev_index
[MAX_FC_CARDS
];
673 void fc_setup(struct net_device
*dev
)
677 /* register boot-defined "fc" devices */
678 if (dev
->name
&& (strncmp(dev
->name
, "fc", 2) == 0)) {
679 i
= simple_strtoul(dev
->name
+ 2, NULL
, 0);
680 if (fcdev_index
[i
] == NULL
) {
681 fcdev_index
[i
] = dev
;
683 else if (dev
!= fcdev_index
[i
]) {
684 /* Really shouldn't happen! */
685 printk("fc_setup: Ouch! Someone else took %s\n",
690 dev
->hard_header
= fc_header
;
691 dev
->rebuild_header
= fc_rebuild_header
;
693 dev
->type
= ARPHRD_IEEE802
;
694 dev
->hard_header_len
= FC_HLEN
;
696 dev
->addr_len
= FC_ALEN
;
697 dev
->tx_queue_len
= 100; /* Long queues on fc */
699 memset(dev
->broadcast
,0xFF, FC_ALEN
);
701 /* New-style flags. */
702 dev
->flags
= IFF_BROADCAST
;
703 dev_init_buffers(dev
);
708 struct net_device
*init_fcdev(struct net_device
*dev
, int sizeof_priv
)
712 /* Use an existing correctly named device in Space.c:dev_base. */
714 int alloc_size
= sizeof(struct net_device
) + sizeof("fc%d ") + sizeof_priv
+ 3;
715 struct net_device
*cur_dev
;
716 char pname
[8]; /* Putative name for the device. */
718 for (i
= 0; i
< MAX_FC_CARDS
; ++i
)
719 if (fcdev_index
[i
] == NULL
) {
720 sprintf(pname
, "fc%d", i
);
721 for (cur_dev
= dev_base
; cur_dev
; cur_dev
= cur_dev
->next
)
722 if (strcmp(pname
, cur_dev
->name
) == 0) {
725 sizeof_priv
= (sizeof_priv
+ 3) &~3;
726 dev
->priv
= sizeof_priv
727 ? kmalloc(sizeof_priv
, GFP_KERNEL
)
729 if (dev
->priv
) memset(dev
->priv
, 0, sizeof_priv
);
734 alloc_size
&= ~3; /* Round to dword boundary. */
735 dev
= (struct net_device
*)kmalloc(alloc_size
, GFP_KERNEL
);
736 memset(dev
, 0, alloc_size
);
738 dev
->priv
= (void *) (dev
+ 1);
739 dev
->name
= sizeof_priv
+ (char *)(dev
+ 1);
743 fcfound
: /* From the double loop */
745 for (i
= 0; i
< MAX_FC_CARDS
; ++i
)
746 if (fcdev_index
[i
] == NULL
) {
747 sprintf(dev
->name
, "fc%d", i
);
748 fcdev_index
[i
] = dev
;
755 register_netdevice(dev
);
761 void fc_freedev(struct net_device
*dev
)
764 for (i
= 0; i
< MAX_FC_CARDS
; ++i
) {
765 if (fcdev_index
[i
] == dev
) {
766 fcdev_index
[i
] = NULL
;
773 int register_fcdev(struct net_device
*dev
)
775 dev_init_buffers(dev
);
776 if (dev
->init
&& dev
->init(dev
) != 0) {
777 unregister_fcdev(dev
);
783 void unregister_fcdev(struct net_device
*dev
)
786 unregister_netdevice(dev
);
791 #endif /* CONFIG_NET_FC */
795 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
797 * kept-new-versions: 5