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