Update ia64 patch to 2.5.69-030521, throwing away the parts included
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / sn / io / drivers / ifconfig_net.c
1 /* $Id: ifconfig_net.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
2  *
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  *  ifconfig_net - SGI's Persistent Network Device names.
8  *
9  * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All rights reserved.
10  */
11
12 #include <linux/types.h>
13 #include <linux/config.h>
14 #include <linux/slab.h>
15 #include <linux/ctype.h>
16 #include <linux/module.h>
17 #include <linux/init.h>
18
19 #include <linux/pci.h>
20 #include <linux/netdevice.h>
21 #include <linux/etherdevice.h>
22 #include <linux/skbuff.h>
23
24 #include <asm/sn/sgi.h>
25 #include <linux/devfs_fs.h>
26 #include <linux/devfs_fs_kernel.h>
27 #include <asm/io.h>
28 #include <asm/sn/iograph.h>
29 #include <asm/sn/invent.h>
30 #include <asm/sn/hcl.h>
31 #include <asm/sn/labelcl.h>
32 #include <asm/sn/ifconfig_net.h>
33
34 #define SGI_IFCONFIG_NET "SGI-PERSISTENT NETWORK DEVICE NAME DRIVER"
35 #define SGI_IFCONFIG_NET_VERSION "1.0"
36
37 /*
38  * Some Global definitions.
39  */
40 static devfs_handle_t ifconfig_net_handle;
41 static unsigned long ifconfig_net_debug;
42
43 /*
44  * ifconfig_net_open - Opens the special device node "/devhw/.ifconfig_net".
45  */
46 static int ifconfig_net_open(struct inode * inode, struct file * filp)
47 {
48         if (ifconfig_net_debug) {
49                 printk("ifconfig_net_open called.\n");
50         }
51
52         return(0);
53
54 }
55
56 /*
57  * ifconfig_net_close - Closes the special device node "/devhw/.ifconfig_net".
58  */
59 static int ifconfig_net_close(struct inode * inode, struct file * filp)
60 {
61
62         if (ifconfig_net_debug) {
63                 printk("ifconfig_net_close called.\n");
64         }
65
66         return(0);
67 }
68
69 /*
70  * assign_ifname - Assign the next available interface name from the persistent list.
71  */
72 void
73 assign_ifname(struct net_device *dev,
74                   struct ifname_num *ifname_num)
75
76 {
77
78         /*
79          * Handle eth devices.
80          */
81         if ( (memcmp(dev->name, "eth", 3) == 0) ) {
82                 if (ifname_num->next_eth != -1) {
83                         /*
84                          * Assign it the next available eth interface number. 
85                          */
86                         memset(dev->name, 0, strlen(dev->name));
87                         sprintf(dev->name, "eth%d", (int)ifname_num->next_eth);
88                         ifname_num->next_eth++;
89                 } 
90
91                 return;
92         }
93
94         /*
95          * Handle fddi devices.
96          */
97         if ( (memcmp(dev->name, "fddi", 4) == 0) ) {
98                 if (ifname_num->next_fddi != -1) {
99                         /*
100                          * Assign it the next available fddi interface number.
101                          */
102                         memset(dev->name, 0, strlen(dev->name));
103                         sprintf(dev->name, "fddi%d", (int)ifname_num->next_fddi);
104                         ifname_num->next_fddi++;
105                 }
106
107                 return;
108         }
109
110         /*
111          * Handle hip devices.
112          */
113         if ( (memcmp(dev->name, "hip", 3) == 0) ) {
114                 if (ifname_num->next_hip != -1) {
115                         /*
116                          * Assign it the next available hip interface number.
117                          */
118                         memset(dev->name, 0, strlen(dev->name));
119                         sprintf(dev->name, "hip%d", (int)ifname_num->next_hip);
120                         ifname_num->next_hip++;
121                 }
122
123                 return;
124         }
125
126         /*
127          * Handle tr devices.
128          */
129         if ( (memcmp(dev->name, "tr", 2) == 0) ) {
130                 if (ifname_num->next_tr != -1) {
131                         /*
132                          * Assign it the next available tr interface number.
133                          */
134                         memset(dev->name, 0, strlen(dev->name));
135                         sprintf(dev->name, "tr%d", (int)ifname_num->next_tr);
136                         ifname_num->next_tr++;
137                 }
138
139                 return;
140         }
141
142         /*
143          * Handle fc devices.
144          */
145         if ( (memcmp(dev->name, "fc", 2) == 0) ) {
146                 if (ifname_num->next_fc != -1) {
147                         /*
148                          * Assign it the next available fc interface number.
149                          */
150                         memset(dev->name, 0, strlen(dev->name));
151                         sprintf(dev->name, "fc%d", (int)ifname_num->next_fc);
152                         ifname_num->next_fc++;
153                 }
154
155                 return;
156         }
157 }
158
159 /*
160  * find_persistent_ifname: Returns the entry that was seen in previous boot.
161  */
162 struct ifname_MAC *
163 find_persistent_ifname(struct net_device *dev,
164         struct ifname_MAC *ifname_MAC)
165
166 {
167
168         while (ifname_MAC->addr_len) {
169                 if (memcmp(dev->dev_addr, ifname_MAC->dev_addr, dev->addr_len) == 0)
170                         return(ifname_MAC);
171
172                 ifname_MAC++;
173         }
174
175         return(NULL);
176 }
177
178 /*
179  * ifconfig_net_ioctl: ifconfig_net driver ioctl interface.
180  */
181 static int ifconfig_net_ioctl(struct inode * inode, struct file * file,
182         unsigned int cmd, unsigned long arg)
183 {
184
185         extern struct net_device *__dev_get_by_name(const char *);
186 #ifdef CONFIG_NET
187         struct net_device *dev;
188         struct ifname_MAC *found;
189         char temp[64];
190 #endif
191         struct ifname_MAC *ifname_MAC;
192         struct ifname_MAC *new_devices, *temp_new_devices;
193         struct ifname_num *ifname_num;
194         unsigned long size;
195
196
197         if (ifconfig_net_debug) {
198                 printk("HCL: hcl_ioctl called.\n");
199         }
200
201         /*
202          * Read in the header and see how big of a buffer we really need to 
203          * allocate.
204          */
205         ifname_num = (struct ifname_num *) kmalloc(sizeof(struct ifname_num), 
206                         GFP_KERNEL);
207         copy_from_user( ifname_num, (char *) arg, sizeof(struct ifname_num));
208         size = ifname_num->size;
209         kfree(ifname_num);
210         ifname_num = (struct ifname_num *) kmalloc(size, GFP_KERNEL);
211         ifname_MAC = (struct ifname_MAC *) ((char *)ifname_num + (sizeof(struct ifname_num)) );
212
213         copy_from_user( ifname_num, (char *) arg, size);
214         new_devices =  kmalloc(size - sizeof(struct ifname_num), GFP_KERNEL);
215         temp_new_devices = new_devices;
216
217         memset(new_devices, 0, size - sizeof(struct ifname_num));
218
219 #ifdef CONFIG_NET
220         /*
221          * Go through the net device entries and make them persistent!
222          */
223         for (dev = dev_base; dev != NULL; dev = dev->next) {
224                 /*
225                  * Skip NULL entries or "lo"
226                  */
227                 if ( (dev->addr_len == 0) || ( !strncmp(dev->name, "lo", strlen(dev->name))) ){
228                         continue;
229                 }
230
231                 /*
232                  * See if we have a persistent interface name for this device.
233                  */
234                 found = NULL;
235                 found = find_persistent_ifname(dev, ifname_MAC);
236                 if (found) {
237                         strcpy(dev->name, found->name);
238                 } else {
239                         /* Never seen this before .. */
240                         assign_ifname(dev, ifname_num);
241
242                         /* 
243                          * Save the information for the next boot.
244                          */
245                         sprintf(temp,"%s %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
246                                 dev->dev_addr[0],  dev->dev_addr[1],  dev->dev_addr[2],
247                                 dev->dev_addr[3],  dev->dev_addr[4],  dev->dev_addr[5]);
248                         strcpy(temp_new_devices->name, dev->name);
249                         temp_new_devices->addr_len = dev->addr_len;
250                         memcpy(temp_new_devices->dev_addr, dev->dev_addr, dev->addr_len);
251                         temp_new_devices++;
252                 }
253                 
254         }
255 #endif
256
257         /*
258          * Copy back to the User Buffer area any new devices encountered.
259          */
260         copy_to_user((char *)arg + (sizeof(struct ifname_num)), new_devices, 
261                         size - sizeof(struct ifname_num));
262
263         return(0);
264
265 }
266
267 struct file_operations ifconfig_net_fops = {
268         ioctl:ifconfig_net_ioctl,       /* ioctl */
269         open:ifconfig_net_open,         /* open */
270         release:ifconfig_net_close      /* release */
271 };
272
273
274 /*
275  * init_ifconfig_net() - Boot time initialization.  Ensure that it is called 
276  *      after devfs has been initialized.
277  *
278  */
279 #ifdef MODULE
280 int init_module (void)
281 #else
282 int __init init_ifconfig_net(void)
283 #endif
284 {
285         ifconfig_net_handle = NULL;
286         ifconfig_net_handle = hwgraph_register(hwgraph_root, ".ifconfig_net",
287                         0, 0,
288                         0, 0,
289                         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
290                         &ifconfig_net_fops, NULL);
291
292         if (ifconfig_net_handle == NULL) {
293                 panic("Unable to create SGI PERSISTENT NETWORK DEVICE Name Driver.\n");
294         }
295
296         return(0);
297
298 }