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 becker@cesdis.gsfc.nasa.gov 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 <bj0rn@blox.se>:
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/string.h>
33 #include <linux/netdevice.h>
34 #include <linux/etherdevice.h>
35 #include <linux/trdevice.h>
36 #include <linux/if_arp.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
63 /* Fill in the fields of the device structure with ethernet-generic values.
64
65 If no device structure is passed, a new one is constructed, complete with
66 a SIZEOF_PRIVATE private data area.
67
68 If an empty string area is passed as dev->name, or a new structure is made,
69 a new name string is constructed. The passed string area should be 8 bytes
70 long.
71 */
72
73 struct device *
74 init_etherdev(struct device *dev, int sizeof_priv)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
75 {
76 int new_device = 0;
77 int i;
78
79 /* Use an existing correctly named device in Space.c:dev_base. */
80 if (dev == NULL) {
81 int alloc_size = sizeof(struct device) + sizeof("eth%d ")
82 + sizeof_priv + 3;
83 struct device *cur_dev;
84 char pname[8]; /* Putative name for the device. */
85
86 for (i = 0; i < MAX_ETH_CARDS; ++i)
87 if (ethdev_index[i] == NULL) {
88 sprintf(pname, "eth%d", i);
89 for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
90 if (strcmp(pname, cur_dev->name) == 0) {
91 dev = cur_dev;
92 dev->init = NULL;
93 sizeof_priv = (sizeof_priv + 3) & ~3;
94 dev->priv = sizeof_priv
95 ? kmalloc(sizeof_priv, GFP_KERNEL)
96 : NULL;
97 if (dev->priv) memset(dev->priv, 0, sizeof_priv);
98 goto found;
99 }
100 }
101
102 alloc_size &= ~3; /* Round to dword boundary. */
103
104 dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
105 memset(dev, 0, alloc_size);
106 if (sizeof_priv)
107 dev->priv = (void *) (dev + 1);
108 dev->name = sizeof_priv + (char *)(dev + 1);
109 new_device = 1;
110 }
111
112 found: /* From the double loop above. */
113
114 if (dev->name &&
115 ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
116 for (i = 0; i < MAX_ETH_CARDS; ++i)
117 if (ethdev_index[i] == NULL) {
118 sprintf(dev->name, "eth%d", i);
119 ethdev_index[i] = dev;
120 break;
121 }
122 }
123
124 ether_setup(dev); /* Hmmm, should this be called here? */
125
126 if (new_device) {
127 /* Append the device to the device queue. */
128 struct device **old_devp = &dev_base;
129 while ((*old_devp)->next)
130 old_devp = & (*old_devp)->next;
131 (*old_devp)->next = dev;
132 dev->next = 0;
133 }
134 return dev;
135 }
136
137
138 static int eth_mac_addr(struct device *dev, void *p)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
139 {
140 struct sockaddr *addr=p;
141 if(dev->start)
142 return -EBUSY;
143 memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
144 return 0;
145 }
146
147 void ether_setup(struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
148 {
149 int i;
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 printk("ether_setup: Ouch! Someone else took %s\n",
164 dev->name);
165 }
166 }
167
168 dev->hard_header = eth_header;
169 dev->rebuild_header = eth_rebuild_header;
170 dev->set_mac_address = eth_mac_addr;
171 dev->header_cache_bind = eth_header_cache_bind;
172 dev->header_cache_update= eth_header_cache_update;
173
174 dev->type = ARPHRD_ETHER;
175 dev->hard_header_len = ETH_HLEN;
176 dev->mtu = 1500; /* eth_mtu */
177 dev->addr_len = ETH_ALEN;
178 dev->tx_queue_len = 100; /* Ethernet wants good queues */
179
180 memset(dev->broadcast,0xFF, ETH_ALEN);
181
182 /* New-style flags. */
183 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
184 dev->family = AF_INET;
185 dev->pa_addr = 0;
186 dev->pa_brdaddr = 0;
187 dev->pa_mask = 0;
188 dev->pa_alen = 4;
189 }
190
191 #ifdef CONFIG_TR
192
193 void tr_setup(struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
194 {
195 int i;
196 /* Fill in the fields of the device structure with ethernet-generic values.
197 This should be in a common file instead of per-driver. */
198 for (i = 0; i < DEV_NUMBUFFS; i++)
199 skb_queue_head_init(&dev->buffs[i]);
200
201 dev->hard_header = tr_header;
202 dev->rebuild_header = tr_rebuild_header;
203
204 dev->type = ARPHRD_IEEE802;
205 dev->hard_header_len = TR_HLEN;
206 dev->mtu = 2000; /* bug in fragmenter...*/
207 dev->addr_len = TR_ALEN;
208 dev->tx_queue_len = 100; /* Long queues on tr */
209
210 memset(dev->broadcast,0xFF, TR_ALEN);
211
212 /* New-style flags. */
213 dev->flags = IFF_BROADCAST;
214 dev->family = AF_INET;
215 dev->pa_addr = 0;
216 dev->pa_brdaddr = 0;
217 dev->pa_mask = 0;
218 dev->pa_alen = 4;
219 }
220
221 #endif
222
223 int ether_config(struct device *dev, struct ifmap *map)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
224 {
225 if (map->mem_start != (u_long)(-1))
226 dev->mem_start = map->mem_start;
227 if (map->mem_end != (u_long)(-1))
228 dev->mem_end = map->mem_end;
229 if (map->base_addr != (u_short)(-1))
230 dev->base_addr = map->base_addr;
231 if (map->irq != (u_char)(-1))
232 dev->irq = map->irq;
233 if (map->dma != (u_char)(-1))
234 dev->dma = map->dma;
235 if (map->port != (u_char)(-1))
236 dev->if_port = map->port;
237 return 0;
238 }
239
240 int register_netdev(struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
241 {
242 struct device *d = dev_base;
243 unsigned long flags;
244 int i=MAX_ETH_CARDS;
245
246 save_flags(flags);
247 cli();
248
249 if (dev && dev->init) {
250 if (dev->name &&
251 ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
252 for (i = 0; i < MAX_ETH_CARDS; ++i)
253 if (ethdev_index[i] == NULL) {
254 sprintf(dev->name, "eth%d", i);
255 printk("loading device '%s'...\n", dev->name);
256 ethdev_index[i] = dev;
257 break;
258 }
259 }
260
261 sti(); /* device probes assume interrupts enabled */
262 if (dev->init(dev) != 0) {
263 if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL;
264 restore_flags(flags);
265 return -EIO;
266 }
267 cli();
268
269 /* Add device to end of chain */
270 if (dev_base) {
271 while (d->next)
272 d = d->next;
273 d->next = dev;
274 }
275 else
276 dev_base = dev;
277 dev->next = NULL;
278 }
279 restore_flags(flags);
280 return 0;
281 }
282
283 void unregister_netdev(struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
284 {
285 struct device *d = dev_base;
286 unsigned long flags;
287 int i;
288
289 save_flags(flags);
290 cli();
291
292 if (dev == NULL)
293 {
294 printk("was NULL\n");
295 restore_flags(flags);
296 return;
297 }
298 /* else */
299 if (dev->start)
300 printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
301
302 /*
303 * must jump over main_device+aliases
304 * avoid alias devices unregistration so that only
305 * net_alias module manages them
306 */
307 #ifdef CONFIG_NET_ALIAS
308 if (dev_base == dev)
309 dev_base = net_alias_nextdev(dev);
310 else
311 {
312 while(d && (net_alias_nextdev(d) != dev)) /* skip aliases */
313 d = net_alias_nextdev(d);
314
315 if (d && (net_alias_nextdev(d) == dev))
316 {
317 /*
318 * Critical: Bypass by consider devices as blocks (maindev+aliases)
319 */
320 net_alias_nextdev_set(d, net_alias_nextdev(dev));
321 }
322 #else
323 if (dev_base == dev)
324 dev_base = dev->next;
325 else
326 {
327 while (d && (d->next != dev))
328 d = d->next;
329
330 if (d && (d->next == dev))
331 {
332 d->next = dev->next;
333 }
334 #endif
335 else
336 {
337 printk("unregister_netdev: '%s' not found\n", dev->name);
338 restore_flags(flags);
339 return;
340 }
341 }
342 for (i = 0; i < MAX_ETH_CARDS; ++i)
343 {
344 if (ethdev_index[i] == dev)
345 {
346 ethdev_index[i] = NULL;
347 break;
348 }
349 }
350
351 restore_flags(flags);
352
353 /*
354 * You can i.e use a interfaces in a route though it is not up.
355 * We call close_dev (which is changed: it will down a device even if
356 * dev->flags==0 (but it will not call dev->stop if IFF_UP
357 * is not set).
358 * This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev),
359 * dev_mc_discard(dev), ....
360 */
361
362 dev_close(dev);
363 }
364
365
366 /*
367 * Local variables:
368 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
369 * version-control: t
370 * kept-new-versions: 5
371 * tab-width: 4
372 * End:
373 */