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/string.h>
  33 #include <linux/netdevice.h>
  34 #include <linux/etherdevice.h>
  35 #include <linux/trdevice.h>
  36 #include <linux/if_arp.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         dev->tx_queue_len       = 100;  /* Ethernet wants good queues */        
 179         
 180         memset(dev->broadcast,0xFF, ETH_ALEN);
 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         dev->tx_queue_len       = 100;  /* Long queues on tr */
 209         
 210         memset(dev->broadcast,0xFF, TR_ALEN);
 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                 sti();  /* device probes assume interrupts enabled */
 262                 if (dev->init(dev) != 0) {
 263                     if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL;
 264                         restore_flags(flags);
 265                         return -EIO;
 266                 }
 267                 cli();
 268 
 269                 /* Add device to end of chain */
 270                 if (dev_base) {
 271                         while (d->next)
 272                                 d = d->next;
 273                         d->next = dev;
 274                 }
 275                 else
 276                         dev_base = dev;
 277                 dev->next = NULL;
 278         }
 279         restore_flags(flags);
 280         return 0;
 281 }
 282 
 283 void unregister_netdev(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 284 {
 285         struct device *d = dev_base;
 286         unsigned long flags;
 287         int i;
 288 
 289         save_flags(flags);
 290         cli();
 291 
 292         if (dev == NULL) 
 293         {
 294                 printk("was NULL\n");
 295                 restore_flags(flags);
 296                 return;
 297         }
 298         /* else */
 299         if (dev->start)
 300                 printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
 301 
 302         /*
 303          *      must jump over main_device+aliases
 304          *      avoid alias devices unregistration so that only
 305          *      net_alias module manages them
 306          */
 307 #ifdef CONFIG_NET_ALIAS         
 308         if (dev_base == dev)
 309                 dev_base = net_alias_nextdev(dev);
 310         else
 311         {
 312                 while(d && (net_alias_nextdev(d) != dev)) /* skip aliases */
 313                         d = net_alias_nextdev(d);
 314           
 315                 if (d && (net_alias_nextdev(d) == dev))
 316                 {
 317                         /*
 318                          *      Critical: Bypass by consider devices as blocks (maindev+aliases)
 319                          */
 320                         net_alias_nextdev_set(d, net_alias_nextdev(dev)); 
 321                 }
 322 #else
 323         if (dev_base == dev)
 324                 dev_base = dev->next;
 325         else 
 326         {
 327                 while (d && (d->next != dev))
 328                         d = d->next;
 329                 
 330                 if (d && (d->next == dev)) 
 331                 {
 332                         d->next = dev->next;
 333                 }
 334 #endif
 335                 else 
 336                 {
 337                         printk("unregister_netdev: '%s' not found\n", dev->name);
 338                         restore_flags(flags);
 339                         return;
 340                 }
 341         }
 342         for (i = 0; i < MAX_ETH_CARDS; ++i) 
 343         {
 344                 if (ethdev_index[i] == dev) 
 345                 {
 346                         ethdev_index[i] = NULL;
 347                         break;
 348                 }
 349         }
 350 
 351         restore_flags(flags);
 352 
 353         /*
 354          *      You can i.e use a interfaces in a route though it is not up.
 355          *      We call close_dev (which is changed: it will down a device even if
 356          *      dev->flags==0 (but it will not call dev->stop if IFF_UP
 357          *      is not set).
 358          *      This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev),
 359          *      dev_mc_discard(dev), ....
 360          */
 361          
 362         dev_close(dev);
 363 }
 364 
 365 
 366 /*
 367  * Local variables:
 368  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
 369  *  version-control: t
 370  *  kept-new-versions: 5
 371  *  tab-width: 4
 372  * End:
 373  */

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