X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fpcmcia%2F3c589_cs.c;fp=drivers%2Fnet%2Fpcmcia%2F3c589_cs.c;h=1c3c9c666f741a9e7cbeb80627b2f7776d33e79b;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=875a0fe251e7bfab9ef409893a9216835855d992;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 875a0fe25..1c3c9c666 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -105,7 +104,7 @@ enum RxFilter { #define TX_TIMEOUT ((400*HZ)/1000) struct el3_private { - struct pcmcia_device *p_dev; + dev_link_t link; dev_node_t node; struct net_device_stats stats; /* For transceiver monitoring */ @@ -116,7 +115,7 @@ struct el3_private { spinlock_t lock; }; -static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; +static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; /*====================================================================*/ @@ -142,8 +141,8 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; /*====================================================================*/ -static int tc589_config(struct pcmcia_device *link); -static void tc589_release(struct pcmcia_device *link); +static void tc589_config(dev_link_t *link); +static void tc589_release(dev_link_t *link); static u16 read_eeprom(kio_addr_t ioaddr, int index); static void tc589_reset(struct net_device *dev); @@ -170,9 +169,10 @@ static void tc589_detach(struct pcmcia_device *p_dev); ======================================================================*/ -static int tc589_probe(struct pcmcia_device *link) +static int tc589_attach(struct pcmcia_device *p_dev) { struct el3_private *lp; + dev_link_t *link; struct net_device *dev; DEBUG(0, "3c589_attach()\n"); @@ -182,8 +182,8 @@ static int tc589_probe(struct pcmcia_device *link) if (!dev) 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; @@ -193,6 +193,7 @@ static int tc589_probe(struct pcmcia_device *link) 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; @@ -211,7 +212,13 @@ static int tc589_probe(struct pcmcia_device *link) #endif SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - return tc589_config(link); + link->handle = p_dev; + p_dev->instance = link; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + tc589_config(link); + + return 0; } /* tc589_attach */ /*====================================================================== @@ -223,16 +230,18 @@ static int tc589_probe(struct pcmcia_device *link) ======================================================================*/ -static void tc589_detach(struct pcmcia_device *link) +static void tc589_detach(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "3c589_detach(0x%p)\n", link); - if (link->dev_node) + if (link->dev) unregister_netdev(dev); - tc589_release(link); + if (link->state & DEV_CONFIG) + tc589_release(link); free_netdev(dev); } /* tc589_detach */ @@ -248,8 +257,9 @@ static void tc589_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int tc589_config(struct pcmcia_device *link) +static void tc589_config(dev_link_t *link) { + client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; @@ -264,40 +274,43 @@ static int tc589_config(struct pcmcia_device *link) phys_addr = (u16 *)dev->dev_addr; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &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(link, &tuple) == CS_SUCCESS) && - (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { + if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && + (pcmcia_get_tuple_data(handle, &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, &link->io); + i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { - cs_error(link, RequestIO, i); + cs_error(link->handle, RequestIO, i); goto failed; } - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -307,8 +320,8 @@ static int tc589_config(struct pcmcia_device *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(link, &tuple) == CS_SUCCESS) { - pcmcia_get_tuple_data(link, &tuple); + if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { + pcmcia_get_tuple_data(handle, &tuple); for (i = 0; i < 3; i++) phys_addr[i] = htons(buf[i]); } else { @@ -332,12 +345,13 @@ static int tc589_config(struct pcmcia_device *link) else printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); - link->dev_node = &lp->node; - SET_NETDEV_DEV(dev, &handle_to_dev(link)); + link->dev = &lp->node; + link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); - link->dev_node = NULL; + link->dev = NULL; goto failed; } @@ -351,13 +365,14 @@ static int tc589_config(struct pcmcia_device *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 0; + return; cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link->handle, last_fn, last_ret); failed: tc589_release(link); - return -ENODEV; + return; + } /* tc589_config */ /*====================================================================== @@ -368,28 +383,44 @@ failed: ======================================================================*/ -static void tc589_release(struct pcmcia_device *link) +static void tc589_release(dev_link_t *link) { - pcmcia_disable_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; } -static int tc589_suspend(struct pcmcia_device *link) +static int tc589_suspend(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - if (link->open) - netif_device_detach(dev); + link->state |= DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + if (link->open) + netif_device_detach(dev); + pcmcia_release_configuration(link->handle); + } return 0; } -static int tc589_resume(struct pcmcia_device *link) +static int tc589_resume(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - if (link->open) { - tc589_reset(dev); - netif_device_attach(dev); + link->state &= ~DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + pcmcia_request_configuration(link->handle, &link->conf); + if (link->open) { + tc589_reset(dev); + netif_device_attach(dev); + } } return 0; @@ -555,9 +586,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); - struct pcmcia_device *link = lp->p_dev; + dev_link_t *link = &lp->link; - if (!pcmcia_dev_present(link)) + if (!DEV_OK(link)) return -ENODEV; link->open++; @@ -765,7 +796,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 (time_before(jiffies, lp->last_irq + HZ)) { + if (jiffies - lp->last_irq < HZ) { media &= ~0x0010; } else { /* Try harder to detect carrier errors */ @@ -816,9 +847,9 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); unsigned long flags; - struct pcmcia_device *link = lp->p_dev; + dev_link_t *link = &lp->link; - if (pcmcia_dev_present(link)) { + if (DEV_OK(link)) { spin_lock_irqsave(&lp->lock, flags); update_stats(dev); spin_unlock_irqrestore(&lp->lock, flags); @@ -918,11 +949,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); - struct pcmcia_device *link = lp->p_dev; + dev_link_t *link = &lp->link; kio_addr_t ioaddr = dev->base_addr; u16 opts = SetRxFilter | RxStation | RxBroadcast; - if (!pcmcia_dev_present(link)) return; + if (!(DEV_OK(link))) return; if (dev->flags & IFF_PROMISC) opts |= RxMulticast | RxProm; else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) @@ -933,12 +964,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); - struct pcmcia_device *link = lp->p_dev; + dev_link_t *link = &lp->link; kio_addr_t ioaddr = dev->base_addr; DEBUG(1, "%s: shutting down ethercard.\n", dev->name); - if (pcmcia_dev_present(link)) { + if (DEV_OK(link)) { /* Turn off statistics ASAP. We update lp->stats below. */ outw(StatsDisable, ioaddr + EL3_CMD); @@ -988,7 +1019,7 @@ static struct pcmcia_driver tc589_driver = { .drv = { .name = "3c589_cs", }, - .probe = tc589_probe, + .probe = tc589_attach, .remove = tc589_detach, .id_table = tc589_ids, .suspend = tc589_suspend,