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