1 /* $Id: ifconfig_net.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
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
7 * ifconfig_net - SGI's Persistent Network Device names.
9 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
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>
19 #include <linux/pci.h>
20 #include <linux/netdevice.h>
21 #include <linux/etherdevice.h>
22 #include <linux/skbuff.h>
24 #include <asm/sn/sgi.h>
25 #include <asm/uaccess.h>
26 #include <linux/devfs_fs.h>
27 #include <linux/devfs_fs_kernel.h>
29 #include <asm/sn/iograph.h>
30 #include <asm/sn/invent.h>
31 #include <asm/sn/hcl.h>
32 #include <asm/sn/labelcl.h>
33 #include <asm/sn/ifconfig_net.h>
35 #define SGI_IFCONFIG_NET "SGI-PERSISTENT NETWORK DEVICE NAME DRIVER"
36 #define SGI_IFCONFIG_NET_VERSION "1.0"
39 * Some Global definitions.
41 static vertex_hdl_t ifconfig_net_handle;
42 static unsigned long ifconfig_net_debug;
43 static struct ifname_MAC *new_devices;
44 static struct ifname_num *ifname_num;
48 * ifconfig_net_open - Opens the special device node "/devhw/.ifconfig_net".
50 static int ifconfig_net_open(struct inode * inode, struct file * filp)
52 if (ifconfig_net_debug) {
53 printk("ifconfig_net_open called.\n");
61 * ifconfig_net_close - Closes the special device node "/devhw/.ifconfig_net".
63 static int ifconfig_net_close(struct inode * inode, struct file * filp)
66 if (ifconfig_net_debug) {
67 printk("ifconfig_net_close called.\n");
74 * assign_ifname - Assign the next available interface name from the persistent list.
77 assign_ifname(struct net_device *dev,
78 struct ifname_num *ifname_num)
85 if ( (memcmp(dev->name, "eth", 3) == 0) ) {
86 if (ifname_num->next_eth != -1) {
88 * Assign it the next available eth interface number.
90 memset(dev->name, 0, strlen(dev->name));
91 sprintf(dev->name, "eth%d", (int)ifname_num->next_eth);
92 ifname_num->next_eth++;
99 * Handle fddi devices.
101 if ( (memcmp(dev->name, "fddi", 4) == 0) ) {
102 if (ifname_num->next_fddi != -1) {
104 * Assign it the next available fddi interface number.
106 memset(dev->name, 0, strlen(dev->name));
107 sprintf(dev->name, "fddi%d", (int)ifname_num->next_fddi);
108 ifname_num->next_fddi++;
115 * Handle hip devices.
117 if ( (memcmp(dev->name, "hip", 3) == 0) ) {
118 if (ifname_num->next_hip != -1) {
120 * Assign it the next available hip interface number.
122 memset(dev->name, 0, strlen(dev->name));
123 sprintf(dev->name, "hip%d", (int)ifname_num->next_hip);
124 ifname_num->next_hip++;
133 if ( (memcmp(dev->name, "tr", 2) == 0) ) {
134 if (ifname_num->next_tr != -1) {
136 * Assign it the next available tr interface number.
138 memset(dev->name, 0, strlen(dev->name));
139 sprintf(dev->name, "tr%d", (int)ifname_num->next_tr);
140 ifname_num->next_tr++;
149 if ( (memcmp(dev->name, "fc", 2) == 0) ) {
150 if (ifname_num->next_fc != -1) {
152 * Assign it the next available fc interface number.
154 memset(dev->name, 0, strlen(dev->name));
155 sprintf(dev->name, "fc%d", (int)ifname_num->next_fc);
156 ifname_num->next_fc++;
164 * find_persistent_ifname: Returns the entry that was seen in previous boot.
167 find_persistent_ifname(struct net_device *dev,
168 struct ifname_MAC *ifname_MAC)
172 while (ifname_MAC->addr_len) {
173 if (memcmp(dev->dev_addr, ifname_MAC->dev_addr, dev->addr_len) == 0)
183 * ifconfig_net_ioctl: ifconfig_net driver ioctl interface.
185 static int ifconfig_net_ioctl(struct inode * inode, struct file * file,
186 unsigned int cmd, unsigned long arg)
189 extern struct net_device *__dev_get_by_name(const char *);
191 struct net_device *dev;
192 struct ifname_MAC *found;
195 struct ifname_MAC *ifname_MAC;
196 struct ifname_MAC *temp_new_devices;
200 if (ifconfig_net_debug) {
201 printk("HCL: hcl_ioctl called.\n");
205 * Read in the header and see how big of a buffer we really need to
208 ifname_num = (struct ifname_num *) kmalloc(sizeof(struct ifname_num),
210 if (copy_from_user( ifname_num, (char *) arg, sizeof(struct ifname_num)))
212 size = ifname_num->size;
214 ifname_num = (struct ifname_num *) kmalloc(size, GFP_KERNEL);
217 ifname_MAC = (struct ifname_MAC *) ((char *)ifname_num + (sizeof(struct ifname_num)) );
219 if (copy_from_user( ifname_num, (char *) arg, size)){
223 new_devices = kmalloc(size - sizeof(struct ifname_num), GFP_KERNEL);
224 if (new_devices <= 0){
228 temp_new_devices = new_devices;
230 memset(new_devices, 0, size - sizeof(struct ifname_num));
234 * Go through the net device entries and make them persistent!
236 for (dev = dev_base; dev != NULL; dev = dev->next) {
238 * Skip NULL entries or "lo"
240 if ( (dev->addr_len == 0) || ( !strncmp(dev->name, "lo", strlen(dev->name))) ){
245 * See if we have a persistent interface name for this device.
248 found = find_persistent_ifname(dev, ifname_MAC);
250 strcpy(dev->name, found->name);
252 /* Never seen this before .. */
253 assign_ifname(dev, ifname_num);
256 * Save the information for the next boot.
258 sprintf(temp,"%s %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
259 dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
260 dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
261 strcpy(temp_new_devices->name, dev->name);
262 temp_new_devices->addr_len = dev->addr_len;
263 memcpy(temp_new_devices->dev_addr, dev->dev_addr, dev->addr_len);
271 * Copy back to the User Buffer area any new devices encountered.
274 return copy_to_user((char *)arg + (sizeof(struct ifname_num)), new_devices,
275 size - sizeof(struct ifname_num))?-EFAULT:0;
280 struct file_operations ifconfig_net_fops = {
281 ioctl:ifconfig_net_ioctl, /* ioctl */
282 open:ifconfig_net_open, /* open */
283 release:ifconfig_net_close /* release */
288 * init_ifconfig_net() - Boot time initialization. Ensure that it is called
289 * after devfs has been initialized.
293 int init_module (void)
295 int __init init_ifconfig_net(void)
298 ifconfig_net_handle = NULL;
299 ifconfig_net_handle = hwgraph_register(hwgraph_root, ".ifconfig_net",
300 0, DEVFS_FL_AUTO_DEVNUM,
302 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
303 &ifconfig_net_fops, NULL);
305 if (ifconfig_net_handle == NULL) {
306 panic("Unable to create SGI PERSISTENT NETWORK DEVICE Name Driver.\n");