3c509: convert to isa_driver and pnp_driver
Subsystems (2)
PATCH 11/21 3c509: convert to isa_driver and pnp_driver
From: Ondrej Zary <[email protected]>
Convert 3c509 driver to isa_driver and pnp_driver. The result is that autoloading using udev and hibernation works with ISA PnP cards. It also adds hibernation support for non-PnP ISA cards.
xcvr module parameter was removed as its value was not used.
Tested using 3 ISA cards in various combinations of PnP and non-PnP modes. EISA and MCA only compile-tested.
---
drivers/net/3c509.c | 729 +++++++++++++++++++++--------------------- 1 file changed, 372 insertions(+), 357 deletions(-)
drivers/net/3c509.c renamed from drivers/net/3c509.c~3c509-convert-to-isa_driver-and-pnp_driver-v6 +372 -357
@@ -54,25 +54,24 @@v1.19a 28Oct2002 Davud Ruggiero <[email protected]> - Increase *read_eeprom udelay to workaround oops with 2 cards. v1.19b 08Nov2002 Marc Zyngier <[email protected]> -- Introduce driver model for EISA cards. +- Introduce driver model for EISA cards. +v1.20 04Feb2008 Ondrej Zary <[email protected]> +- convert to isa_driver and pnp_driver and some cleanups */ #define DRV_NAME "3c509" -#define DRV_VERSION "1.19b" -#define DRV_RELDATE "08Nov2002" +#define DRV_VERSION "1.20" +#define DRV_RELDATE "04Feb2008"/* A few values that may be tweaked. */ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (400*HZ/1000) -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work =10 ;#include <linux/module.h> -#ifdef CONFIG_MCA #include <linux/mca.h> -#endif -#include <linux/isapnp.h> +#include <linux/isa.h> +#include <linux/pnp.h> #include <linux/string.h> #include <linux/interrupt.h> #include <linux/errno.h>
@@ -97,10 +96,6 @@ static int max_interrupt_work = 10;static char version[]__initdata =DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " [email protected]\n" ; -#if defined(CONFIG_PM ) && (defined(CONFIG_MCA ) || defined(CONFIG_EISA )) -#define EL3_SUSPEND -#endif -#ifdef EL3_DEBUG static int el3_debug =EL3_DEBUG ;#else
@@ -111,6 +106,7 @@ static int el3_debug = 2;* a global variable so that the mca/eisa probe routines can increment * it */ static int el3_cards =0 ; +#define EL3_MAX_CARDS 8/* To minimize the size of the driver source I only define operating constants if they are used several times. You'll need the manual
@@ -119,7 +115,7 @@ static int el3_cards = 0;#define EL3_DATA 0x00#define EL3_CMD 0x0e#define EL3_STATUS 0x0e -#define EEPROM_READ 0x80 +#define EEPROM_READ 0x80#define EL3_IO_EXTENT 16
@@ -168,23 +164,31 @@ enum RxFilter {*/ #define SKB_QUEUE_SIZE 64 +enum el3_cardtype {EL3_ISA ,EL3_PNP ,EL3_MCA ,EL3_EISA }; +struct el3_private {struct net_device_stats stats; -struct net_device *next_dev;spinlock_t lock;/* skb send-queue */ int head, size;struct sk_buff *queue[SKB_QUEUE_SIZE ]; -enum { -EL3_MCA , -EL3_PNP , -EL3_EISA , - } type;/* type of device */ -struct device *dev; +enum el3_cardtype type; }; -static int id_port__initdata =0x110 ;/* Start with 0x110 to avoid new sound cards.*/ -static struct net_device *el3_root_dev; +static int id_port; +static int current_tag; +static struct net_device *el3_devs[EL3_MAX_CARDS ]; + +/* Parameters that may be passed into the module. */ +static int debug =-1 ; +static int irq[] = {-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }; +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ +static int max_interrupt_work =10 ; +#ifdef CONFIG_PNP +static int nopnp; +#endif +static int __init el3_common_init (struct net_device *dev); +static void el3_common_remove (struct net_device *dev);static ushort id_read_eeprom (int index);static ushort read_eeprom (int ioaddr,int index);static int el3_open (struct net_device *dev);
@@ -199,7 +203,7 @@ static void el3_tx_timeout (struct net_dstatic void el3_down (struct net_device *dev);static void el3_up (struct net_device *dev);static const struct ethtool_ops ethtool_ops; -#ifdef EL3_SUSPEND +#ifdef CONFIG_PM static int el3_suspend (struct device *,pm_message_t );static int el3_resume (struct device *);#else
@@ -209,13 +213,272 @@ static int el3_resume(struct device *);/* generic device remove for all device types */ -#if defined(CONFIG_EISA ) || defined(CONFIG_MCA )static int el3_device_remove (struct device *device); -#endif #ifdef CONFIG_NET_POLL_CONTROLLER static void el3_poll_controller (struct net_device *dev);#endif +/* Return 0 on success, 1 on error, 2 when found already detected PnP card */ +static int el3_isa_id_sequence (__be16 *phys_addr) +{ +short lrs_state =0xff ; +int i; + +/* ISA boards are detected by sending the ID sequence to the +ID_PORT. We find cards past the first by setting the 'current_tag' +on cards as they are found. Cards with their tag set will not +respond to subsequent ID sequences. */ + +outb (0x00 , id_port); +outb (0x00 , id_port); +for (i =0 ; i <255 ; i++) { +outb (lrs_state, id_port); + lrs_state <<=1 ; + lrs_state = lrs_state &0x100 ? lrs_state ^0xcf : lrs_state; + } +/* For the first probe, clear all board's tag registers. */ +if (current_tag ==0 ) +outb (0xd0 , id_port); +else /* Otherwise kill off already-found boards. */ +outb (0xd8 , id_port); +if (id_read_eeprom (7 ) !=0x6d50 ) +return 1 ; +/* Read in EEPROM data, which does contention-select. +Only the lowest address board will stay "on-line". +3Com got the byte order backwards. */ +for (i =0 ; i <3 ; i++) + phys_addr[i] =htons (id_read_eeprom (i)); +#ifdef CONFIG_PNP +if (!nopnp) { +/* The ISA PnP 3c509 cards respond to the ID sequence too. +This check is needed in order not to register them twice. */ +for (i =0 ; i < el3_cards; i++) { +struct el3_private *lp =netdev_priv (el3_devs[i]); +if (lp->type ==EL3_PNP + && !memcmp (phys_addr, el3_devs[i]->dev_addr, +ETH_ALEN )) { +if (el3_debug >3 ) +printk (KERN_DEBUG "3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n" , + phys_addr[0 ] &0xff , phys_addr[0 ] >>8 , + phys_addr[1 ] &0xff , phys_addr[1 ] >>8 , + phys_addr[2 ] &0xff , phys_addr[2 ] >>8 ); +/* Set the adaptor tag so that the next card can be found. */ +outb (0xd0 + ++current_tag, id_port); +return 2 ; + } + } + } +#endif /* CONFIG_PNP */ +return 0 ; + +} + +static void __devinit el3_dev_fill (struct net_device *dev,__be16 *phys_addr, +int ioaddr,int irq,int if_port, +enum el3_cardtype type) +{ +struct el3_private *lp =netdev_priv (dev); + +memcpy (dev->dev_addr, phys_addr,ETH_ALEN ); + dev->base_addr = ioaddr; + dev->irq = irq; + dev->if_port = if_port; + lp->type = type; +} + +static int __devinit el3_isa_match (struct device *pdev, +unsigned int ndev) +{ +struct net_device *dev; +int ioaddr, isa_irq, if_port, err; +unsigned int iobase; +__be16 phys_addr[3 ]; + +while ((err =el3_isa_id_sequence (phys_addr)) ==2 ) + ;/* Skip to next card when PnP card found */ +if (err ==1 ) +return 0 ; + + iobase =id_read_eeprom (8 ); + if_port = iobase >>14 ; + ioaddr =0x200 + ((iobase &0x1f ) <<4 ); +if (irq[el3_cards] >1 && irq[el3_cards] <16 ) + isa_irq = irq[el3_cards]; +else + isa_irq =id_read_eeprom (9 ) >>12 ; + + dev =alloc_etherdev (sizeof (struct el3_private )); +if (!dev) +return -ENOMEM ; + +netdev_boot_setup_check (dev); + +if (!request_region (ioaddr,EL3_IO_EXTENT ,"3c509-isa" )) { +free_netdev (dev); +return 0 ; + } + +/* Set the adaptor tag so that the next card can be found. */ +outb (0xd0 + ++current_tag, id_port); + +/* Activate the adaptor at the EEPROM location. */ +outb ((ioaddr >>4 ) |0xe0 , id_port); + +EL3WINDOW (0 ); +if (inw (ioaddr) !=0x6d50 ) { +free_netdev (dev); +return 0 ; + } + +/* Free the interrupt so that some other card can use it. */ +outw (0x0f00 , ioaddr +WN0_IRQ ); + +el3_dev_fill (dev, phys_addr, ioaddr, isa_irq, if_port,EL3_ISA ); +dev_set_drvdata (pdev, dev); +if (el3_common_init (dev)) { +free_netdev (dev); +return 0 ; + } + + el3_devs[el3_cards++] = dev; +return 1 ; +} + +static int __devexit el3_isa_remove(struct device *pdev, +unsigned int ndev) +{ +el3_device_remove (pdev); +dev_set_drvdata (pdev,NULL ); +return 0 ; +} + +#ifdef CONFIG_PM +static int el3_isa_suspend (struct device *dev,unsigned int n, +pm_message_t state) +{ + current_tag =0 ; +return el3_suspend (dev, state); +} + +static int el3_isa_resume (struct device *dev,unsigned int n) +{ +struct net_device *ndev =dev_get_drvdata (dev); +int ioaddr = ndev->base_addr, err; +__be16 phys_addr[3 ]; + +while ((err =el3_isa_id_sequence (phys_addr)) ==2 ) + ;/* Skip to next card when PnP card found */ +if (err ==1 ) +return 0 ; +/* Set the adaptor tag so that the next card can be found. */ +outb (0xd0 + ++current_tag, id_port); +/* Enable the card */ +outb ((ioaddr >>4 ) |0xe0 , id_port); +EL3WINDOW (0 ); +if (inw (ioaddr) !=0x6d50 ) +return 1 ; +/* Free the interrupt so that some other card can use it. */ +outw (0x0f00 , ioaddr +WN0_IRQ ); +return el3_resume (dev); +} +#endif + +static struct isa_driver el3_isa_driver = { + .match = el3_isa_match, + .remove =__devexit_p (el3_isa_remove), +#ifdef CONFIG_PM + .suspend = el3_isa_suspend, + .resume = el3_isa_resume, +#endif + .driver = { + .name ="3c509" + }, +}; +static int isa_registered; + +#ifdef CONFIG_PNP +static struct pnp_device_id el3_pnp_ids[] = { + { .id ="TCM5090" },/* 3Com Etherlink III (TP) */ + { .id ="TCM5091" },/* 3Com Etherlink III */ + { .id ="TCM5094" },/* 3Com Etherlink III (combo) */ + { .id ="TCM5095" },/* 3Com Etherlink III (TPO) */ + { .id ="TCM5098" },/* 3Com Etherlink III (TPC) */ + { .id ="PNP80f7" },/* 3Com Etherlink III compatible */ + { .id ="PNP80f8" },/* 3Com Etherlink III compatible */ + { .id ="" } +}; +MODULE_DEVICE_TABLE (pnp, el3_pnp_ids); + +static int __devinit el3_pnp_probe (struct pnp_dev *pdev, +const struct pnp_device_id *id) +{ +short i; +int ioaddr, irq, if_port; +u16 phys_addr[3 ]; +struct net_device *dev =NULL ; +int err; + + ioaddr =pnp_port_start (pdev,0 ); +if (!request_region (ioaddr,EL3_IO_EXTENT ,"3c509-pnp" )) +return -EBUSY ; + irq =pnp_irq (pdev,0 ); +EL3WINDOW (0 ); +for (i =0 ; i <3 ; i++) + phys_addr[i] =htons (read_eeprom (ioaddr, i)); + if_port =read_eeprom (ioaddr,8 ) >>14 ; + dev =alloc_etherdev (sizeof (struct el3_private )); +if (!dev) { +release_region (ioaddr,EL3_IO_EXTENT ); +return -ENOMEM ; + } +SET_NETDEV_DEV (dev, &pdev->dev); +netdev_boot_setup_check (dev); + +el3_dev_fill (dev, phys_addr, ioaddr, irq, if_port,EL3_PNP ); +pnp_set_drvdata (pdev, dev); + err =el3_common_init (dev); + +if (err) { +pnp_set_drvdata (pdev,NULL ); +free_netdev (dev); +return err; + } + + el3_devs[el3_cards++] = dev; +return 0 ; +} + +static void __devexit el3_pnp_remove(struct pnp_dev *pdev) +{ +el3_common_remove (pnp_get_drvdata (pdev)); +pnp_set_drvdata (pdev,NULL ); +} + +#ifdef CONFIG_PM +static int el3_pnp_suspend (struct pnp_dev *pdev,pm_message_t state) +{ +return el3_suspend (&pdev->dev, state); +} + +static int el3_pnp_resume (struct pnp_dev *pdev) +{ +return el3_resume (&pdev->dev); +} +#endif + +static struct pnp_driver el3_pnp_driver = { + .name ="3c509" , + .id_table = el3_pnp_ids, + .probe = el3_pnp_probe, + .remove =__devexit_p (el3_pnp_remove), +#ifdef CONFIG_PM + .suspend = el3_pnp_suspend, + .resume = el3_pnp_resume, +#endif +}; +static int pnp_registered; +#endif /* CONFIG_PNP */ +#ifdef CONFIG_EISA static struct eisa_device_id el3_eisa_ids[] = { { "TCM5092" },
@@ -230,13 +493,14 @@ static int el3_eisa_probe (struct devicestatic struct eisa_driver el3_eisa_driver = { .id_table = el3_eisa_ids, .driver = { - .name ="3c509" , + .name ="3c579" , .probe = el3_eisa_probe, .remove =__devexit_p (el3_device_remove), .suspend = el3_suspend, .resume = el3_resume, } }; +static int eisa_registered;#endif #ifdef CONFIG_MCA
@@ -271,45 +535,9 @@ static struct mca_driver el3_mca_driver .resume = el3_resume, }, }; +static int mca_registered;#endif /* CONFIG_MCA */ -#if defined(__ISAPNP__) -static struct isapnp_device_id el3_isapnp_adapters[]__initdata = { - {ISAPNP_ANY_ID ,ISAPNP_ANY_ID , -ISAPNP_VENDOR ('T' ,'C' ,'M' ),ISAPNP_FUNCTION (0x5090 ), - (long )"3Com Etherlink III (TP)" }, - {ISAPNP_ANY_ID ,ISAPNP_ANY_ID , -ISAPNP_VENDOR ('T' ,'C' ,'M' ),ISAPNP_FUNCTION (0x5091 ), - (long )"3Com Etherlink III" }, - {ISAPNP_ANY_ID ,ISAPNP_ANY_ID , -ISAPNP_VENDOR ('T' ,'C' ,'M' ),ISAPNP_FUNCTION (0x5094 ), - (long )"3Com Etherlink III (combo)" }, - {ISAPNP_ANY_ID ,ISAPNP_ANY_ID , -ISAPNP_VENDOR ('T' ,'C' ,'M' ),ISAPNP_FUNCTION (0x5095 ), - (long )"3Com Etherlink III (TPO)" }, - {ISAPNP_ANY_ID ,ISAPNP_ANY_ID , -ISAPNP_VENDOR ('T' ,'C' ,'M' ),ISAPNP_FUNCTION (0x5098 ), - (long )"3Com Etherlink III (TPC)" }, - {ISAPNP_ANY_ID ,ISAPNP_ANY_ID , -ISAPNP_VENDOR ('P' ,'N' ,'P' ),ISAPNP_FUNCTION (0x80f7 ), - (long )"3Com Etherlink III compatible" }, - {ISAPNP_ANY_ID ,ISAPNP_ANY_ID , -ISAPNP_VENDOR ('P' ,'N' ,'P' ),ISAPNP_FUNCTION (0x80f8 ), - (long )"3Com Etherlink III compatible" }, - { }/* terminate list */ -}; - -static __be16 el3_isapnp_phys_addr[8 ][3 ]; -static int nopnp; -#endif /* __ISAPNP__ */ - -/* With the driver model introduction for EISA devices, both init -* and cleanup have been split : -* - EISA devices probe/remove starts in el3_eisa_probe/el3_device_remove -* - MCA/ISA still use el3_probe -* -* Both call el3_common_init/el3_common_remove. */ -static int __init el3_common_init (struct net_device *dev) {struct el3_private *lp =netdev_priv (dev);
@@ -360,231 +588,11 @@ static int __init el3_common_init(structstatic void el3_common_remove (struct net_device *dev) { -struct el3_private *lp =netdev_priv (dev); - - (void ) lp;/* Keep gcc quiet... */ -#if defined(__ISAPNP__) -if (lp->type ==EL3_PNP ) -pnp_device_detach (to_pnp_dev (lp->dev)); -#endif -unregister_netdev (dev);release_region (dev->base_addr,EL3_IO_EXTENT );free_netdev (dev); } -static int __init el3_probe (int card_idx) -{ -struct net_device *dev; -struct el3_private *lp; -short lrs_state =0xff , i; -int ioaddr, irq, if_port; -__be16 phys_addr[3 ]; -static int current_tag; -int err = -ENODEV ; -#if defined(__ISAPNP__) -static int pnp_cards; -struct pnp_dev *idev =NULL ; -int pnp_found =0 ; - -if (nopnp ==1 ) - goto no_pnp; - -for (i=0 ; el3_isapnp_adapters[i].vendor !=0 ; i++) { -int j; -while ((idev =pnp_find_dev (NULL , - el3_isapnp_adapters[i].vendor, - el3_isapnp_adapters[i].function, - idev))) { -if (pnp_device_attach (idev) <0 ) -continue ; -if (pnp_activate_dev (idev) <0 ) { -__again: -pnp_device_detach (idev); -continue ; - } -if (!pnp_port_valid (idev,0 ) || !pnp_irq_valid (idev,0 )) - goto __again; - ioaddr =pnp_port_start (idev,0 ); -if (!request_region (ioaddr,EL3_IO_EXTENT ,"3c509 PnP" )) { -pnp_device_detach (idev); -return -EBUSY ; - } - irq =pnp_irq (idev,0 ); -if (el3_debug >3 ) -printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n" , - (char *) el3_isapnp_adapters[i].driver_data, ioaddr, irq); -EL3WINDOW (0 ); -for (j =0 ; j <3 ; j++) - el3_isapnp_phys_addr[pnp_cards][j] = - phys_addr[j] = -htons (read_eeprom (ioaddr, j)); - if_port =read_eeprom (ioaddr,8 ) >>14 ; - dev =alloc_etherdev (sizeof (struct el3_private )); -if (!dev) { -release_region (ioaddr,EL3_IO_EXTENT ); -pnp_device_detach (idev); -return -ENOMEM ; - } - -SET_NETDEV_DEV (dev, &idev->dev); - pnp_cards++; - -netdev_boot_setup_check (dev); - pnp_found =1 ; - goto found; - } - } -no_pnp: -#endif /* __ISAPNP__ */ - -/* Select an open I/O location at 0x1*0 to do contention select. */ -for ( ; id_port <0x200 ; id_port +=0x10 ) { -if (!request_region (id_port,1 ,"3c509" )) -continue ; -outb (0x00 , id_port); -outb (0xff , id_port); -if (inb (id_port) &0x01 ){ -release_region (id_port,1 ); -break ; - }else -release_region (id_port,1 ); - } -if (id_port >=0x200 ) { -/* Rare -- do we really need a warning? */ -printk (" WARNING: No I/O port available for 3c509 activation.\n" ); -return -ENODEV ; - } - -/* Next check for all ISA bus boards by sending the ID sequence to the -ID_PORT. We find cards past the first by setting the 'current_tag' -on cards as they are found. Cards with their tag set will not -respond to subsequent ID sequences. */ - -outb (0x00 , id_port); -outb (0x00 , id_port); -for (i =0 ; i <255 ; i++) { -outb (lrs_state, id_port); - lrs_state <<=1 ; - lrs_state = lrs_state &0x100 ? lrs_state ^0xcf : lrs_state; - } - -/* For the first probe, clear all board's tag registers. */ -if (current_tag ==0 ) -outb (0xd0 , id_port); -else /* Otherwise kill off already-found boards. */ -outb (0xd8 , id_port); - -if (id_read_eeprom (7 ) !=0x6d50 ) { -return -ENODEV ; - } - -/* Read in EEPROM data, which does contention-select. -Only the lowest address board will stay "on-line". -3Com got the byte order backwards. */ -for (i =0 ; i <3 ; i++) { - phys_addr[i] =htons (id_read_eeprom (i)); - } - -#if defined(__ISAPNP__) -if (nopnp ==0 ) { -/* The ISA PnP 3c509 cards respond to the ID sequence. -This check is needed in order not to register them twice. */ -for (i =0 ; i < pnp_cards; i++) { -if (phys_addr[0 ] == el3_isapnp_phys_addr[i][0 ] && - phys_addr[1 ] == el3_isapnp_phys_addr[i][1 ] && - phys_addr[2 ] == el3_isapnp_phys_addr[i][2 ]) - { -if (el3_debug >3 ) -printk ("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n" , - phys_addr[0 ] &0xff , phys_addr[0 ] >>8 , - phys_addr[1 ] &0xff , phys_addr[1 ] >>8 , - phys_addr[2 ] &0xff , phys_addr[2 ] >>8 ); -/* Set the adaptor tag so that the next card can be found. */ -outb (0xd0 + ++current_tag, id_port); - goto no_pnp; - } - } - } -#endif /* __ISAPNP__ */ - - { -unsigned int iobase =id_read_eeprom (8 ); - if_port = iobase >>14 ; - ioaddr =0x200 + ((iobase &0x1f ) <<4 ); - } - irq =id_read_eeprom (9 ) >>12 ; - - dev =alloc_etherdev (sizeof (struct el3_private )); -if (!dev) -return -ENOMEM ; - -netdev_boot_setup_check (dev); - -/* Set passed-in IRQ or I/O Addr. */ -if (dev->irq >1 && dev->irq <16 ) - irq = dev->irq; - -if (dev->base_addr) { -if (dev->mem_end ==0x3c509 /* Magic key */ - && dev->base_addr >=0x200 && dev->base_addr <=0x3e0 ) - ioaddr = dev->base_addr &0x3f0 ; -else if (dev->base_addr != ioaddr) - goto out; - } - -if (!request_region (ioaddr,EL3_IO_EXTENT ,"3c509" )) { - err = -EBUSY ; - goto out; - } - -/* Set the adaptor tag so that the next card can be found. */ -outb (0xd0 + ++current_tag, id_port); - -/* Activate the adaptor at the EEPROM location. */ -outb ((ioaddr >>4 ) |0xe0 , id_port); - -EL3WINDOW (0 ); -if (inw (ioaddr) !=0x6d50 ) - goto out1; - -/* Free the interrupt so that some other card can use it. */ -outw (0x0f00 , ioaddr +WN0_IRQ ); - -#if defined(__ISAPNP__) - found: /* PNP jumps here... */ -#endif /* __ISAPNP__ */ - - memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr)); - dev->base_addr = ioaddr; - dev->irq = irq; - dev->if_port = if_port; - lp = netdev_priv(dev); -#if defined(__ISAPNP__) - lp->dev = &idev->dev; - if (pnp_found) - lp->type = EL3_PNP; -#endif - err = el3_common_init(dev); - - if (err) - goto out1; - - el3_cards++; - lp->next_dev = el3_root_dev; - el3_root_dev = dev; - return 0; - -out1: -#if defined(__ISAPNP__) - if (idev) - pnp_device_detach(idev); -#endif -out: - free_netdev(dev); - return err; -} -#ifdef CONFIG_MCA static int __init el3_mca_probe (struct device *device) {
@@ -596,7 +604,6 @@ static int __init el3_mca_probe(struct d* redone for multi-card detection by ZP Gu ([email protected]) * now works as a module */ -struct el3_private *lp;short i;int ioaddr, irq, if_port;u16 phys_addr[3 ];
@@ -613,7 +620,7 @@ static int __init el3_mca_probe(struct d irq = pos5 &0x0f ; -printk ("3c529: found %s at slot %d\n" , +printk (KERN_INFO "3c529: found %s at slot %d\n" , el3_mca_adapter_names[mdev->index], slot +1 );/* claim the slot */
@@ -626,7 +633,7 @@ static int __init el3_mca_probe(struct d irq =mca_device_transform_irq (mdev, irq); ioaddr =mca_device_transform_ioport (mdev, ioaddr);if (el3_debug >2 ) { -printk ("3c529: irq %d ioaddr 0x%x ifport %d\n" , irq, ioaddr, if_port); +printk (KERN_DEBUG "3c529: irq %d ioaddr 0x%x ifport %d\n" , irq, ioaddr, if_port); }EL3WINDOW (0 );for (i =0 ; i <3 ; i++) {
@@ -641,13 +648,7 @@ static int __init el3_mca_probe(struct dnetdev_boot_setup_check (dev); -memcpy (dev->dev_addr, phys_addr,sizeof (phys_addr)); - dev->base_addr = ioaddr; - dev->irq = irq; - dev->if_port = if_port; - lp =netdev_priv (dev); - lp->dev = device; - lp->type =EL3_MCA ; +el3_dev_fill (dev, phys_addr, ioaddr, irq, if_port,EL3_MCA ); device->driver_data = dev; err =el3_common_init (dev);
@@ -657,7 +658,7 @@ static int __init el3_mca_probe(struct dreturn -ENOMEM ; } - el3_cards++; + el3_devs[el3_cards++] = dev;return 0 ; }
@@ -666,7 +667,6 @@ static int __init el3_mca_probe(struct d#ifdef CONFIG_EISA static int __init el3_eisa_probe (struct device *device) { -struct el3_private *lp;short i;int ioaddr, irq, if_port;u16 phys_addr[3 ];
@@ -678,7 +678,7 @@ static int __init el3_eisa_probe (struct edev =to_eisa_device (device); ioaddr = edev->base_addr; -if (!request_region (ioaddr,EL3_IO_EXTENT ,"3c509" )) +if (!request_region (ioaddr,EL3_IO_EXTENT ,"3c579-eisa" ))return -EBUSY ;/* Change the register set to the configuration window 0. */
@@ -700,13 +700,7 @@ static int __init el3_eisa_probe (structnetdev_boot_setup_check (dev); -memcpy (dev->dev_addr, phys_addr,sizeof (phys_addr)); - dev->base_addr = ioaddr; - dev->irq = irq; - dev->if_port = if_port; - lp =netdev_priv (dev); - lp->dev = device; - lp->type =EL3_EISA ; +el3_dev_fill (dev, phys_addr, ioaddr, irq, if_port,EL3_EISA );eisa_set_drvdata (edev, dev); err =el3_common_init (dev);
@@ -716,12 +710,11 @@ static int __init el3_eisa_probe (struct return err; } - el3_cards++; + el3_devs[el3_cards++] = dev;return 0 ; }#endif -#if defined(CONFIG_EISA ) || defined(CONFIG_MCA )/* This remove works for all device types. * * The net dev must be stored in the driver_data field */
@@ -734,7 +727,6 @@ static int __devexit el3_device_remove (el3_common_remove (dev);return 0 ; } -#endif /* Read a word from the EEPROM using the regular EEPROM access register. Assume that we are in register window zero.
@@ -749,7 +741,7 @@ static ushort read_eeprom(int ioaddr, in }/* Read a word from the EEPROM when in the ISA ID probe state. */ -static ushort __init id_read_eeprom (int index) +static ushort id_read_eeprom (int index) {int bit, word =0 ;
@@ -765,7 +757,7 @@ static ushort __init id_read_eeprom(int word = (word <<1 ) + (inb (id_port) &0x01 );if (el3_debug >3 ) -printk (" 3c509 EEPROM word %d %#4.4x.\n" , index, word); +printk (KERN_DEBUG " 3c509 EEPROM word %d %#4.4x.\n" , index, word);return word; }
@@ -787,13 +779,13 @@ el3_open(struct net_device *dev)EL3WINDOW (0 );if (el3_debug >3 ) -printk ("%s: Opening, IRQ %d status@%x %4.4x.\n" , dev->name, +printk (KERN_DEBUG "%s: Opening, IRQ %d status@%x %4.4x.\n" , dev->name, dev->irq, ioaddr +EL3_STATUS ,inw (ioaddr +EL3_STATUS ));el3_up (dev);if (el3_debug >3 ) -printk ("%s: Opened 3c509 IRQ %d status %4.4x.\n" , +printk (KERN_DEBUG "%s: Opened 3c509 IRQ %d status %4.4x.\n" , dev->name, dev->irq,inw (ioaddr +EL3_STATUS ));return 0 ;
@@ -806,7 +798,7 @@ el3_tx_timeout (struct net_device *dev)int ioaddr = dev->base_addr;/* Transmitter timeout, serious problems. */ -printk ("%s: transmit timed out, Tx_status %2.2x status %4.4x " +printk (KERN_WARNING "%s: transmit timed out, Tx_status %2.2x status %4.4x " "Tx FIFO room %d.\n" , dev->name,inb (ioaddr +TX_STATUS ),inw (ioaddr +EL3_STATUS ),inw (ioaddr +TX_FREE ));
@@ -831,7 +823,7 @@ el3_start_xmit(struct sk_buff *skb, stru lp->stats.tx_bytes += skb->len;if (el3_debug >4 ) { -printk ("%s: el3_start_xmit(length = %u) called, status %4.4x.\n" , +printk (KERN_DEBUG "%s: el3_start_xmit(length = %u) called, status %4.4x.\n" , dev->name, skb->len,inw (ioaddr +EL3_STATUS )); }#if 0
@@ -840,7 +832,7 @@ el3_start_xmit(struct sk_buff *skb, struushort status =inw (ioaddr +EL3_STATUS );if (status &0x0001 /* IRQ line active, missed one. */ &&inw (ioaddr +EL3_STATUS ) &1 ) {/* Make sure. */ -printk ("%s: Missed interrupt, status then %04x now %04x" +printk (KERN_DEBUG "%s: Missed interrupt, status then %04x now %04x" " Tx %2.2x Rx %4.4x.\n" , dev->name, status,inw (ioaddr +EL3_STATUS ),inb (ioaddr +TX_STATUS ),inw (ioaddr +RX_STATUS ));
@@ -914,7 +906,7 @@ el3_interrupt(int irq, void *dev_id)if (el3_debug >4 ) { status =inw (ioaddr +EL3_STATUS ); -printk ("%s: interrupt, status %4.4x.\n" , dev->name, status); +printk (KERN_DEBUG "%s: interrupt, status %4.4x.\n" , dev->name, status); } while ((status = inw(ioaddr + EL3_STATUS)) &
@@ -925,7 +917,7 @@ el3_interrupt(int irq, void *dev_id)if (status & TxAvailable) {if (el3_debug >5 ) -printk (" TX room bit was handled.\n" ); +printk (KERN_DEBUG " TX room bit was handled.\n" );/* There's room in the FIFO for a full-sized packet. */ outw (AckIntr | TxAvailable, ioaddr +EL3_CMD );netif_wake_queue (dev);
@@ -964,7 +956,7 @@ el3_interrupt(int irq, void *dev_id) }if (--i <0 ) { -printk ("%s: Infinite loop in interrupt, status %4.4x.\n" , +printk (KERN_ERR "%s: Infinite loop in interrupt, status %4.4x.\n" , dev->name, status);/* Clear all interrupts. */ outw (AckIntr |0xFF , ioaddr +EL3_CMD );
@@ -975,7 +967,7 @@ el3_interrupt(int irq, void *dev_id) }if (el3_debug >4 ) { -printk ("%s: exiting interrupt, status %4.4x.\n" , dev->name, +printk (KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n" , dev->name,inw (ioaddr +EL3_STATUS )); }spin_unlock (&lp->lock);
@@ -1450,7 +1442,7 @@ el3_up(struct net_device *dev) }/* Power Management support functions */ -#ifdef EL3_SUSPEND +#ifdef CONFIG_PM static int el3_suspend (struct device *pdev,pm_message_t state)
@@ -1500,79 +1492,102 @@ el3_resume(struct device *pdev)return 0 ; } -#endif /* EL3_SUSPEND */ - -/* Parameters that may be passed into the module. */ -static int debug =-1 ; -static int irq[] = {-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }; -static int xcvr[] = {-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 }; +#endif /* CONFIG_PM */ module_param (debug,int,0 );module_param_array (irq, int,NULL ,0 ); -module_param_array (xcvr, int,NULL ,0 );module_param (max_interrupt_work, int,0 );MODULE_PARM_DESC (debug,"debug level (0-6)" );MODULE_PARM_DESC (irq,"IRQ number(s) (assigned)" ); -MODULE_PARM_DESC (xcvr,"transceiver(s) (0=internal, 1=external)" );MODULE_PARM_DESC (max_interrupt_work,"maximum events handled per interrupt" ); -#if defined(__ISAPNP__) +#ifdef CONFIG_PNP module_param (nopnp, int,0 );MODULE_PARM_DESC (nopnp,"disable ISA PnP support (0-1)" ); -MODULE_DEVICE_TABLE (isapnp, el3_isapnp_adapters); -#endif /* __ISAPNP__ */ -MODULE_DESCRIPTION ("3Com Etherlink III (3c509, 3c509B) ISA/PnP ethernet driver" ); +#endif /* CONFIG_PNP */ +MODULE_DESCRIPTION ("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver" );MODULE_LICENSE ("GPL" );static int __init el3_init_module (void ) {int ret =0 ; - el3_cards =0 ;if (debug >=0 ) el3_debug = debug; - el3_root_dev =NULL ; -while (el3_probe (el3_cards) ==0 ) { -if (irq[el3_cards] >1 ) - el3_root_dev->irq = irq[el3_cards]; -if (xcvr[el3_cards] >=0 ) - el3_root_dev->if_port = xcvr[el3_cards]; - el3_cards++; +#ifdef CONFIG_PNP +if (!nopnp) { + ret =pnp_register_driver (&el3_pnp_driver); +if (!ret) + pnp_registered =1 ; + } +#endif +/* Select an open I/O location at 0x1*0 to do ISA contention select. */ +/* Start with 0x110 to avoid some sound cards.*/ +for (id_port =0x110 ; id_port <0x200 ; id_port +=0x10 ) { +if (!request_region (id_port,1 ,"3c509-control" )) +continue ; +outb (0x00 , id_port); +outb (0xff , id_port); +if (inb (id_port) &0x01 ) +break ; +else +release_region (id_port,1 ); + } +if (id_port >=0x200 ) { + id_port =0 ; +printk (KERN_ERR "No I/O port available for 3c509 activation.\n" ); + }else { + ret =isa_register_driver (&el3_isa_driver,EL3_MAX_CARDS ); +if (!ret) + isa_registered =1 ; } -#ifdef CONFIG_EISA ret =eisa_driver_register (&el3_eisa_driver); +if (!ret) + eisa_registered =1 ;#endif #ifdef CONFIG_MCA - { -int err =mca_register_driver (&el3_mca_driver); -if (ret ==0 ) - ret = err; - } + ret =mca_register_driver (&el3_mca_driver); +if (!ret) + mca_registered =1 ; +#endif + +#ifdef CONFIG_PNP +if (pnp_registered) + ret =0 ; +#endif +if (isa_registered) + ret =0 ; +#ifdef CONFIG_EISA +if (eisa_registered) + ret =0 ; +#endif +#ifdef CONFIG_MCA +if (mca_registered) + ret =0 ;#endif return ret; } static void __exit el3_cleanup_module(void) { -struct net_device *next_dev; - -while (el3_root_dev) { -struct el3_private *lp =netdev_priv (el3_root_dev); - - next_dev = lp->next_dev; -el3_common_remove (el3_root_dev); - el3_root_dev = next_dev; - } - +#ifdef CONFIG_PNP +if (pnp_registered) +pnp_unregister_driver (&el3_pnp_driver); +#endif +if (isa_registered) +isa_unregister_driver (&el3_isa_driver); +if (id_port) +release_region (id_port,1 );#ifdef CONFIG_EISA -eisa_driver_unregister (&el3_eisa_driver); +if (eisa_registered) +eisa_driver_unregister (&el3_eisa_driver);#endif #ifdef CONFIG_MCA -mca_unregister_driver (&el3_mca_driver); +if (mca_registered) +mca_unregister_driver (&el3_mca_driver);#endif }module_init (el3_init_module);module_exit (el3_cleanup_module); -
_
Quoted 10 lines · [email protected] wrote:
From: Ondrej Zary <[email protected]>
Convert 3c509 driver to
isa_driverandpnp_driver. The result is that autoloading using udev and hibernation works with ISA PnP cards. It also adds hibernation support for non-PnP ISA cards.xcvr module parameter was removed as its value was not used.
Tested using 3 ISA cards in various combinations of PnP and non-PnP modes. EISA and MCA only compile-tested.
Quoted 7 lines
Signed-off-by Ondrej Zary <[email protected]>Cc Jeff Garzik <[email protected]>Signed-off-by Andrew Morton <[email protected]>---
drivers/net/3c509.c | 729 +++++++++++++++++++++--------------------- 1 file changed, 372 insertions(+), 357 deletions(-)
applied 11-19