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

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