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