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

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