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. ether_config
  5. register_netdev
  6. unregister_netdev

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

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