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/if_arp.h>
33 #include <linux/string.h>
34 #include <linux/netdevice.h>
35 #include <linux/etherdevice.h>
36 #include <linux/trdevice.h>
37
38 /* The network devices currently exist only in the socket namespace, so these
39 entries are unused. The only ones that make sense are
40 open start the ethercard
41 close stop the ethercard
42 ioctl To get statistics, perhaps set the interface port (AUI, BNC, etc.)
43 One can also imagine getting raw packets using
44 read & write
45 but this is probably better handled by a raw packet socket.
46
47 Given that almost all of these functions are handled in the current
48 socket-based scheme, putting ethercard devices in /dev/ seems pointless.
49
50 [Removed all support for /dev network devices. When someone adds
51 streams then by magic we get them, but otherwise they are un-needed
52 and a space waste]
53 */
54
55 /* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */
56 #define MAX_ETH_CARDS 16 /* same as the number if irq's in irq2dev[] */
57 static struct device *ethdev_index[MAX_ETH_CARDS];
58
59
60 /* Fill in the fields of the device structure with ethernet-generic values.
61
62 If no device structure is passed, a new one is constructed, complete with
63 a SIZEOF_PRIVATE private data area.
64
65 If an empty string area is passed as dev->name, or a new structure is made,
66 a new name string is constructed. The passed string area should be 8 bytes
67 long.
68 */
69
70 struct device *
71 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)
*/
72 {
73 int new_device = 0;
74 int i;
75
76 /* Use an existing correctly named device in Space.c:dev_base. */
77 if (dev == NULL) {
78 int alloc_size = sizeof(struct device) + sizeof("eth%d ")
79 + sizeof_priv + 3;
80 struct device *cur_dev;
81 char pname[8]; /* Putative name for the device. */
82
83 for (i = 0; i < MAX_ETH_CARDS; ++i)
84 if (ethdev_index[i] == NULL) {
85 sprintf(pname, "eth%d", i);
86 for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
87 if (strcmp(pname, cur_dev->name) == 0) {
88 dev = cur_dev;
89 dev->init = NULL;
90 sizeof_priv = (sizeof_priv + 3) & ~3;
91 dev->priv = sizeof_priv
92 ? kmalloc(sizeof_priv, GFP_KERNEL)
93 : NULL;
94 if (dev->priv) memset(dev->priv, 0, sizeof_priv);
95 goto found;
96 }
97 }
98
99 alloc_size &= ~3; /* Round to dword boundary. */
100
101 dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
102 memset(dev, 0, alloc_size);
103 if (sizeof_priv)
104 dev->priv = (void *) (dev + 1);
105 dev->name = sizeof_priv + (char *)(dev + 1);
106 new_device = 1;
107 }
108
109 found: /* From the double loop above. */
110
111 if (dev->name &&
112 ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
113 for (i = 0; i < MAX_ETH_CARDS; ++i)
114 if (ethdev_index[i] == NULL) {
115 sprintf(dev->name, "eth%d", i);
116 ethdev_index[i] = dev;
117 break;
118 }
119 }
120
121 ether_setup(dev); /* Hmmm, should this be called here? */
122
123 if (new_device) {
124 /* Append the device to the device queue. */
125 struct device **old_devp = &dev_base;
126 while ((*old_devp)->next)
127 old_devp = & (*old_devp)->next;
128 (*old_devp)->next = dev;
129 dev->next = 0;
130 }
131 return dev;
132 }
133
134
135 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)
*/
136 {
137 struct sockaddr *addr=p;
138 if(dev->start)
139 return -EBUSY;
140 memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
141 return 0;
142 }
143
144 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)
*/
145 {
146 int i;
147 /* Fill in the fields of the device structure with ethernet-generic values.
148 This should be in a common file instead of per-driver. */
149 for (i = 0; i < DEV_NUMBUFFS; i++)
150 skb_queue_head_init(&dev->buffs[i]);
151
152 /* register boot-defined "eth" devices */
153 if (dev->name && (strncmp(dev->name, "eth", 3) == 0)) {
154 i = simple_strtoul(dev->name + 3, NULL, 0);
155 if (ethdev_index[i] == NULL) {
156 ethdev_index[i] = dev;
157 }
158 else if (dev != ethdev_index[i]) {
159 /* Really shouldn't happen! */
160 printk("ether_setup: Ouch! Someone else took %s\n",
161 dev->name);
162 }
163 }
164
165 dev->hard_header = eth_header;
166 dev->rebuild_header = eth_rebuild_header;
167 dev->set_mac_address = eth_mac_addr;
168 dev->header_cache_bind = eth_header_cache_bind;
169 dev->header_cache_update = eth_header_cache_update;
170
171 dev->type = ARPHRD_ETHER;
172 dev->hard_header_len = ETH_HLEN;
173 dev->mtu = 1500; /* eth_mtu */
174 dev->addr_len = ETH_ALEN;
175 for (i = 0; i < ETH_ALEN; i++) {
176 dev->broadcast[i]=0xff;
177 }
178
179 /* New-style flags. */
180 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
181 dev->family = AF_INET;
182 dev->pa_addr = 0;
183 dev->pa_brdaddr = 0;
184 dev->pa_mask = 0;
185 dev->pa_alen = 4;
186 }
187
188 #ifdef CONFIG_TR
189
190 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)
*/
191 {
192 int i;
193 /* Fill in the fields of the device structure with ethernet-generic values.
194 This should be in a common file instead of per-driver. */
195 for (i = 0; i < DEV_NUMBUFFS; i++)
196 skb_queue_head_init(&dev->buffs[i]);
197
198 dev->hard_header = tr_header;
199 dev->rebuild_header = tr_rebuild_header;
200
201 dev->type = ARPHRD_IEEE802;
202 dev->hard_header_len = TR_HLEN;
203 dev->mtu = 2000; /* bug in fragmenter...*/
204 dev->addr_len = TR_ALEN;
205 for (i = 0; i < TR_ALEN; i++) {
206 dev->broadcast[i]=0xff;
207 }
208
209 /* New-style flags. */
210 dev->flags = IFF_BROADCAST;
211 dev->family = AF_INET;
212 dev->pa_addr = 0;
213 dev->pa_brdaddr = 0;
214 dev->pa_mask = 0;
215 dev->pa_alen = 4;
216 }
217
218 #endif
219
220 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)
*/
221 {
222 if (map->mem_start != (u_long)(-1))
223 dev->mem_start = map->mem_start;
224 if (map->mem_end != (u_long)(-1))
225 dev->mem_end = map->mem_end;
226 if (map->base_addr != (u_short)(-1))
227 dev->base_addr = map->base_addr;
228 if (map->irq != (u_char)(-1))
229 dev->irq = map->irq;
230 if (map->dma != (u_char)(-1))
231 dev->dma = map->dma;
232 if (map->port != (u_char)(-1))
233 dev->if_port = map->port;
234 return 0;
235 }
236
237 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)
*/
238 {
239 struct device *d = dev_base;
240 unsigned long flags;
241 int i=MAX_ETH_CARDS;
242
243 save_flags(flags);
244 cli();
245
246 if (dev && dev->init) {
247 if (dev->name &&
248 ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
249 for (i = 0; i < MAX_ETH_CARDS; ++i)
250 if (ethdev_index[i] == NULL) {
251 sprintf(dev->name, "eth%d", i);
252 printk("loading device '%s'...\n", dev->name);
253 ethdev_index[i] = dev;
254 break;
255 }
256 }
257
258 if (dev->init(dev) != 0) {
259 if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL;
260 restore_flags(flags);
261 return -EIO;
262 }
263
264 /* Add device to end of chain */
265 if (dev_base) {
266 while (d->next)
267 d = d->next;
268 d->next = dev;
269 }
270 else
271 dev_base = dev;
272 dev->next = NULL;
273 }
274 restore_flags(flags);
275 return 0;
276 }
277
278 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)
*/
279 {
280 struct device *d = dev_base;
281 unsigned long flags;
282 int i;
283
284 save_flags(flags);
285 cli();
286
287 if (dev == NULL)
288 {
289 printk("was NULL\n");
290 restore_flags(flags);
291 return;
292 }
293 /* else */
294 if (dev->start)
295 printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
296 if (dev_base == dev)
297 dev_base = dev->next;
298 else
299 {
300 while (d && (d->next != dev))
301 d = d->next;
302
303 if (d && (d->next == dev))
304 {
305 d->next = dev->next;
306 }
307 else
308 {
309 printk("unregister_netdev: '%s' not found\n", dev->name);
310 restore_flags(flags);
311 return;
312 }
313 }
314 for (i = 0; i < MAX_ETH_CARDS; ++i)
315 {
316 if (ethdev_index[i] == dev)
317 {
318 ethdev_index[i] = NULL;
319 break;
320 }
321 }
322 /* You can i.e use a interfaces in a route though it is not up.
323 We call close_dev (which is changed: it will down a device even if
324 dev->flags==0 (but it will not call dev->stop if IFF_UP
325 is not set).
326 This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev),
327 dev_mc_discard(dev), ....
328 */
329 dev_close(dev);
330
331 restore_flags(flags);
332 }
333
334
335
336 /*
337 * Local variables:
338 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
339 * version-control: t
340 * kept-new-versions: 5
341 * tab-width: 4
342 * End:
343 */