Commit 9808d508 authored by Christoph Hellwig's avatar Christoph Hellwig

[PATCH] switch sb1000 to new style net init & pnp

This cleans up the driver big time and gets rid of a big ugly wart
in setup.c.  Note that I don't have the hardware so this is only
compile-tested.
parent ac062f74
......@@ -158,7 +158,7 @@ config ETHERTAP
config NET_SB1000
tristate "General Instruments Surfboard 1000"
depends on NETDEVICES && ISAPNP
depends on NETDEVICES && PNP
---help---
This is a driver for the General Instrument (also known as
NextLevel) SURFboard 1000 internal
......
......@@ -49,7 +49,7 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
#include <linux/skbuff.h>
#include <linux/delay.h> /* for udelay() */
#include <linux/etherdevice.h>
#include <linux/isapnp.h>
#include <linux/pnp.h>
#include <asm/bitops.h>
#include <asm/io.h>
......@@ -131,82 +131,52 @@ static inline int sb1000_set_PIDs(const int ioaddr[], const char* name,
static inline int sb1000_rx(struct net_device *dev);
static inline void sb1000_error_dpc(struct net_device *dev);
static struct isapnp_device_id id_table[] = {
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('G','I','C'), ISAPNP_FUNCTION(0x1000), 0 },
{0}
static const struct pnp_device_id sb1000_pnp_ids[] = {
{ "GIC1000", 0 },
{ "", 0 }
};
MODULE_DEVICE_TABLE(pnp, sb1000_pnp_ids);
MODULE_DEVICE_TABLE(isapnp, id_table);
/* probe for SB1000 using Plug-n-Play mechanism */
int
sb1000_probe(struct net_device *dev)
static void
sb1000_setup(struct net_device *dev)
{
dev->type = ARPHRD_ETHER;
dev->mtu = 1500;
dev->addr_len = ETH_ALEN;
/* New-style flags. */
dev->flags = IFF_POINTOPOINT|IFF_NOARP;
}
static int
sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id)
{
struct net_device *dev;
unsigned short ioaddr[2], irq;
struct pnp_dev *idev=NULL;
unsigned int serial_number;
int error = -ENODEV;
while(1)
{
/*
* Find the card
*/
idev=pnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'),
ISAPNP_FUNCTION(0x1000), idev);
/*
* No card
*/
if(idev==NULL || idev->card == NULL)
if (pnp_device_attach(pdev) < 0)
return -ENODEV;
if (pnp_activate_dev(pdev) < 0)
goto out_detach;
/*
* Bring it online
*/
if (pnp_device_attach(idev) < 0)
continue;
if (pnp_activate_dev(idev) < 0) {
__again:
pnp_device_detach(idev);
continue;
}
/*
* Ports free ?
*/
if(!pnp_port_valid(idev, 0) || !pnp_port_valid(idev, 1) || !pnp_irq_valid(idev, 0))
goto __again;
serial_number = idev->card->serial;
if (!pnp_port_valid(pdev, 0) || !pnp_port_valid(pdev, 1))
goto out_disable;
if (!pnp_irq_valid(pdev, 0))
goto out_disable;
ioaddr[0]=pnp_port_start(idev, 0);
ioaddr[1]=pnp_port_start(idev, 0);
serial_number = pdev->card->serial;
irq = pnp_irq(idev, 0);
ioaddr[0] = pnp_port_start(pdev, 0);
ioaddr[1] = pnp_port_start(pdev, 0);
/* check I/O base and IRQ */
if (dev->base_addr != 0 && dev->base_addr != ioaddr[0])
goto __again;
if (dev->mem_start != 0 && dev->mem_start != ioaddr[1])
goto __again;
if (dev->irq != 0 && dev->irq != irq)
goto __again;
irq = pnp_irq(pdev, 0);
/*
* Ok set it up.
*/
if (!request_region(ioaddr[0], 16, dev->name))
goto __again;
if (!request_region(ioaddr[1], 16, dev->name)) {
release_region(ioaddr[0], 16);
goto __again;
}
goto out_disable;
if (!request_region(ioaddr[1], 16, dev->name))
goto out_release_region0;
dev->base_addr = ioaddr[0];
/* mem_start holds the second I/O address */
......@@ -218,21 +188,13 @@ sb1000_probe(struct net_device *dev)
"S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr,
dev->mem_start, serial_number, dev->irq);
dev = init_etherdev(dev, 0);
dev = alloc_netdev(sizeof(struct sb1000_private), "cm%d", sb1000_setup);
if (!dev) {
pnp_device_detach(idev);
release_region(ioaddr[1], 16);
release_region(ioaddr[0], 16);
return -ENOMEM;
error = -ENOMEM;
goto out_release_regions;
}
SET_MODULE_OWNER(dev);
/* Make up a SB1000-specific-data structure. */
dev->priv = kmalloc(sizeof(struct sb1000_private), GFP_KERNEL);
if (dev->priv == NULL)
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct sb1000_private));
if (sb1000_debug > 0)
printk(KERN_NOTICE "%s", version);
......@@ -243,35 +205,49 @@ sb1000_probe(struct net_device *dev)
dev->stop = sb1000_close;
dev->get_stats = sb1000_stats;
/* Fill in the generic fields of the device structure. */
dev->change_mtu = NULL;
dev->hard_header = NULL;
dev->rebuild_header = NULL;
dev->set_mac_address = NULL;
dev->header_cache_update= NULL;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = 0;
dev->mtu = 1500;
dev->addr_len = ETH_ALEN;
/* hardware address is 0:0:serial_number */
dev->dev_addr[0] = 0;
dev->dev_addr[1] = 0;
dev->dev_addr[2] = serial_number >> 24 & 0xff;
dev->dev_addr[3] = serial_number >> 16 & 0xff;
dev->dev_addr[4] = serial_number >> 8 & 0xff;
dev->dev_addr[5] = serial_number >> 0 & 0xff;
dev->tx_queue_len = 0;
/* New-style flags. */
dev->flags = IFF_POINTOPOINT|IFF_NOARP;
/* Lock resources */
pnp_set_drvdata(pdev, dev);
error = register_netdev(dev);
if (error)
goto out_unregister;
return 0;
}
out_unregister:
unregister_netdev(dev);
out_release_regions:
release_region(ioaddr[1], 16);
out_release_region0:
release_region(ioaddr[0], 16);
out_disable:
pnp_disable_dev(pdev);
out_detach:
pnp_device_detach(pdev);
return error;
}
static void
sb1000_remove_one(struct pnp_dev *pdev)
{
struct net_device *dev = pnp_get_drvdata(pdev);
unregister_netdev(dev);
release_region(dev->base_addr, 16);
release_region(dev->mem_start, 16);
}
static struct pnp_driver sb1000_driver = {
.name = "sb1000",
.id_table = sb1000_pnp_ids,
.probe = sb1000_probe_one,
.remove = sb1000_remove_one,
};
/*
* SB1000 hardware routines to be used during open/configuration phases
......@@ -1207,60 +1183,21 @@ static int sb1000_close(struct net_device *dev)
return 0;
}
#ifdef MODULE
MODULE_AUTHOR("Franco Venturi <fventuri@mediaone.net>");
MODULE_DESCRIPTION("General Instruments SB1000 driver");
MODULE_LICENSE("GPL");
MODULE_PARM(io, "1-2i");
MODULE_PARM(irq, "i");
MODULE_PARM_DESC(io, "SB1000 I/O base addresses");
MODULE_PARM_DESC(irq, "SB1000 IRQ number");
static struct net_device dev_sb1000;
static int io[2];
static int irq;
int
init_module(void)
static int __init
sb1000_init(void)
{
int i;
for (i = 0; i < 100; i++) {
sprintf(dev_sb1000.name, "cm%d", i);
if (dev_get(dev_sb1000.name) == 0) break;
}
if (i == 100) {
printk(KERN_ERR "sb1000: can't register any device cm<n>\n");
return -ENFILE;
}
dev_sb1000.init = sb1000_probe;
dev_sb1000.base_addr = io[0];
/* mem_start holds the second I/O address */
dev_sb1000.mem_start = io[1];
dev_sb1000.irq = irq;
if (register_netdev(&dev_sb1000) != 0) {
printk(KERN_ERR "sb1000: failed to register device (io: %03x,%03x "
"irq: %d)\n", io[0], io[1], irq);
return -EIO;
}
return 0;
return pnp_register_driver(&sb1000_driver);
}
void cleanup_module(void)
static void __exit
sb1000_exit(void)
{
unregister_netdev(&dev_sb1000);
release_region(dev_sb1000.base_addr, 16);
release_region(dev_sb1000.mem_start, 16);
kfree(dev_sb1000.priv);
dev_sb1000.priv = NULL;
pnp_unregister_driver(&sb1000_driver);
}
#endif /* MODULE */
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -DMODULE -Wall -Wstrict-prototypes -O -m486 -c sb1000.c"
* version-control: t
* tab-width: 4
* c-basic-offset: 4
* End:
*/
module_init(sb1000_init);
module_exit(sb1000_exit);
......@@ -21,14 +21,6 @@ extern int lmc_setup(void);
extern int madgemc_probe(void);
/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */
#define __PAD6 "\0\0\0\0\0\0\0\0\0"
#define __PAD5 __PAD6 "\0"
#define __PAD4 __PAD5 "\0"
#define __PAD3 __PAD4 "\0"
#define __PAD2 __PAD3 "\0"
/*
* Devices in this list must do new style probing. That is they must
* allocate their own device objects and do their own bus scans.
......@@ -84,7 +76,7 @@ static struct net_probe pci_probes[] __initdata = {
* into them.
*/
static void __init network_probe(void)
void __init net_device_init(void)
{
struct net_probe *p = pci_probes;
......@@ -94,28 +86,3 @@ static void __init network_probe(void)
p++;
}
}
static void __init special_device_init(void)
{
#ifdef CONFIG_NET_SB1000
extern int sb1000_probe(struct net_device *dev);
static struct net_device sb1000_dev = {
.name = "cm0" __PAD3,
.init = sb1000_probe,
};
register_netdev(&sb1000_dev);
#endif
}
/*
* Initialise network devices
*/
void __init net_device_init(void)
{
/* Devices supporting the new^H^H^Hold probing API */
network_probe();
/* Special devices */
special_device_init();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment