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

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