Import 2.3.18pre1
[davej-history.git] / drivers / net / net_init.c
blob857080e0f0a67297a88de02ad1b24f552f55ecb5
1 /* netdrv_init.c: Initialization for network devices. */
2 /*
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>
32 #include <linux/fs.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
53 read & write
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
61 and a space waste]
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
76 long.
79 struct net_device *
80 init_etherdev(struct net_device *dev, int sizeof_priv)
82 int new_device = 0;
83 int i;
85 /* Use an existing correctly named device in Space.c:dev_base. */
86 if (dev == NULL) {
87 int alloc_size = sizeof(struct net_device) + IFNAMSIZ
88 + sizeof_priv + 3;
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) {
98 dev = cur_dev;
99 read_unlock_bh(&dev_base_lock);
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;
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);
115 if(dev==NULL)
116 return NULL;
117 memset(dev, 0, alloc_size);
118 if (sizeof_priv)
119 dev->priv = (void *) (dev + 1);
120 dev->name = sizeof_priv + (char *)(dev + 1);
121 new_device = 1;
124 found: /* From the double loop above. */
126 if (dev->name &&
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;
132 break;
136 ether_setup(dev); /* Hmmm, should this be called here? */
138 if (new_device) {
139 rtnl_lock();
140 register_netdevice(dev);
141 rtnl_unlock();
143 return dev;
147 static int eth_mac_addr(struct net_device *dev, void *p)
149 struct sockaddr *addr=p;
150 if(dev->start)
151 return -EBUSY;
152 memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
153 return 0;
156 static int eth_change_mtu(struct net_device *dev, int new_mtu)
158 if ((new_mtu < 68) || (new_mtu > 1500))
159 return -EINVAL;
160 dev->mtu = new_mtu;
161 return 0;
164 #ifdef CONFIG_FDDI
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))
169 return(-EINVAL);
170 dev->mtu = new_mtu;
171 return(0);
174 #endif
176 #ifdef CONFIG_HIPPI
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))
186 return -EINVAL;
187 dev->mtu = new_mtu;
188 return(0);
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;
199 if(dev->start)
200 return -EBUSY;
201 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
202 return 0;
206 struct net_device *init_hippi_dev(struct net_device *dev, int sizeof_priv)
208 int new_device = 0;
209 int i;
211 /* Use an existing correctly named device in Space.c:dev_base. */
212 if (dev == NULL) {
213 int alloc_size = sizeof(struct net_device) + IFNAMSIZ
214 + sizeof_priv + 3;
215 struct net_device *cur_dev;
216 char pname[8];
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) {
224 dev = cur_dev;
225 read_unlock_bh(&dev_base_lock);
226 dev->init = NULL;
227 sizeof_priv = (sizeof_priv + 3) & ~3;
228 dev->priv = sizeof_priv
229 ? kmalloc(sizeof_priv, GFP_KERNEL)
230 : NULL;
231 if (dev->priv) memset(dev->priv, 0, sizeof_priv);
232 goto hipfound;
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);
241 if(dev==NULL)
242 return NULL;
243 memset(dev, 0, alloc_size);
244 if (sizeof_priv)
245 dev->priv = (void *) (dev + 1);
246 dev->name = sizeof_priv + (char *)(dev + 1);
247 new_device = 1;
250 hipfound: /* From the double loop above. */
252 if (dev->name &&
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;
258 break;
262 hippi_setup(dev);
264 if (new_device) {
265 rtnl_lock();
266 register_netdevice(dev);
267 rtnl_unlock();
269 return dev;
273 void unregister_hipdev(struct net_device *dev)
275 int i;
276 rtnl_lock();
277 unregister_netdevice(dev);
278 for (i = 0; i < MAX_HIP_CARDS; ++i) {
279 if (hipdev_index[i] == dev) {
280 hipdev_index[i] = NULL;
281 break;
284 rtnl_unlock();
288 static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
290 /* Never send broadcast/multicast ARP messages */
291 p->mcast_probes = 0;
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)
298 p->ucast_probes = 0;
299 return 0;
302 #endif
304 void ether_setup(struct net_device *dev)
306 int i;
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",
319 dev->name);
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);
345 #ifdef CONFIG_FDDI
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);
371 return;
374 #endif
376 #ifdef CONFIG_HIPPI
377 void hippi_setup(struct net_device *dev)
379 int i;
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",
388 dev->name);
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;
409 dev->mtu = 65280;
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.
419 dev->flags = 0;
421 dev_init_buffers(dev);
423 #endif
425 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
427 static int ltalk_change_mtu(struct net_device *dev, int mtu)
429 return -EINVAL;
432 static int ltalk_mac_addr(struct net_device *dev, void *addr)
434 return -EINVAL;
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);
462 #endif
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))
473 dev->irq = map->irq;
474 if (map->dma != (u_char)(-1))
475 dev->dma = map->dma;
476 if (map->port != (u_char)(-1))
477 dev->if_port = map->port;
478 return 0;
481 static int etherdev_get_index(struct net_device *dev)
483 int i=MAX_ETH_CARDS;
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;
490 return i;
493 return -1;
496 static void etherdev_put_index(struct net_device *dev)
498 int i;
499 for (i = 0; i < MAX_ETH_CARDS; ++i) {
500 if (ethdev_index[i] == dev) {
501 ethdev_index[i] = NULL;
502 break;
507 int register_netdev(struct net_device *dev)
509 int i=-1;
511 rtnl_lock();
513 if (dev->name &&
514 (dev->name[0] == '\0' || dev->name[0] == ' '))
515 i = etherdev_get_index(dev);
517 if (register_netdevice(dev)) {
518 if (i >= 0)
519 etherdev_put_index(dev);
520 rtnl_unlock();
521 return -EIO;
523 rtnl_unlock();
524 return 0;
527 void unregister_netdev(struct net_device *dev)
529 rtnl_lock();
530 unregister_netdevice(dev);
531 etherdev_put_index(dev);
532 rtnl_unlock();
536 #ifdef CONFIG_TR
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)
543 int new_device = 0;
544 int i;
546 /* Use an existing correctly named device in Space.c:dev_base. */
547 if (dev == NULL) {
548 int alloc_size = sizeof(struct net_device) + IFNAMSIZ
549 + sizeof_priv + 3;
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) {
559 dev = cur_dev;
560 read_unlock_bh(&dev_base_lock);
561 dev->init = NULL;
562 sizeof_priv = (sizeof_priv + 3) & ~3;
563 dev->priv = sizeof_priv
564 ? kmalloc(sizeof_priv, GFP_KERNEL)
565 : NULL;
566 if (dev->priv) memset(dev->priv, 0, sizeof_priv);
567 goto trfound;
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);
575 if(dev==NULL)
576 return NULL;
577 memset(dev, 0, alloc_size);
578 if (sizeof_priv)
579 dev->priv = (void *) (dev + 1);
580 dev->name = sizeof_priv + (char *)(dev + 1);
581 new_device = 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;
590 break;
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;
608 if (new_device) {
609 rtnl_lock();
610 register_netdevice(dev);
611 rtnl_unlock();
613 return dev;
616 void tr_setup(struct net_device *dev)
618 int i;
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",
629 dev->name);
634 void tr_freedev(struct net_device *dev)
636 int i;
637 for (i = 0; i < MAX_TR_CARDS; ++i)
639 if (trdev_index[i] == dev)
641 trdev_index[i] = NULL;
642 break;
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);
653 return -EIO;
655 return 0;
658 void unregister_trdev(struct net_device *dev)
660 rtnl_lock();
661 unregister_netdevice(dev);
662 rtnl_unlock();
663 tr_freedev(dev);
665 #endif
668 #ifdef CONFIG_NET_FC
670 #define MAX_FC_CARDS 2
671 static struct net_device *fcdev_index[MAX_FC_CARDS];
673 void fc_setup(struct net_device *dev)
675 int i;
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",
686 dev->name);
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;
695 dev->mtu = 2024;
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);
704 return;
708 struct net_device *init_fcdev(struct net_device *dev, int sizeof_priv)
710 int new_device = 0;
711 int i;
712 /* Use an existing correctly named device in Space.c:dev_base. */
713 if (dev == NULL) {
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) {
723 dev = cur_dev;
724 dev->init = NULL;
725 sizeof_priv = (sizeof_priv + 3) &~3;
726 dev->priv = sizeof_priv
727 ? kmalloc(sizeof_priv, GFP_KERNEL)
728 : NULL;
729 if (dev->priv) memset(dev->priv, 0, sizeof_priv);
730 goto fcfound;
734 alloc_size &= ~3; /* Round to dword boundary. */
735 dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
736 memset(dev, 0, alloc_size);
737 if (sizeof_priv)
738 dev->priv = (void *) (dev + 1);
739 dev->name = sizeof_priv + (char *)(dev + 1);
740 new_device = 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;
749 break;
752 fc_setup(dev);
753 if (new_device) {
754 rtnl_lock();
755 register_netdevice(dev);
756 rtnl_unlock();
758 return dev;
761 void fc_freedev(struct net_device *dev)
763 int i;
764 for (i = 0; i < MAX_FC_CARDS; ++i) {
765 if (fcdev_index[i] == dev) {
766 fcdev_index[i] = NULL;
767 break;
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);
778 return -EIO;
780 return 0;
783 void unregister_fcdev(struct net_device *dev)
785 rtnl_lock();
786 unregister_netdevice(dev);
787 rtnl_unlock();
788 fc_freedev(dev);
791 #endif /* CONFIG_NET_FC */
794 * Local variables:
795 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
796 * version-control: t
797 * kept-new-versions: 5
798 * End: