hp100 - device naming patch

Jean Tourrilhes (jt@hplb.hpl.hp.com)
Wed, 12 Feb 1997 20:05:17 +0000 (GMT)


Hi,

This is the second version of my "device naming" patch for the
100vg network driver. I already send it to the 100vg maintainer, but I
send it also to the list because :
o It has been updated
o 100vg maintainers are a bit slow (first version was in october)
o It migh interest other network driver maintainers

What's device naming ? Nothing really complicated. I've got a
laptop with a pcmcia socket and a docking station, in the docking
station a 100vg card and in the pcmcia slot a Wavelan card.
If I start docked, 100vg is eth0 and Wavelan is eth1. If I
start undocked, Wavelan is eth0. Then, if I dock, 100vg is eth1. The
pcmcia package adapt quite well, but normal configuration scripts
require that the card is at a fixed name.
With device naming, I set [options hp100 hp100_name=eth2] in
/etc/conf.modules and 100vg is *always* eth2. eth0 and eth1 are free
for the pcmcia socket.
It might also be used if you don't like "eth#" and want to use
other name.

This stuff is already implemented in a sligthly different way
in the Wavelan driver (but, who care about the Wavelan ?).
Of course, to use that patch, you need the new version of
insmod which hasn't been yet released. That's the bleeding edge of the
kernel development !

Have fun with that, and sorry to be so talkative...

Jean

P.S. : I'm new to the list, so I don't know if it should really be
there. I'm just trying to understand the instructions in the
MAINTAINERS file. This patch is quite small, but I've got a *big* one
for the Wavelan in 2.0.29 to send...

-----------------------------------------

diff -u --recursive --new-file /usr/src/kernel-source-2.1.26b/drivers/net/hp100.c /usr/src/linux/drivers/net/hp100.c
--- /usr/src/kernel-source-2.1.26b/drivers/net/hp100.c Sun Feb 2 19:50:59 1997
+++ /usr/src/linux/drivers/net/hp100.c Mon Feb 10 20:13:31 1997
@@ -1098,36 +1098,77 @@

#ifdef MODULE

-static int hp100_port = -1;
-MODULE_PARM(hp100_port, "i");
+/* Parameters set by insmod */
+static int hp100_port[5] = { 0, -1, -1, -1, -1 };
+MODULE_PARM(hp100_port, "1-5i");

-static char devicename[9] = { 0, };
-static struct device dev_hp100 = {
- devicename, /* device name is inserted by linux/drivers/net/net_init.c */
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, hp100_probe
-};
+static char hp100_name[5][IFNAMSIZ] = { "", "", "", "", "" };
+MODULE_PARM(hp100_name, "1-5c" __MODULE_STRING(IFNAMSIZ));
+
+/* List of devices */
+static struct device *hp100_devlist[5] = { NULL, NULL, NULL, NULL, NULL };
+
+/* Note : if you have more that 5 100vg card in your pc, feel free to
+ * increase this value :-)
+ */
+
+/* Note : to register three eisa or pci device, do :
+ * option hp100 hp100_port=0,0,0
+ * to register 1 card at io 0x280 as eth239, do :
+ * option hp100 hp100_port=0x280 hp100_name=eth239
+ */

int init_module( void )
{
+ int i;
+ int ret = 0;
+
if (hp100_port == 0 && !EISA_bus)
printk("HP100: You should not use auto-probing with insmod!\n");
- if ( hp100_port > 0 )
- dev_hp100.base_addr = hp100_port;
- if ( register_netdev( &dev_hp100 ) != 0 )
- return -EIO;
- return 0;
+
+ /* Loop on all possible base addresses */
+ i = -1;
+ while((hp100_port[++i] != -1) && (i < 5))
+ {
+ /* Create device and set basics args */
+ hp100_devlist[i] = kmalloc(sizeof(struct device), GFP_KERNEL);
+ memset(hp100_devlist[i], 0x00, sizeof(struct device));
+ hp100_devlist[i]->name = hp100_name[i];
+ hp100_devlist[i]->base_addr = hp100_port[i];
+ hp100_devlist[i]->init = &hp100_probe;
+
+ /* Try to create the device */
+ if(register_netdev(hp100_devlist[i]) != 0)
+ {
+ /* DeAllocate everything */
+ /* Note : if dev->priv is mallocated, there is no way to fail */
+ kfree_s(hp100_devlist[i], sizeof(struct device));
+ hp100_devlist[i] = (struct device *) NULL;
+ ret = -EIO;
+ }
+ } /* Loop on all devices */
+
+ return ret;
}

void cleanup_module( void )
{
- unregister_netdev( &dev_hp100 );
- release_region( dev_hp100.base_addr, HP100_REGION_SIZE );
- if ( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt )
- iounmap( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt );
- kfree_s( dev_hp100.priv, sizeof( struct hp100_private ) );
- dev_hp100.priv = NULL;
+ int i;
+
+ for(i = 0; i < 5; i++)
+ if(hp100_devlist[i] != (struct device *) NULL)
+ {
+ unregister_netdev( hp100_devlist[i] );
+ release_region( hp100_devlist[i]->base_addr, HP100_REGION_SIZE );
+ if ( ((struct hp100_private *)
+ hp100_devlist[i]->priv) -> mem_ptr_virt )
+ iounmap( ((struct hp100_private *)
+ hp100_devlist[i]->priv) -> mem_ptr_virt );
+ kfree_s( hp100_devlist[i]->priv, sizeof( struct hp100_private ) );
+ hp100_devlist[i]->priv = NULL;
+ kfree_s(hp100_devlist[i], sizeof(struct device));
+ hp100_devlist[i] = (struct device *) NULL;
+ }
}

#endif