|
|
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: printk("ether_setup: Ouch! Someone else took %s\n", ! 192: dev->name); ! 193: } ! 194: } ! 195: ! 196: dev->change_mtu = eth_change_mtu; ! 197: dev->hard_header = eth_header; ! 198: dev->rebuild_header = eth_rebuild_header; ! 199: dev->set_mac_address = eth_mac_addr; ! 200: dev->header_cache_bind = eth_header_cache_bind; ! 201: dev->header_cache_update= eth_header_cache_update; ! 202: ! 203: dev->type = ARPHRD_ETHER; ! 204: dev->hard_header_len = ETH_HLEN; ! 205: dev->mtu = 1500; /* eth_mtu */ ! 206: dev->addr_len = ETH_ALEN; ! 207: dev->tx_queue_len = 100; /* Ethernet wants good queues */ ! 208: ! 209: memset(dev->broadcast,0xFF, ETH_ALEN); ! 210: ! 211: /* New-style flags. */ ! 212: dev->flags = IFF_BROADCAST|IFF_MULTICAST; ! 213: dev->family = AF_INET; ! 214: dev->pa_addr = 0; ! 215: dev->pa_brdaddr = 0; ! 216: dev->pa_mask = 0; ! 217: dev->pa_alen = 4; ! 218: } ! 219: ! 220: #ifdef CONFIG_TR ! 221: ! 222: void tr_setup(struct device *dev) ! 223: { ! 224: int i; ! 225: /* Fill in the fields of the device structure with ethernet-generic values. ! 226: This should be in a common file instead of per-driver. */ ! 227: for (i = 0; i < DEV_NUMBUFFS; i++) ! 228: skb_queue_head_init(&dev->buffs[i]); ! 229: ! 230: dev->hard_header = tr_header; ! 231: dev->rebuild_header = tr_rebuild_header; ! 232: ! 233: dev->type = ARPHRD_IEEE802; ! 234: dev->hard_header_len = TR_HLEN; ! 235: dev->mtu = 2000; /* bug in fragmenter...*/ ! 236: dev->addr_len = TR_ALEN; ! 237: dev->tx_queue_len = 100; /* Long queues on tr */ ! 238: ! 239: memset(dev->broadcast,0xFF, TR_ALEN); ! 240: ! 241: /* New-style flags. */ ! 242: dev->flags = IFF_BROADCAST; ! 243: dev->family = AF_INET; ! 244: dev->pa_addr = 0; ! 245: dev->pa_brdaddr = 0; ! 246: dev->pa_mask = 0; ! 247: dev->pa_alen = 4; ! 248: } ! 249: ! 250: #endif ! 251: ! 252: #ifdef CONFIG_FDDI ! 253: ! 254: void fddi_setup(struct device *dev) ! 255: { ! 256: int i; ! 257: ! 258: /* ! 259: * Fill in the fields of the device structure with FDDI-generic values. ! 260: * This should be in a common file instead of per-driver. ! 261: */ ! 262: for (i=0; i < DEV_NUMBUFFS; i++) ! 263: skb_queue_head_init(&dev->buffs[i]); ! 264: ! 265: dev->change_mtu = fddi_change_mtu; ! 266: dev->hard_header = fddi_header; ! 267: dev->rebuild_header = fddi_rebuild_header; ! 268: ! 269: dev->type = ARPHRD_FDDI; ! 270: dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */ ! 271: dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */ ! 272: dev->addr_len = FDDI_K_ALEN; ! 273: dev->tx_queue_len = 100; /* Long queues on FDDI */ ! 274: ! 275: memset(dev->broadcast, 0xFF, FDDI_K_ALEN); ! 276: ! 277: /* New-style flags */ ! 278: dev->flags = IFF_BROADCAST | IFF_MULTICAST; ! 279: dev->family = AF_INET; ! 280: dev->pa_addr = 0; ! 281: dev->pa_brdaddr = 0; ! 282: dev->pa_mask = 0; ! 283: dev->pa_alen = 4; ! 284: return; ! 285: } ! 286: ! 287: #endif ! 288: ! 289: int ether_config(struct device *dev, struct ifmap *map) ! 290: { ! 291: if (map->mem_start != (u_long)(-1)) ! 292: dev->mem_start = map->mem_start; ! 293: if (map->mem_end != (u_long)(-1)) ! 294: dev->mem_end = map->mem_end; ! 295: if (map->base_addr != (u_short)(-1)) ! 296: dev->base_addr = map->base_addr; ! 297: if (map->irq != (u_char)(-1)) ! 298: dev->irq = map->irq; ! 299: if (map->dma != (u_char)(-1)) ! 300: dev->dma = map->dma; ! 301: if (map->port != (u_char)(-1)) ! 302: dev->if_port = map->port; ! 303: return 0; ! 304: } ! 305: ! 306: int register_netdev(struct device *dev) ! 307: { ! 308: struct device *d = dev_base; ! 309: unsigned long flags; ! 310: int i=MAX_ETH_CARDS; ! 311: ! 312: save_flags(flags); ! 313: cli(); ! 314: ! 315: if (dev && dev->init) { ! 316: if (dev->name && ! 317: ((dev->name[0] == '\0') || (dev->name[0] == ' '))) { ! 318: for (i = 0; i < MAX_ETH_CARDS; ++i) ! 319: if (ethdev_index[i] == NULL) { ! 320: sprintf(dev->name, "eth%d", i); ! 321: /* printk("loading device '%s'...\n", dev->name);*/ ! 322: ethdev_index[i] = dev; ! 323: break; ! 324: } ! 325: } ! 326: ! 327: sti(); /* device probes assume interrupts enabled */ ! 328: if (dev->init(dev) != 0) { ! 329: if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL; ! 330: restore_flags(flags); ! 331: return -EIO; ! 332: } ! 333: cli(); ! 334: ! 335: /* Add device to end of chain */ ! 336: if (dev_base) { ! 337: while (d->next) ! 338: d = d->next; ! 339: d->next = dev; ! 340: } ! 341: else ! 342: dev_base = dev; ! 343: dev->next = NULL; ! 344: } ! 345: restore_flags(flags); ! 346: return 0; ! 347: } ! 348: ! 349: void unregister_netdev(struct device *dev) ! 350: { ! 351: struct device *d = dev_base; ! 352: unsigned long flags; ! 353: int i; ! 354: ! 355: save_flags(flags); ! 356: cli(); ! 357: ! 358: if (dev == NULL) ! 359: { ! 360: printk("was NULL\n"); ! 361: restore_flags(flags); ! 362: return; ! 363: } ! 364: /* else */ ! 365: if (dev->start) ! 366: printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name); ! 367: ! 368: /* ! 369: * must jump over main_device+aliases ! 370: * avoid alias devices unregistration so that only ! 371: * net_alias module manages them ! 372: */ ! 373: #ifdef CONFIG_NET_ALIAS ! 374: if (dev_base == dev) ! 375: dev_base = net_alias_nextdev(dev); ! 376: else ! 377: { ! 378: while(d && (net_alias_nextdev(d) != dev)) /* skip aliases */ ! 379: d = net_alias_nextdev(d); ! 380: ! 381: if (d && (net_alias_nextdev(d) == dev)) ! 382: { ! 383: /* ! 384: * Critical: Bypass by consider devices as blocks (maindev+aliases) ! 385: */ ! 386: net_alias_nextdev_set(d, net_alias_nextdev(dev)); ! 387: } ! 388: #else ! 389: if (dev_base == dev) ! 390: dev_base = dev->next; ! 391: else ! 392: { ! 393: while (d && (d->next != dev)) ! 394: d = d->next; ! 395: ! 396: if (d && (d->next == dev)) ! 397: { ! 398: d->next = dev->next; ! 399: } ! 400: #endif ! 401: else ! 402: { ! 403: printk("unregister_netdev: '%s' not found\n", dev->name); ! 404: restore_flags(flags); ! 405: return; ! 406: } ! 407: } ! 408: for (i = 0; i < MAX_ETH_CARDS; ++i) ! 409: { ! 410: if (ethdev_index[i] == dev) ! 411: { ! 412: ethdev_index[i] = NULL; ! 413: break; ! 414: } ! 415: } ! 416: ! 417: restore_flags(flags); ! 418: ! 419: /* ! 420: * You can i.e use a interfaces in a route though it is not up. ! 421: * We call close_dev (which is changed: it will down a device even if ! 422: * dev->flags==0 (but it will not call dev->stop if IFF_UP ! 423: * is not set). ! 424: * This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev), ! 425: * dev_mc_discard(dev), .... ! 426: */ ! 427: ! 428: dev_close(dev); ! 429: } ! 430: ! 431: ! 432: /* ! 433: * Local variables: ! 434: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c" ! 435: * version-control: t ! 436: * kept-new-versions: 5 ! 437: * tab-width: 4 ! 438: * End: ! 439: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.