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, struct sockaddr *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 136 {
 137         if(dev->start)
 138                 return -EBUSY;
 139         memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
 140         return 0;
 141 }
 142 
 143 void ether_setup(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145         int i;
 146         /* Fill in the fields of the device structure with ethernet-generic values.
 147            This should be in a common file instead of per-driver.  */
 148         for (i = 0; i < DEV_NUMBUFFS; i++)
 149                 skb_queue_head_init(&dev->buffs[i]);
 150 
 151         /* register boot-defined "eth" devices */
 152         if (dev->name && (strncmp(dev->name, "eth", 3) == 0)) {
 153                 i = simple_strtoul(dev->name + 3, NULL, 0);
 154                 if (ethdev_index[i] == NULL) {
 155                         ethdev_index[i] = dev;
 156                 }
 157                 else if (dev != ethdev_index[i]) {
 158                         /* Really shouldn't happen! */
 159                         printk("ether_setup: Ouch! Someone else took %s\n",
 160                                 dev->name);
 161                 }
 162         }
 163 
 164         dev->hard_header        = eth_header;
 165         dev->rebuild_header = eth_rebuild_header;
 166         dev->set_mac_address = eth_mac_addr;
 167         dev->header_cache = eth_header_cache;
 168 
 169         dev->type               = ARPHRD_ETHER;
 170         dev->hard_header_len = ETH_HLEN;
 171         dev->mtu                = 1500; /* eth_mtu */
 172         dev->addr_len   = ETH_ALEN;
 173         for (i = 0; i < ETH_ALEN; i++) {
 174                 dev->broadcast[i]=0xff;
 175         }
 176 
 177         /* New-style flags. */
 178         dev->flags              = IFF_BROADCAST|IFF_MULTICAST;
 179         dev->family             = AF_INET;
 180         dev->pa_addr    = 0;
 181         dev->pa_brdaddr = 0;
 182         dev->pa_mask    = 0;
 183         dev->pa_alen    = 4;
 184 }
 185 
 186 #ifdef CONFIG_TR
 187 
 188 void tr_setup(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190         int i;
 191         /* Fill in the fields of the device structure with ethernet-generic values.
 192            This should be in a common file instead of per-driver.  */
 193         for (i = 0; i < DEV_NUMBUFFS; i++)
 194                 skb_queue_head_init(&dev->buffs[i]);
 195 
 196         dev->hard_header        = tr_header;
 197         dev->rebuild_header = tr_rebuild_header;
 198 
 199         dev->type               = ARPHRD_IEEE802;
 200         dev->hard_header_len = TR_HLEN;
 201         dev->mtu                = 2000; /* bug in fragmenter...*/
 202         dev->addr_len   = TR_ALEN;
 203         for (i = 0; i < TR_ALEN; i++) {
 204                 dev->broadcast[i]=0xff;
 205         }
 206 
 207         /* New-style flags. */
 208         dev->flags              = IFF_BROADCAST;
 209         dev->family             = AF_INET;
 210         dev->pa_addr    = 0;
 211         dev->pa_brdaddr = 0;
 212         dev->pa_mask    = 0;
 213         dev->pa_alen    = 4;
 214 }
 215 
 216 #endif
 217 
 218 int ether_config(struct device *dev, struct ifmap *map)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220         if (map->mem_start != (u_long)(-1))
 221                 dev->mem_start = map->mem_start;
 222         if (map->mem_end != (u_long)(-1))
 223                 dev->mem_end = map->mem_end;
 224         if (map->base_addr != (u_short)(-1))
 225                 dev->base_addr = map->base_addr;
 226         if (map->irq != (u_char)(-1))
 227                 dev->irq = map->irq;
 228         if (map->dma != (u_char)(-1))
 229                 dev->dma = map->dma;
 230         if (map->port != (u_char)(-1))
 231                 dev->if_port = map->port;
 232         return 0;
 233 }
 234 
 235 int register_netdev(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 236 {
 237         struct device *d = dev_base;
 238         unsigned long flags;
 239         int i=MAX_ETH_CARDS;
 240 
 241         save_flags(flags);
 242         cli();
 243 
 244         if (dev && dev->init) {
 245                 if (dev->name &&
 246                         ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
 247                         for (i = 0; i < MAX_ETH_CARDS; ++i)
 248                                 if (ethdev_index[i] == NULL) {
 249                                         sprintf(dev->name, "eth%d", i);
 250                                         printk("loading device '%s'...\n", dev->name);
 251                                         ethdev_index[i] = dev;
 252                                         break;
 253                                 }
 254                 }
 255 
 256                 if (dev->init(dev) != 0) {
 257                     if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL;
 258                         restore_flags(flags);
 259                         return -EIO;
 260                 }
 261 
 262                 /* Add device to end of chain */
 263                 if (dev_base) {
 264                         while (d->next)
 265                                 d = d->next;
 266                         d->next = dev;
 267                 }
 268                 else
 269                         dev_base = dev;
 270                 dev->next = NULL;
 271         }
 272         restore_flags(flags);
 273         return 0;
 274 }
 275 
 276 void unregister_netdev(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 277 {
 278         struct device *d = dev_base;
 279         unsigned long flags;
 280         int i;
 281 
 282         save_flags(flags);
 283         cli();
 284 
 285         if (dev == NULL) 
 286         {
 287                 printk("was NULL\n");
 288                 restore_flags(flags);
 289                 return;
 290         }
 291         /* else */
 292         if (dev->start)
 293                 printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
 294         if (dev_base == dev)
 295                 dev_base = dev->next;
 296         else 
 297         {
 298                 while (d && (d->next != dev))
 299                         d = d->next;
 300                         
 301                 if (d && (d->next == dev)) 
 302                 {
 303                         d->next = dev->next;
 304                 }
 305                 else 
 306                 {
 307                         printk("unregister_netdev: '%s' not found\n", dev->name);
 308                         restore_flags(flags);
 309                         return;
 310                 }
 311         }
 312         for (i = 0; i < MAX_ETH_CARDS; ++i) 
 313         {
 314                 if (ethdev_index[i] == dev) 
 315                 {
 316                         ethdev_index[i] = NULL;
 317                         break;
 318                 }
 319         }
 320         /* You can i.e use a interfaces in a route though it is not up.
 321            We call close_dev (which is changed: it will down a device even if
 322            dev->flags==0 (but it will not call dev->stop if IFF_UP
 323            is not set).
 324            This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev),
 325            dev_mc_discard(dev), ....
 326         */
 327         dev_close(dev);
 328 
 329         restore_flags(flags);
 330 }
 331 
 332 
 333 
 334 /*
 335  * Local variables:
 336  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
 337  *  version-control: t
 338  *  kept-new-versions: 5
 339  *  tab-width: 4
 340  * End:
 341  */

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