X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fpcmcia%2F3c589_cs.c;h=875a0fe251e7bfab9ef409893a9216835855d992;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=be997bd296e722889b5da69b6ad038c6e8996e63;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index be997bd29..875a0fe25 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -38,8 +38,9 @@ #include #include #include +#include +#include -#include #include #include #include @@ -50,7 +51,6 @@ #include #include #include -#include /* To minimize the size of the driver source I only define operating constants if they are used several times. You'll need the manual @@ -105,7 +105,7 @@ enum RxFilter { #define TX_TIMEOUT ((400*HZ)/1000) struct el3_private { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; /* For transceiver monitoring */ @@ -116,7 +116,7 @@ struct el3_private { spinlock_t lock; }; -static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; +static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; /*====================================================================*/ @@ -126,16 +126,11 @@ MODULE_AUTHOR("David Hinds "); MODULE_DESCRIPTION("3Com 3c589 series PCMCIA ethernet driver"); MODULE_LICENSE("GPL"); -#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") +#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) /* Special hook for setting if_port when module is loaded */ INT_MODULE_PARM(if_port, 0); -/* Bit map of interrupts to choose from */ -INT_MODULE_PARM(irq_mask, 0xdeb8); -static int irq_list[4] = { -1 }; -MODULE_PARM(irq_list, "1-4i"); - #ifdef PCMCIA_DEBUG INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) @@ -147,12 +142,10 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; /*====================================================================*/ -static void tc589_config(dev_link_t *link); -static void tc589_release(dev_link_t *link); -static int tc589_event(event_t event, int priority, - event_callback_args_t *args); +static int tc589_config(struct pcmcia_device *link); +static void tc589_release(struct pcmcia_device *link); -static u16 read_eeprom(ioaddr_t ioaddr, int index); +static u16 read_eeprom(kio_addr_t ioaddr, int index); static void tc589_reset(struct net_device *dev); static void media_check(unsigned long arg); static int el3_config(struct net_device *dev, struct ifmap *map); @@ -167,12 +160,7 @@ static void el3_tx_timeout(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static struct ethtool_ops netdev_ethtool_ops; -static dev_info_t dev_info = "3c589_cs"; - -static dev_link_t *tc589_attach(void); -static void tc589_detach(dev_link_t *); - -static dev_link_t *dev_list; +static void tc589_detach(struct pcmcia_device *p_dev); /*====================================================================== @@ -182,42 +170,33 @@ static dev_link_t *dev_list; ======================================================================*/ -static dev_link_t *tc589_attach(void) +static int tc589_probe(struct pcmcia_device *link) { struct el3_private *lp; - client_reg_t client_reg; - dev_link_t *link; struct net_device *dev; - int i, ret; DEBUG(0, "3c589_attach()\n"); - + /* Create new ethernet device */ dev = alloc_etherdev(sizeof(struct el3_private)); if (!dev) - return NULL; + return -ENOMEM; lp = netdev_priv(dev); - link = &lp->link; link->priv = dev; + lp->p_dev = link; spin_lock_init(&lp->lock); link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &el3_interrupt; link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; - + /* The EL3-specific entries in the device structure. */ SET_MODULE_OWNER(dev); dev->hard_start_xmit = &el3_start_xmit; @@ -232,26 +211,7 @@ static dev_link_t *tc589_attach(void) #endif SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &tc589_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = pcmcia_register_client(&link->handle, &client_reg); - if (ret != 0) { - cs_error(link->handle, RegisterClient, ret); - tc589_detach(link); - return NULL; - } - - return link; + return tc589_config(link); } /* tc589_attach */ /*====================================================================== @@ -263,29 +223,17 @@ static dev_link_t *tc589_attach(void) ======================================================================*/ -static void tc589_detach(dev_link_t *link) +static void tc589_detach(struct pcmcia_device *link) { struct net_device *dev = link->priv; - dev_link_t **linkp; - + DEBUG(0, "3c589_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; - if (link->state & DEV_CONFIG) - tc589_release(link); - - if (link->handle) - pcmcia_deregister_client(link->handle); - - /* Unlink device structure, free bits */ - *linkp = link->next; - if (link->dev) + if (link->dev_node) unregister_netdev(dev); + + tc589_release(link); + free_netdev(dev); } /* tc589_detach */ @@ -300,16 +248,15 @@ static void tc589_detach(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void tc589_config(dev_link_t *link) +static int tc589_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; cisparse_t parse; u16 buf[32], *phys_addr; int last_fn, last_ret, i, j, multi = 0, fifo; - ioaddr_t ioaddr; + kio_addr_t ioaddr; char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; DEBUG(0, "3c589_config(0x%p)\n", link); @@ -317,43 +264,40 @@ static void tc589_config(dev_link_t *link) phys_addr = (u16 *)dev->dev_addr; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Is this a 3c562? */ tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = TUPLE_RETURN_COMMON; - if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && - (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) { + if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && + (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { if (le16_to_cpu(buf[0]) != MANFID_3COM) printk(KERN_INFO "3c589_cs: hmmm, is this really a " "3Com card??\n"); multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); } - - /* Configure card */ - link->state |= DEV_CONFIG; /* For the 3c562, the base address must be xx00-xx7f */ link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x10) { if (multi && (j & 0x80)) continue; link->io.BasePort1 = j ^ 0x300; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -363,8 +307,8 @@ static void tc589_config(dev_link_t *link) /* The 3c589 has an extra EEPROM for configuration info, including the hardware address. The 3c562 puts the address in the CIS. */ tuple.DesiredTuple = 0x88; - if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { - pcmcia_get_tuple_data(handle, &tuple); + if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { + pcmcia_get_tuple_data(link, &tuple); for (i = 0; i < 3; i++) phys_addr[i] = htons(buf[i]); } else { @@ -388,12 +332,12 @@ static void tc589_config(dev_link_t *link) else printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); - link->dev = &lp->node; - link->state &= ~DEV_CONFIG_PENDING; + link->dev_node = &lp->node; + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } @@ -407,14 +351,13 @@ static void tc589_config(dev_link_t *link) printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], if_names[dev->if_port]); - return; + return 0; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: tc589_release(link); - return; - + return -ENODEV; } /* tc589_config */ /*====================================================================== @@ -425,71 +368,32 @@ failed: ======================================================================*/ -static void tc589_release(dev_link_t *link) +static void tc589_release(struct pcmcia_device *link) { - DEBUG(0, "3c589_release(0x%p)\n", link); - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link); } -/*====================================================================== +static int tc589_suspend(struct pcmcia_device *link) +{ + struct net_device *dev = link->priv; - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the net drivers from trying - to talk to the card any more. - -======================================================================*/ + if (link->open) + netif_device_detach(dev); -static int tc589_event(event_t event, int priority, - event_callback_args_t *args) + return 0; +} + +static int tc589_resume(struct pcmcia_device *link) { - dev_link_t *link = args->client_data; - struct net_device *dev = link->priv; - - DEBUG(1, "3c589_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) { - netif_device_detach(dev); - tc589_release(link); - } - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - tc589_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { + struct net_device *dev = link->priv; + + if (link->open) { tc589_reset(dev); netif_device_attach(dev); - } } - break; - } - return 0; -} /* tc589_event */ + + return 0; +} /*====================================================================*/ @@ -511,7 +415,7 @@ static void tc589_wait_for_completion(struct net_device *dev, int cmd) Read a word from the EEPROM using the regular EEPROM access register. Assume that we are in register window zero. */ -static u16 read_eeprom(ioaddr_t ioaddr, int index) +static u16 read_eeprom(kio_addr_t ioaddr, int index) { int i; outw(EEPROM_READ + index, ioaddr + 10); @@ -529,7 +433,7 @@ static u16 read_eeprom(ioaddr_t ioaddr, int index) static void tc589_set_xcvr(struct net_device *dev, int if_port) { struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; EL3WINDOW(0); switch (if_port) { @@ -551,7 +455,7 @@ static void tc589_set_xcvr(struct net_device *dev, int if_port) static void dump_status(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; EL3WINDOW(1); printk(KERN_INFO " irq status %04x, rx status %04x, tx status " "%02x tx free %04x\n", inw(ioaddr+EL3_STATUS), @@ -567,7 +471,7 @@ static void dump_status(struct net_device *dev) /* Reset and restore all of the 3c589 registers. */ static void tc589_reset(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; int i; EL3WINDOW(0); @@ -651,9 +555,9 @@ static int el3_config(struct net_device *dev, struct ifmap *map) static int el3_open(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + struct pcmcia_device *link = lp->p_dev; - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; link->open++; @@ -675,7 +579,7 @@ static int el3_open(struct net_device *dev) static void el3_tx_timeout(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; printk(KERN_WARNING "%s: Transmit timed out!\n", dev->name); dump_status(dev); @@ -690,7 +594,7 @@ static void el3_tx_timeout(struct net_device *dev) static void pop_tx_status(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; int i; /* Clear the Tx status stack. */ @@ -712,7 +616,7 @@ static void pop_tx_status(struct net_device *dev) static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; struct el3_private *priv = netdev_priv(dev); DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " @@ -745,7 +649,8 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr, status; + kio_addr_t ioaddr; + __u16 status; int i = 0, handled = 1; if (!netif_device_present(dev)) @@ -830,7 +735,7 @@ static void media_check(unsigned long arg) { struct net_device *dev = (struct net_device *)(arg); struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; u16 media, errs; unsigned long flags; @@ -860,7 +765,7 @@ static void media_check(unsigned long arg) media = inw(ioaddr+WN4_MEDIA) & 0xc810; /* Ignore collisions unless we've had no irq's recently */ - if (jiffies - lp->last_irq < HZ) { + if (time_before(jiffies, lp->last_irq + HZ)) { media &= ~0x0010; } else { /* Try harder to detect carrier errors */ @@ -911,9 +816,9 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); unsigned long flags; - dev_link_t *link = &lp->link; + struct pcmcia_device *link = lp->p_dev; - if (DEV_OK(link)) { + if (pcmcia_dev_present(link)) { spin_lock_irqsave(&lp->lock, flags); update_stats(dev); spin_unlock_irqrestore(&lp->lock, flags); @@ -932,7 +837,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) static void update_stats(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; DEBUG(2, "%s: updating the statistics.\n", dev->name); /* Turn off statistics updates while reading. */ @@ -959,7 +864,7 @@ static void update_stats(struct net_device *dev) static int el3_rx(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; int worklimit = 32; short rx_status; @@ -1013,11 +918,11 @@ static int el3_rx(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; - ioaddr_t ioaddr = dev->base_addr; + struct pcmcia_device *link = lp->p_dev; + kio_addr_t ioaddr = dev->base_addr; u16 opts = SetRxFilter | RxStation | RxBroadcast; - if (!(DEV_OK(link))) return; + if (!pcmcia_dev_present(link)) return; if (dev->flags & IFF_PROMISC) opts |= RxMulticast | RxProm; else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) @@ -1028,12 +933,12 @@ static void set_multicast_list(struct net_device *dev) static int el3_close(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; - ioaddr_t ioaddr = dev->base_addr; + struct pcmcia_device *link = lp->p_dev; + kio_addr_t ioaddr = dev->base_addr; DEBUG(1, "%s: shutting down ethercard.\n", dev->name); - if (DEV_OK(link)) { + if (pcmcia_dev_present(link)) { /* Turn off statistics ASAP. We update lp->stats below. */ outw(StatsDisable, ioaddr + EL3_CMD); @@ -1067,13 +972,27 @@ static int el3_close(struct net_device *dev) return 0; } +static struct pcmcia_device_id tc589_ids[] = { + PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562), + PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), + PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), + PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, tc589_ids); + static struct pcmcia_driver tc589_driver = { .owner = THIS_MODULE, .drv = { .name = "3c589_cs", }, - .attach = tc589_attach, - .detach = tc589_detach, + .probe = tc589_probe, + .remove = tc589_detach, + .id_table = tc589_ids, + .suspend = tc589_suspend, + .resume = tc589_resume, }; static int __init init_tc589(void) @@ -1084,8 +1003,6 @@ static int __init init_tc589(void) static void __exit exit_tc589(void) { pcmcia_unregister_driver(&tc589_driver); - while (dev_list != NULL) - tc589_detach(dev_list); } module_init(init_tc589);