|
|
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.