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

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