X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fpcmcia%2F3c574_cs.c;h=448bf4a780163751bc154d543b7289e1d50dcf67;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=7c4ed0ddd12a63f2995d4a2eae9b1405c4592b8f;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 7c4ed0ddd..448bf4a78 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -84,8 +84,8 @@ earlier 3Com products. #include #include #include +#include -#include #include #include #include @@ -97,7 +97,6 @@ earlier 3Com products. #include #include #include -#include /*====================================================================*/ @@ -107,12 +106,7 @@ MODULE_AUTHOR("David Hinds "); MODULE_DESCRIPTION("3Com 3c574 series PCMCIA ethernet driver"); MODULE_LICENSE("GPL"); -#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") - -/* Now-standard PC card module parameters. */ -INT_MODULE_PARM(irq_mask, 0xdeb8); -static int irq_list[4] = { -1 }; -MODULE_PARM(irq_list, "1-4i"); +#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ INT_MODULE_PARM(max_interrupt_work, 32); @@ -210,7 +204,7 @@ enum Window4 { /* Window 4: Xcvr/media bits. */ #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ struct el3_private { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; u16 advertising, partner; /* NWay media advertisement */ @@ -231,37 +225,30 @@ static char mii_preamble_required = 0; /* Index of functions. */ -static void tc574_config(dev_link_t *link); -static void tc574_release(dev_link_t *link); -static int tc574_event(event_t event, int priority, - event_callback_args_t *args); +static int tc574_config(struct pcmcia_device *link); +static void tc574_release(struct pcmcia_device *link); -static void mdio_sync(ioaddr_t ioaddr, int bits); -static int mdio_read(ioaddr_t ioaddr, int phy_id, int location); -static void mdio_write(ioaddr_t ioaddr, int phy_id, int location, int value); -static unsigned short read_eeprom(ioaddr_t ioaddr, int index); +static void mdio_sync(kio_addr_t ioaddr, int bits); +static int mdio_read(kio_addr_t ioaddr, int phy_id, int location); +static void mdio_write(kio_addr_t ioaddr, int phy_id, int location, int value); +static unsigned short read_eeprom(kio_addr_t ioaddr, int index); static void tc574_wait_for_completion(struct net_device *dev, int cmd); static void tc574_reset(struct net_device *dev); static void media_check(unsigned long arg); static int el3_open(struct net_device *dev); static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t el3_interrupt(int irq, void *dev_id); static void update_stats(struct net_device *dev); static struct net_device_stats *el3_get_stats(struct net_device *dev); static int el3_rx(struct net_device *dev, int worklimit); static int el3_close(struct net_device *dev); static void el3_tx_timeout(struct net_device *dev); static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static struct ethtool_ops netdev_ethtool_ops; +static const struct ethtool_ops netdev_ethtool_ops; static void set_rx_mode(struct net_device *dev); -static dev_info_t dev_info = "3c574_cs"; - -static dev_link_t *tc574_attach(void); -static void tc574_detach(dev_link_t *); - -static dev_link_t *dev_list; +static void tc574_detach(struct pcmcia_device *p_dev); /* tc574_attach() creates an "instance" of the driver, allocating @@ -269,41 +256,31 @@ static dev_link_t *dev_list; with Card Services. */ -static dev_link_t *tc574_attach(void) +static int tc574_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, "3c574_attach()\n"); /* Create the PC card device object. */ 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->window_lock); link->io.NumPorts1 = 32; 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. */ dev->hard_start_xmit = &el3_start_xmit; @@ -318,26 +295,7 @@ static dev_link_t *tc574_attach(void) dev->watchdog_timeo = TX_TIMEOUT; #endif - /* 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 = &tc574_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); - tc574_detach(link); - return NULL; - } - - return link; + return tc574_config(link); } /* tc574_attach */ /* @@ -349,30 +307,17 @@ static dev_link_t *tc574_attach(void) */ -static void tc574_detach(dev_link_t *link) +static void tc574_detach(struct pcmcia_device *link) { struct net_device *dev = link->priv; - dev_link_t **linkp; DEBUG(0, "3c574_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->dev) + if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - tc574_release(link); - - if (link->handle) - pcmcia_deregister_client(link->handle); + tc574_release(link); - /* Unlink device structure, free bits */ - *linkp = link->next; free_netdev(dev); } /* tc574_detach */ @@ -385,18 +330,16 @@ static void tc574_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 char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; +static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; -static void tc574_config(dev_link_t *link) +static int tc574_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; unsigned short buf[32]; int last_fn, last_ret, i, j; - ioaddr_t ioaddr; + kio_addr_t ioaddr; u16 *phys_addr; char *cardname; union wn3_config config; @@ -405,32 +348,18 @@ static void tc574_config(dev_link_t *link) DEBUG(0, "3c574_config(0x%p)\n", link); - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - 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]; - - /* Configure card */ - link->state |= DEV_CONFIG; - link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x20) { 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; @@ -440,9 +369,13 @@ static void tc574_config(dev_link_t *link) /* The 3c574 normally uses an EEPROM for configuration info, including the hardware address. The future products may include a modem chip and put the address in the CIS. */ + tuple.Attributes = 0; + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleDataMax = 64; + tuple.TupleOffset = 0; 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 { @@ -455,12 +388,9 @@ static void tc574_config(dev_link_t *link) goto failed; } } - tuple.DesiredTuple = CISTPL_VERS_1; - if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS && - pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS && - pcmcia_parse_tuple(handle, &tuple, &parse) == CS_SUCCESS) { - cardname = parse.version_1.str + parse.version_1.ofs[1]; - } else + if (link->prod_id[1]) + cardname = link->prod_id[1]; + else cardname = "3Com 3c574"; { @@ -517,12 +447,12 @@ static void tc574_config(dev_link_t *link) } } - link->state &= ~DEV_CONFIG_PENDING; - link->dev = &lp->node; + link->dev_node = &lp->node; + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } @@ -536,13 +466,13 @@ static void tc574_config(dev_link_t *link) 8 << config.u.ram_size, ram_split[config.u.ram_split], config.u.autoselect ? "autoselect " : ""); - return; + return 0; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: tc574_release(link); - return; + return -ENODEV; } /* tc574_config */ @@ -552,71 +482,36 @@ failed: still open, this will be postponed until it is closed. */ -static void tc574_release(dev_link_t *link) +static void tc574_release(struct pcmcia_device *link) { - DEBUG(0, "3c574_release(0x%p)\n", link); + pcmcia_disable_device(link); +} - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); +static int tc574_suspend(struct pcmcia_device *link) +{ + struct net_device *dev = link->priv; - link->state &= ~DEV_CONFIG; -} + if (link->open) + netif_device_detach(dev); -/* - 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. -*/ + return 0; +} -static int tc574_event(event_t event, int priority, - event_callback_args_t *args) +static int tc574_resume(struct pcmcia_device *link) { - dev_link_t *link = args->client_data; struct net_device *dev = link->priv; - DEBUG(1, "3c574_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); - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - tc574_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) { - tc574_reset(dev); - netif_device_attach(dev); - } - } - break; + if (link->open) { + tc574_reset(dev); + netif_device_attach(dev); } + return 0; -} /* tc574_event */ +} 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), @@ -645,7 +540,7 @@ static void tc574_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 unsigned short read_eeprom(ioaddr_t ioaddr, int index) +static unsigned short read_eeprom(kio_addr_t ioaddr, int index) { int timer; outw(EEPROM_Read + index, ioaddr + Wn0EepromCmd); @@ -673,9 +568,9 @@ static unsigned short read_eeprom(ioaddr_t ioaddr, int index) /* Generate the preamble required for initial synchronization and a few older transceivers. */ -static void mdio_sync(ioaddr_t ioaddr, int bits) +static void mdio_sync(kio_addr_t ioaddr, int bits) { - int mdio_addr = ioaddr + Wn4_PhysicalMgmt; + kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt; /* Establish sync by sending at least 32 logic ones. */ while (-- bits >= 0) { @@ -684,12 +579,12 @@ static void mdio_sync(ioaddr_t ioaddr, int bits) } } -static int mdio_read(ioaddr_t ioaddr, int phy_id, int location) +static int mdio_read(kio_addr_t ioaddr, int phy_id, int location) { int i; int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; unsigned int retval = 0; - int mdio_addr = ioaddr + Wn4_PhysicalMgmt; + kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt; if (mii_preamble_required) mdio_sync(ioaddr, 32); @@ -709,10 +604,10 @@ static int mdio_read(ioaddr_t ioaddr, int phy_id, int location) return (retval>>1) & 0xffff; } -static void mdio_write(ioaddr_t ioaddr, int phy_id, int location, int value) +static void mdio_write(kio_addr_t ioaddr, int phy_id, int location, int value) { int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; - int mdio_addr = ioaddr + Wn4_PhysicalMgmt; + kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt; int i; if (mii_preamble_required) @@ -737,7 +632,8 @@ static void mdio_write(ioaddr_t ioaddr, int phy_id, int location, int value) static void tc574_reset(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - int i, ioaddr = dev->base_addr; + int i; + kio_addr_t ioaddr = dev->base_addr; unsigned long flags; tc574_wait_for_completion(dev, TotalReset|0x10); @@ -818,9 +714,9 @@ static void tc574_reset(struct net_device *dev) 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++; @@ -841,7 +737,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_NOTICE "%s: Transmit timed out!\n", dev->name); dump_status(dev); @@ -856,7 +752,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. */ @@ -879,7 +775,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 *lp = netdev_priv(dev); unsigned long flags; @@ -909,11 +805,12 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* The EL3 interrupt handler. */ -static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t el3_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr, status; + kio_addr_t ioaddr; + unsigned status; int work_budget = max_interrupt_work; int handled = 0; @@ -1006,7 +903,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; unsigned long flags; unsigned short /* cable, */ media, partner; @@ -1018,7 +915,7 @@ static void media_check(unsigned long arg) if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) { if (!lp->fast_poll) printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); - el3_interrupt(dev->irq, lp, NULL); + el3_interrupt(dev->irq, lp); lp->fast_poll = HZ; } if (lp->fast_poll) { @@ -1095,7 +992,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; u8 rx, tx, up; DEBUG(2, "%s: updating the statistics.\n", dev->name); @@ -1132,7 +1029,7 @@ static void update_stats(struct net_device *dev) static int el3_rx(struct net_device *dev, int worklimit) { struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; short rx_status; DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", @@ -1186,7 +1083,7 @@ static void netdev_get_drvinfo(struct net_device *dev, strcpy(info->driver, "3c574_cs"); } -static struct ethtool_ops netdev_ethtool_ops = { +static const struct ethtool_ops netdev_ethtool_ops = { .get_drvinfo = netdev_get_drvinfo, }; @@ -1194,7 +1091,7 @@ static struct ethtool_ops netdev_ethtool_ops = { static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct el3_private *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; u16 *data = (u16 *)&rq->ifr_ifru; int phy = lp->phys & 0x1f; @@ -1248,7 +1145,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static void set_rx_mode(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; if (dev->flags & IFF_PROMISC) outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm, @@ -1261,13 +1158,13 @@ static void set_rx_mode(struct net_device *dev) static int el3_close(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + struct pcmcia_device *link = lp->p_dev; DEBUG(2, "%s: shutting down ethercard.\n", dev->name); - if (DEV_OK(link)) { + if (pcmcia_dev_present(link)) { unsigned long flags; /* Turn off statistics ASAP. We update lp->stats below. */ @@ -1282,6 +1179,9 @@ static int el3_close(struct net_device *dev) spin_lock_irqsave(&lp->window_lock, flags); update_stats(dev); spin_unlock_irqrestore(&lp->window_lock, flags); + + /* force interrupts off */ + outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); } link->open--; @@ -1291,13 +1191,23 @@ static int el3_close(struct net_device *dev) return 0; } +static struct pcmcia_device_id tc574_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "3CCFEM556.cis"), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, tc574_ids); + static struct pcmcia_driver tc574_driver = { .owner = THIS_MODULE, .drv = { .name = "3c574_cs", }, - .attach = tc574_attach, - .detach = tc574_detach, + .probe = tc574_probe, + .remove = tc574_detach, + .id_table = tc574_ids, + .suspend = tc574_suspend, + .resume = tc574_resume, }; static int __init init_tc574(void) @@ -1308,8 +1218,6 @@ static int __init init_tc574(void) static void __exit exit_tc574(void) { pcmcia_unregister_driver(&tc574_driver); - while (dev_list != NULL) - tc574_detach(dev_list); } module_init(init_tc574);