root/drivers/net/net_init.c

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

DEFINITIONS

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

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