root/drivers/net/net_init.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_etherdev
  2. eth_mac_addr
  3. ether_setup
  4. tr_setup
  5. ether_config
  6. register_netdev
  7. unregister_netdev

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

/* [previous][next][first][last][top][bottom][index][help] */