[PATCH] convert dgrs to driver bus model probing.
flat view
DORMANTno replies
From: Stephen Hemminger <hidden>
Date: 2003-11-26 00:24:50
Convert the net/dgrs.c driver to use pci and eisa driver to use the common
bus interface for device location. Tested for the no board case.
diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c--- a/drivers/net/dgrs.c Tue Nov 25 16:21:05 2003
+++ b/drivers/net/dgrs.c Tue Nov 25 16:21:05 2003@@ -121,11 +121,22 @@ #include "dgrs_asstruct.h" #include "dgrs_bcomm.h" +#ifdef CONFIG_PCI static struct pci_device_id dgrs_pci_tbl[] = { { SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, dgrs_pci_tbl); +#endif + +#ifdef CONFIG_EISA +static struct eisa_device_id dgrs_eisa_tbl[] = { + { "DBI0A01" }, + { } +}; +MODULE_DEVICE_TABLE(eisa, dgrs_eisa_tbl); +#endif + MODULE_LICENSE("GPL");
@@ -179,11 +190,6 @@ static int dgrs_nicmode; /* - * Chain of device structures - */ -static struct net_device *dgrs_root_dev; - -/* * Private per-board data structure (dev->priv) */ typedef struct
@@ -191,7 +197,6 @@ /* * Stuff for generic ethercard I/F */ - struct net_device *next_dev; struct net_device_stats stats; /*
@@ -1242,22 +1247,23 @@ return (0); } -static int __init +static struct net_device * __init dgrs_found_device( int io, ulong mem, int irq, ulong plxreg, - ulong plxdma + ulong plxdma, + struct device *pdev ) { - DGRS_PRIV *priv; - struct net_device *dev, *aux; + DGRS_PRIV *priv; + struct net_device *dev; int i, ret; dev = alloc_etherdev(sizeof(DGRS_PRIV)); if (!dev) - return -ENOMEM; + return ERR_PTR(-ENOMEM); priv = (DGRS_PRIV *)dev->priv;
@@ -1274,17 +1280,15 @@ dev->init = dgrs_probe1; SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, pdev); if (register_netdev(dev) != 0) { free_netdev(dev); - return -EIO; + return ERR_PTR(-EIO); } - priv->next_dev = dgrs_root_dev; - dgrs_root_dev = dev; - if ( !dgrs_nicmode ) - return (0); /* Switch mode, we are done */ + return dev; /* Switch mode, we are done */ /* * Operating card as N separate NICs
@@ -1297,13 +1301,12 @@ struct net_device *devN; DGRS_PRIV *privN; /* Allocate new dev and priv structures */ - devN = alloc_etherdev(sizeof(DGRS_PRIV)); + devN = alloc_etherdev(sizeof(DGRS_PRIV )); ret = -ENOMEM; if (!devN) goto fail; - /* Make it an exact copy of dev[0]... */ - *devN = *dev; + /* Don't copy the network device structure! */ /* copy the priv structure of dev[0] */ privN = (DGRS_PRIV *)devN->priv;
@@ -1317,9 +1320,9 @@ /* ... and base MAC address off address of 1st port */ devN->dev_addr[5] += i; /* ... choose a new name */ - strncpy(devN->name, "eth%d", IFNAMSIZ); devN->init = dgrs_initclone; SET_MODULE_OWNER(devN); + SET_NETDEV_DEV(dev, pdev); ret = -EIO; if (register_netdev(devN)) {
@@ -1328,110 +1331,165 @@ } privN->chan = i+1; priv->devtbl[i] = devN; - privN->next_dev = dgrs_root_dev; - dgrs_root_dev = devN; } - return 0; -fail: aux = priv->next_dev; - while (dgrs_root_dev != aux) { - struct net_device *d = dgrs_root_dev; - - dgrs_root_dev = ((DGRS_PRIV *)d->priv)->next_dev; + return dev; + + fail: + while (i >= 0) { + struct net_device *d = priv->devtbl[i--]; unregister_netdev(d); free_netdev(d); } - return ret; + return ERR_PTR(ret); } -/* - * Scan for all boards - */ -static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 }; +static void __devexit dgrs_remove(struct net_device *dev) +{ + DGRS_PRIV *priv = dev->priv; + int i; -static int __init dgrs_scan(void) + unregister_netdev(dev); + + for (i = 1; i < priv->nports; ++i) { + struct net_device *d = priv->devtbl[i]; + if (d) { + unregister_netdev(d); + free_netdev(d); + } + } + + proc_reset(priv->devtbl[0], 1); + + if (priv->vmem) + iounmap(priv->vmem); + if (priv->vplxdma) + iounmap((uchar *) priv->vplxdma); + + release_region(dev->base_addr, 256); + + if (dev->irq) + free_irq(dev->irq, dev); + + for (i = 1; i < priv->nports; ++i) { + if (priv->devtbl[i]) + unregister_netdev(priv->devtbl[i]); + } + free_netdev(dev); +} + +#ifdef CONFIG_PCI +static int __init dgrs_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int cards_found = 0; + struct net_device *dev; + int err; uint io; uint mem; uint irq; uint plxreg; uint plxdma; - struct pci_dev *pdev = NULL; /* - * First, check for PCI boards - */ - while ((pdev = pci_find_device(SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, pdev)) != NULL) - { - /* - * Get and check the bus-master and latency values. - * Some PCI BIOSes fail to set the master-enable bit, - * and the latency timer must be set to the maximum - * value to avoid data corruption that occurs when the - * timer expires during a transfer. Yes, it's a bug. - */ - if (pci_enable_device(pdev)) - continue; - pci_set_master(pdev); - - plxreg = pci_resource_start (pdev, 0); - io = pci_resource_start (pdev, 1); - mem = pci_resource_start (pdev, 2); - pci_read_config_dword(pdev, 0x30, &plxdma); - irq = pdev->irq; - plxdma &= ~15; + * Get and check the bus-master and latency values. + * Some PCI BIOSes fail to set the master-enable bit, + * and the latency timer must be set to the maximum + * value to avoid data corruption that occurs when the + * timer expires during a transfer. Yes, it's a bug. + */ + err = pci_enable_device(pdev); + if (err) + return err; + pci_set_master(pdev); + + plxreg = pci_resource_start (pdev, 0); + io = pci_resource_start (pdev, 1); + mem = pci_resource_start (pdev, 2); + pci_read_config_dword(pdev, 0x30, &plxdma); + irq = pdev->irq; + plxdma &= ~15; + + /* + * On some BIOSES, the PLX "expansion rom" (used for DMA) + * address comes up as "0". This is probably because + * the BIOS doesn't see a valid 55 AA ROM signature at + * the "ROM" start and zeroes the address. To get + * around this problem the SE-6 is configured to ask + * for 4 MB of space for the dual port memory. We then + * must set its range back to 2 MB, and use the upper + * half for DMA register access + */ + OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L); + if (plxdma == 0) + plxdma = mem + (2048L * 1024L); + pci_write_config_dword(pdev, 0x30, plxdma + 1); + pci_read_config_dword(pdev, 0x30, &plxdma); + plxdma &= ~15; + + dev = dgrs_found_device(io, mem, irq, plxreg, plxdma, &pdev->dev); + if (IS_ERR(dev)) + return PTR_ERR(dev); - /* - * On some BIOSES, the PLX "expansion rom" (used for DMA) - * address comes up as "0". This is probably because - * the BIOS doesn't see a valid 55 AA ROM signature at - * the "ROM" start and zeroes the address. To get - * around this problem the SE-6 is configured to ask - * for 4 MB of space for the dual port memory. We then - * must set its range back to 2 MB, and use the upper - * half for DMA register access - */ - OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L); - if (plxdma == 0) - plxdma = mem + (2048L * 1024L); - pci_write_config_dword(pdev, 0x30, plxdma + 1); - pci_read_config_dword(pdev, 0x30, &plxdma); - plxdma &= ~15; + pci_set_drvdata(pdev, dev); + return 0; +} + +static void __devexit dgrs_pci_remove(struct pci_dev *pdev) +{ + dgrs_remove(pci_get_drvdata(pdev)); +} - dgrs_found_device(io, mem, irq, plxreg, plxdma); +static struct pci_driver dgrs_pci_driver = { + .name = "dgrs", + .id_table = dgrs_pci_tbl, + .probe = dgrs_pci_probe, + .remove = __devexit_p(dgrs_pci_remove), +}; +#endif - cards_found++; - } - /* - * Second, check for EISA boards - */ - if (EISA_bus) - { - for (io = 0x1000; io < 0x9000; io += 0x1000) - { - if (inb(io+ES4H_MANUFmsb) != 0x10 - || inb(io+ES4H_MANUFlsb) != 0x49 - || inb(io+ES4H_PRODUCT) != ES4H_PRODUCT_CODE) - continue; +#ifdef CONFIG_EISA +static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 }; - if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) ) - continue; /* Not EISA configured */ +static int __init dgrs_eisa_probe (struct device *gendev) +{ + struct net_device *dev; + struct eisa_device *edev = to_eisa_device(gendev); + uint io = edev->base_addr; + uint mem; + uint irq; - mem = (inb(io+ES4H_AS_31_24) << 24) - + (inb(io+ES4H_AS_23_16) << 16); + if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) ) + return -ENODEV; /* Not EISA configured */ - irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ]; + mem = (inb(io+ES4H_AS_31_24) << 24) + + (inb(io+ES4H_AS_23_16) << 16); - dgrs_found_device(io, mem, irq, 0L, 0L); + irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ]; - ++cards_found; - } - } + dev = dgrs_found_device(io, mem, irq, 0L, 0L, gendev); + if (IS_ERR(dev)) + return PTR_ERR(dev); - return cards_found; + gendev->driver_data = dev; + return 0; } +static int __devexit dgrs_eisa_remove(struct device *gendev) +{ + dgrs_remove(gendev->driver_data); + return 0; +} + + +static struct eisa_driver dgrs_eisa_driver = { + .id_table = dgrs_eisa_tbl, + .driver = { + .name = "dgrs", + .probe = dgrs_eisa_probe, + .remove = __devexit_p(dgrs_eisa_remove), + } +}; +#endif /* * Variables that can be overriden from module command line
@@ -1459,8 +1517,8 @@ static int __init dgrs_init_module (void) { - int cards_found; int i; + int eisacount = 0, pcicount = 0; /* * Command line variable overrides
@@ -1501,38 +1559,27 @@ /* * Find and configure all the cards */ - dgrs_root_dev = NULL; - cards_found = dgrs_scan(); - - return cards_found ? 0 : -ENODEV; +#ifdef CONFIG_EISA + eisacount = eisa_driver_register(&dgrs_eisa_driver); + if (eisacount < 0) + return eisacount; +#endif +#ifdef CONFIG_PCI + pcicount = pci_module_init(&dgrs_pci_driver); + if (pcicount < 0) + return pcicount; +#endif + return (eisacount + pcicount) == 0 ? -ENODEV : 0; } static void __exit dgrs_cleanup_module (void) { - while (dgrs_root_dev) - { - struct net_device *next_dev; - DGRS_PRIV *priv; - - priv = (DGRS_PRIV *) dgrs_root_dev->priv; - next_dev = priv->next_dev; - unregister_netdev(dgrs_root_dev); - - proc_reset(priv->devtbl[0], 1); - - if (priv->vmem) - iounmap(priv->vmem); - if (priv->vplxdma) - iounmap((uchar *) priv->vplxdma); - - release_region(dgrs_root_dev->base_addr, 256); - - if (dgrs_root_dev->irq) - free_irq(dgrs_root_dev->irq, dgrs_root_dev); - - free_netdev(dgrs_root_dev); - dgrs_root_dev = next_dev; - } +#ifdef CONFIG_EISA + eisa_driver_unregister (&dgrs_eisa_driver); +#endif +#ifdef CONFIG_PCI + pci_unregister_driver (&dgrs_pci_driver); +#endif } module_init(dgrs_init_module);