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