X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fpcmcia%2Fxirc2ps_cs.c;h=5879e7c36988e800fa21ebc21a48b3de7288c625;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=5be2ba3b03e81510acbca7ba79a4fdf045ee783f;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 5be2ba3b0..5879e7c36 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -79,8 +79,8 @@ #include #include #include +#include -#include #include #include #include @@ -89,7 +89,6 @@ #include #include -#include #include #ifndef MANFID_COMPAQ @@ -209,7 +208,7 @@ enum xirc_cmd { /* Commands */ #define XIRCREG45_REV 15 /* Revision Register (rd) */ #define XIRCREG50_IA 8 /* Individual Address (8-13) */ -static char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; +static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; /**************** * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If @@ -220,7 +219,7 @@ static char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; */ #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); +module_param(pc_debug, int, 0); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KDBG_XIRC args) #else #define DEBUG(n, args...) @@ -255,11 +254,8 @@ MODULE_PARM(pc_debug, "i"); MODULE_DESCRIPTION("Xircom PCMCIA ethernet driver"); MODULE_LICENSE("Dual MPL/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) -static int irq_list[4] = { -1 }; -MODULE_PARM(irq_list, "1-4i"); -INT_MODULE_PARM(irq_mask, 0xdeb8); INT_MODULE_PARM(if_port, 0); INT_MODULE_PARM(full_duplex, 0); INT_MODULE_PARM(do_sound, 1); @@ -277,12 +273,12 @@ INT_MODULE_PARM(lockup_hack, 0); /* anti lockup hack */ static unsigned maxrx_bytes = 22000; /* MII management prototypes */ -static void mii_idle(ioaddr_t ioaddr); -static void mii_putbit(ioaddr_t ioaddr, unsigned data); -static int mii_getbit(ioaddr_t ioaddr); -static void mii_wbits(ioaddr_t ioaddr, unsigned data, int len); -static unsigned mii_rd(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg); -static void mii_wr(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg, +static void mii_idle(kio_addr_t ioaddr); +static void mii_putbit(kio_addr_t ioaddr, unsigned data); +static int mii_getbit(kio_addr_t ioaddr); +static void mii_wbits(kio_addr_t ioaddr, unsigned data, int len); +static unsigned mii_rd(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg); +static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len); /* @@ -293,11 +289,9 @@ static void mii_wr(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg, * and ejection events. They are invoked from the event handler. */ -static int has_ce2_string(dev_link_t * link); -static void xirc2ps_config(dev_link_t * link); -static void xirc2ps_release(dev_link_t * link); -static int xirc2ps_event(event_t event, int priority, - event_callback_args_t * args); +static int has_ce2_string(struct pcmcia_device * link); +static int xirc2ps_config(struct pcmcia_device * link); +static void xirc2ps_release(struct pcmcia_device * link); /**************** * The attach() and detach() entry points are used to create and destroy @@ -305,8 +299,7 @@ static int xirc2ps_event(event_t event, int priority, * needed to manage one actual PCMCIA card. */ -static dev_link_t *xirc2ps_attach(void); -static void xirc2ps_detach(dev_link_t *); +static void xirc2ps_detach(struct pcmcia_device *p_dev); /**************** * You'll also need to prototype all the functions that will actually @@ -315,47 +308,32 @@ static void xirc2ps_detach(dev_link_t *); * less on other parts of the kernel. */ -static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); - -/* - * The dev_info variable is the "key" that is used to match up this - * device driver with appropriate cards, through the card configuration - * database. - */ - -static dev_info_t dev_info = "xirc2ps_cs"; +static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id); /**************** * A linked list of "instances" of the device. Each actual * PCMCIA card corresponds to one device instance, and is described - * by one dev_link_t structure (defined in ds.h). + * by one struct pcmcia_device structure (defined in ds.h). * * You may not want to use a linked list for this -- for example, the - * memory card driver uses an array of dev_link_t pointers, where minor + * memory card driver uses an array of struct pcmcia_device pointers, where minor * device numbers are used to derive the corresponding array index. */ -static dev_link_t *dev_list; - /**************** - * A dev_link_t structure has fields for most things that are needed - * to keep track of a socket, but there will usually be some device - * specific information that also needs to be kept track of. The - * 'priv' pointer in a dev_link_t structure can be used to point to - * a device-specific private data structure, like this. - * * A driver needs to provide a dev_node_t structure for each device * on a card. In some cases, there is only one device per card (for * example, ethernet cards, modems). In other cases, there may be * many actual or logical devices (SCSI adapters, memory cards with * multiple partitions). The dev_node_t structures need to be kept - * in a linked list starting at the 'dev' field of a dev_link_t + * in a linked list starting at the 'dev' field of a struct pcmcia_device * structure. We allocate them in the card's private data structure, * because they generally can't be allocated dynamically. */ typedef struct local_info_t { - dev_link_t link; + struct net_device *dev; + struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; int card_type; @@ -365,9 +343,10 @@ typedef struct local_info_t { int dingo; /* a CEM56 type card */ int new_mii; /* has full 10baseT/100baseT MII */ int modem; /* is a multi function card (i.e with a modem) */ - caddr_t dingo_ccr; /* only used for CEM56 cards */ + void __iomem *dingo_ccr; /* only used for CEM56 cards */ unsigned last_ptr_value; /* last packets transmitted value */ const char *manf_str; + struct work_struct tx_timeout_task; } local_info_t; /**************** @@ -375,14 +354,15 @@ typedef struct local_info_t { */ static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); static void do_tx_timeout(struct net_device *dev); +static void xirc2ps_tx_timeout_task(struct work_struct *work); static struct net_device_stats *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); -static int set_card_type(dev_link_t *link, const void *s); +static int set_card_type(struct pcmcia_device *link, const void *s); static int do_config(struct net_device *dev, struct ifmap *map); static int do_open(struct net_device *dev); static int do_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 hardreset(struct net_device *dev); static void do_reset(struct net_device *dev, int full); static int init_mii(struct net_device *dev); @@ -391,7 +371,7 @@ static int do_stop(struct net_device *dev); /*=============== Helper functions =========================*/ static int -first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int err; @@ -402,7 +382,7 @@ first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) } static int -next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int err; @@ -418,17 +398,12 @@ next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) #define PutByte(reg,value) outb((value), ioaddr+(reg)) #define PutWord(reg,value) outw((value), ioaddr+(reg)) -#define Wait(n) do { \ - set_current_state(TASK_UNINTERRUPTIBLE); \ - schedule_timeout(n); \ -} while (0) - /*====== Functions used for debugging =================================*/ #if defined(PCMCIA_DEBUG) && 0 /* reading regs may change system status */ static void PrintRegisters(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; if (pc_debug > 1) { int i, page; @@ -464,7 +439,7 @@ PrintRegisters(struct net_device *dev) * Turn around for read */ static void -mii_idle(ioaddr_t ioaddr) +mii_idle(kio_addr_t ioaddr) { PutByte(XIRCREG2_GPR2, 0x04|0); /* drive MDCK low */ udelay(1); @@ -476,7 +451,7 @@ mii_idle(ioaddr_t ioaddr) * Write a bit to MDI/O */ static void -mii_putbit(ioaddr_t ioaddr, unsigned data) +mii_putbit(kio_addr_t ioaddr, unsigned data) { #if 1 if (data) { @@ -509,7 +484,7 @@ mii_putbit(ioaddr_t ioaddr, unsigned data) * Get a bit from MDI/O */ static int -mii_getbit(ioaddr_t ioaddr) +mii_getbit(kio_addr_t ioaddr) { unsigned d; @@ -522,7 +497,7 @@ mii_getbit(ioaddr_t ioaddr) } static void -mii_wbits(ioaddr_t ioaddr, unsigned data, int len) +mii_wbits(kio_addr_t ioaddr, unsigned data, int len) { unsigned m = 1 << (len-1); for (; m; m >>= 1) @@ -530,7 +505,7 @@ mii_wbits(ioaddr_t ioaddr, unsigned data, int len) } static unsigned -mii_rd(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg) +mii_rd(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg) { int i; unsigned data=0, m; @@ -552,7 +527,7 @@ mii_rd(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg) } static void -mii_wr(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) +mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) { int i; @@ -580,31 +555,27 @@ mii_wr(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) * card insertion event. */ -static dev_link_t * -xirc2ps_attach(void) +static int +xirc2ps_probe(struct pcmcia_device *link) { - client_reg_t client_reg; - dev_link_t *link; struct net_device *dev; local_info_t *local; - int err; DEBUG(0, "attach()\n"); /* Allocate the device structure */ dev = alloc_etherdev(sizeof(local_info_t)); if (!dev) - return NULL; + return -ENOMEM; local = netdev_priv(dev); - link = &local->link; + local->dev = dev; + local->p_dev = link; link->priv = dev; /* General socket configuration */ 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; link->irq.Handler = xirc2ps_interrupt; link->irq.Instance = dev; @@ -621,27 +592,10 @@ xirc2ps_attach(void) #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = do_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task); #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 = &xirc2ps_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - if ((err = pcmcia_register_client(&link->handle, &client_reg))) { - cs_error(link->handle, RegisterClient, err); - xirc2ps_detach(link); - return NULL; - } - - return link; + return xirc2ps_config(link); } /* xirc2ps_attach */ /**************** @@ -652,40 +606,17 @@ xirc2ps_attach(void) */ static void -xirc2ps_detach(dev_link_t * link) +xirc2ps_detach(struct pcmcia_device *link) { struct net_device *dev = link->priv; - dev_link_t **linkp; DEBUG(0, "detach(0x%p)\n", link); - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) - break; - if (!*linkp) { - DEBUG(0, "detach(0x%p): dev_link lost\n", link); - return; - } - - if (link->dev) + if (link->dev_node) unregister_netdev(dev); - /* - * If the device is currently configured and active, we won't - * actually delete it yet. Instead, it is marked so that when - * the release() function is called, that will trigger a proper - * detach(). - */ - if (link->state & DEV_CONFIG) - xirc2ps_release(link); - - /* Break the link with Card Services */ - if (link->handle) - pcmcia_deregister_client(link->handle); + xirc2ps_release(link); - /* Unlink device structure, free it */ - *linkp = link->next; free_netdev(dev); } /* xirc2ps_detach */ @@ -708,7 +639,7 @@ xirc2ps_detach(dev_link_t * link) * */ static int -set_card_type(dev_link_t *link, const void *s) +set_card_type(struct pcmcia_device *link, const void *s) { struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); @@ -777,23 +708,11 @@ set_card_type(dev_link_t *link, const void *s) * Returns: true if this is a CE2 */ static int -has_ce2_string(dev_link_t * link) +has_ce2_string(struct pcmcia_device * p_dev) { - client_handle_t handle = link->handle; - tuple_t tuple; - cisparse_t parse; - u_char buf[256]; - - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = 254; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_VERS_1; - if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) { - if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) - return 1; - } - return 0; + if (p_dev->prod_id[2] && strstr(p_dev->prod_id[2], "CE2")) + return 1; + return 0; } /**************** @@ -801,15 +720,14 @@ has_ce2_string(dev_link_t * link) * is received, to configure the PCMCIA socket, and to make the * ethernet device available to the system. */ -static void -xirc2ps_config(dev_link_t * link) +static int +xirc2ps_config(struct pcmcia_device * link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); tuple_t tuple; cisparse_t parse; - ioaddr_t ioaddr; + kio_addr_t ioaddr; int err, i; u_char buf[64]; cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data; @@ -830,7 +748,7 @@ xirc2ps_config(dev_link_t * link) /* Is this a valid card */ tuple.DesiredTuple = CISTPL_MANFID; - if ((err=first_tuple(handle, &tuple, &parse))) { + if ((err=first_tuple(link, &tuple, &parse))) { printk(KNOT_XIRC "manfid not found in CIS\n"); goto failure; } @@ -864,17 +782,10 @@ xirc2ps_config(dev_link_t * link) goto failure; } - /* get configuration stuff */ - tuple.DesiredTuple = CISTPL_CONFIG; - if ((err=first_tuple(handle, &tuple, &parse))) - goto cis_error; - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* get the ethernet address from the CIS */ tuple.DesiredTuple = CISTPL_FUNCE; - for (err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse)) { + for (err = first_tuple(link, &tuple, &parse); !err; + err = next_tuple(link, &tuple, &parse)) { /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: * the first one with a length of zero the second correct - * so I skip all entries with length 0 */ @@ -884,8 +795,8 @@ xirc2ps_config(dev_link_t * link) } if (err) { /* not found: try to get the node-id from tuple 0x89 */ tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ - if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 && - (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) { + if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 && + (err = pcmcia_get_tuple_data(link, &tuple)) == 0) { if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) memcpy(&parse, buf, 8); else @@ -894,8 +805,8 @@ xirc2ps_config(dev_link_t * link) } if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ tuple.DesiredTuple = CISTPL_FUNCE; - for (err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse)) { + for (err = first_tuple(link, &tuple, &parse); !err; + err = next_tuple(link, &tuple, &parse)) { if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { buf[1] = 4; @@ -916,19 +827,10 @@ xirc2ps_config(dev_link_t * link) for (i=0; i < 6; i++) dev->dev_addr[i] = node_id->id[i]; - /* Configure card */ - link->state |= DEV_CONFIG; - link->io.IOAddrLines =10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; link->irq.Attributes = 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; if (local->modem) { int pass; @@ -944,14 +846,14 @@ xirc2ps_config(dev_link_t * link) * Ethernet port */ link->io.NumPorts1 = 16; /* no Mako stuff anymore */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse)) { + for (err = first_tuple(link, &tuple, &parse); !err; + err = next_tuple(link, &tuple, &parse)) { if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = ioaddr; - if (!(err=pcmcia_request_io(link->handle, &link->io))) + if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } } @@ -965,15 +867,15 @@ xirc2ps_config(dev_link_t * link) */ for (pass=0; pass < 2; pass++) { tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse)){ + for (err = first_tuple(link, &tuple, &parse); !err; + err = next_tuple(link, &tuple, &parse)){ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = link->io.BasePort2 + (pass ? (cf->index & 0x20 ? -24:8) : (cf->index & 0x20 ? 8:-24)); - if (!(err=pcmcia_request_io(link->handle, &link->io))) + if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } } @@ -988,12 +890,12 @@ xirc2ps_config(dev_link_t * link) link->io.NumPorts1 = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; - if (!(err=pcmcia_request_io(link->handle, &link->io))) + if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } link->io.BasePort1 = 0; /* let CS decide */ - if ((err=pcmcia_request_io(link->handle, &link->io))) { - cs_error(link->handle, RequestIO, err); + if ((err=pcmcia_request_io(link, &link->io))) { + cs_error(link, RequestIO, err); goto config_error; } } @@ -1005,8 +907,8 @@ xirc2ps_config(dev_link_t * link) * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ - if ((err=pcmcia_request_irq(link->handle, &link->irq))) { - cs_error(link->handle, RequestIRQ, err); + if ((err=pcmcia_request_irq(link, &link->irq))) { + cs_error(link, RequestIRQ, err); goto config_error; } @@ -1014,8 +916,8 @@ xirc2ps_config(dev_link_t * link) * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. */ - if ((err=pcmcia_request_configuration(link->handle, &link->conf))) { - cs_error(link->handle, RequestConfiguration, err); + if ((err=pcmcia_request_configuration(link, &link->conf))) { + cs_error(link, RequestConfiguration, err); goto config_error; } @@ -1032,15 +934,15 @@ xirc2ps_config(dev_link_t * link) reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_0; reg.Value = link->io.BasePort2 & 0xff; - if ((err = pcmcia_access_configuration_register(link->handle, ®))) { - cs_error(link->handle, AccessConfigurationRegister, err); + if ((err = pcmcia_access_configuration_register(link, ®))) { + cs_error(link, AccessConfigurationRegister, err); goto config_error; } reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_1; reg.Value = (link->io.BasePort2 >> 8) & 0xff; - if ((err = pcmcia_access_configuration_register(link->handle, ®))) { - cs_error(link->handle, AccessConfigurationRegister, err); + if ((err = pcmcia_access_configuration_register(link, ®))) { + cs_error(link, AccessConfigurationRegister, err); goto config_error; } @@ -1051,15 +953,15 @@ xirc2ps_config(dev_link_t * link) req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = req.Size = 0; req.AccessSpeed = 0; - if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) { - cs_error(link->handle, RequestWindow, err); + if ((err = pcmcia_request_window(&link, &req, &link->win))) { + cs_error(link, RequestWindow, err); goto config_error; } local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; mem.CardOffset = 0x0; mem.Page = 0; if ((err = pcmcia_map_mem_page(link->win, &mem))) { - cs_error(link->handle, MapMemPage, err); + cs_error(link, MapMemPage, err); goto config_error; } @@ -1119,12 +1021,12 @@ xirc2ps_config(dev_link_t * link) if (local->dingo) do_reset(dev, 1); /* a kludge to make the cem56 work */ - link->dev = &local->node; - link->state &= ~DEV_CONFIG_PENDING; + link->dev_node = &local->node; + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if ((err=register_netdev(dev))) { printk(KNOT_XIRC "register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto config_error; } @@ -1137,17 +1039,14 @@ xirc2ps_config(dev_link_t * link) printk("%c%02X", i?':':' ', dev->dev_addr[i]); printk("\n"); - return; + return 0; config_error: - link->state &= ~DEV_CONFIG_PENDING; xirc2ps_release(link); - return; + return -ENODEV; - cis_error: - printk(KNOT_XIRC "unable to parse CIS\n"); failure: - link->state &= ~DEV_CONFIG_PENDING; + return -ENODEV; } /* xirc2ps_config */ /**************** @@ -1156,88 +1055,46 @@ xirc2ps_config(dev_link_t * link) * still open, this will be postponed until it is closed. */ static void -xirc2ps_release(dev_link_t *link) +xirc2ps_release(struct pcmcia_device *link) { + DEBUG(0, "release(0x%p)\n", link); - DEBUG(0, "release(0x%p)\n", link); - - if (link->win) { - struct net_device *dev = link->priv; - local_info_t *local = netdev_priv(dev); - if (local->dingo) - iounmap(local->dingo_ccr - 0x0800); - pcmcia_release_window(link->win); - } - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; - + if (link->win) { + struct net_device *dev = link->priv; + local_info_t *local = netdev_priv(dev); + if (local->dingo) + iounmap(local->dingo_ccr - 0x0800); + } + pcmcia_disable_device(link); } /* xirc2ps_release */ /*====================================================================*/ -/**************** - * 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. - * - * When a CARD_REMOVAL event is received, we immediately set a flag - * to block future accesses to this device. All the functions that - * actually access the device should check this flag to make sure - * the card is still present. - */ -static int -xirc2ps_event(event_t event, int priority, - event_callback_args_t * args) +static int xirc2ps_suspend(struct pcmcia_device *link) { - dev_link_t *link = args->client_data; - struct net_device *dev = link->priv; - - DEBUG(0, "event(%d)\n", (int)event); + struct net_device *dev = link->priv; - switch (event) { - case CS_EVENT_REGISTRATION_COMPLETE: - DEBUG(0, "registration complete\n"); - break; - 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; - xirc2ps_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) { + if (link->open) { netif_device_detach(dev); do_powerdown(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) { + + return 0; +} + +static int xirc2ps_resume(struct pcmcia_device *link) +{ + struct net_device *dev = link->priv; + + if (link->open) { do_reset(dev,1); netif_device_attach(dev); - } } - break; - } - return 0; -} /* xirc2ps_event */ + + return 0; +} + /*====================================================================*/ @@ -1245,11 +1102,11 @@ xirc2ps_event(event_t event, int priority, * This is the Interrupt service route. */ static irqreturn_t -xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) +xirc2ps_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; local_info_t *lp = netdev_priv(dev); - ioaddr_t ioaddr; + kio_addr_t ioaddr; u_char saved_page; unsigned bytes_rcvd; unsigned int_status, eth_status, rx_status, tx_status; @@ -1354,7 +1211,7 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) unsigned i; u_long *p = skb_put(skb, pktlen); register u_long a; - ioaddr_t edpreg = ioaddr+XIRCREG_EDP-2; + kio_addr_t edpreg = ioaddr+XIRCREG_EDP-2; for (i=0; i < len ; i += 4, p++) { a = inl(edpreg); __asm__("rorl $16,%0\n\t" @@ -1468,25 +1325,34 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) /*====================================================================*/ static void -do_tx_timeout(struct net_device *dev) +xirc2ps_tx_timeout_task(struct work_struct *work) { - local_info_t *lp = netdev_priv(dev); - printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); - lp->stats.tx_errors++; + local_info_t *local = + container_of(work, local_info_t, tx_timeout_task); + struct net_device *dev = local->dev; /* reset the card */ do_reset(dev,1); dev->trans_start = jiffies; netif_wake_queue(dev); } +static void +do_tx_timeout(struct net_device *dev) +{ + local_info_t *lp = netdev_priv(dev); + lp->stats.tx_errors++; + printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); + schedule_work(&lp->tx_timeout_task); +} + static int do_start_xmit(struct sk_buff *skb, struct net_device *dev) { local_info_t *lp = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; int okay; unsigned freespace; - unsigned pktlen = skb? skb->len : 0; + unsigned pktlen = skb->len; DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", skb, dev, pktlen); @@ -1501,8 +1367,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) */ if (pktlen < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; pktlen = ETH_ZLEN; } @@ -1553,7 +1418,7 @@ do_get_stats(struct net_device *dev) static void set_addresses(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; local_info_t *lp = netdev_priv(dev); struct dev_mc_list *dmi = dev->mc_list; char *addr; @@ -1595,7 +1460,7 @@ set_addresses(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; SelectPage(0x42); if (dev->flags & IFF_PROMISC) { /* snoop */ @@ -1646,13 +1511,13 @@ static int do_open(struct net_device *dev) { local_info_t *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + struct pcmcia_device *link = lp->p_dev; DEBUG(0, "do_open(%p)\n", dev); /* Check that the PCMCIA card is still here. */ /* Physical device present signature. */ - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; /* okay */ @@ -1671,7 +1536,7 @@ static void netdev_get_drvinfo(struct net_device *dev, sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr); } -static struct ethtool_ops netdev_ethtool_ops = { +static const struct ethtool_ops netdev_ethtool_ops = { .get_drvinfo = netdev_get_drvinfo, }; @@ -1679,7 +1544,7 @@ static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { local_info_t *local = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; u16 *data = (u16 *)&rq->ifr_ifru; DEBUG(1, "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n", @@ -1692,7 +1557,7 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get the address of the PHY in use. */ data[0] = 0; /* we have only this address */ - /* fall trough */ + /* fall through */ case SIOCGMIIREG: /* Read the specified MII register. */ data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f); break; @@ -1711,33 +1576,33 @@ static void hardreset(struct net_device *dev) { local_info_t *local = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; SelectPage(4); udelay(1); PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ - Wait(HZ/25); /* wait 40 msec */ + msleep(40); /* wait 40 msec */ if (local->mohawk) PutByte(XIRCREG4_GPR1, 1); /* set bit 0: power up */ else PutByte(XIRCREG4_GPR1, 1 | 4); /* set bit 0: power up, bit 2: AIC */ - Wait(HZ/50); /* wait 20 msec */ + msleep(20); /* wait 20 msec */ } static void do_reset(struct net_device *dev, int full) { local_info_t *local = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; unsigned value; DEBUG(0, "%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full); hardreset(dev); PutByte(XIRCREG_CR, SoftReset); /* set */ - Wait(HZ/50); /* wait 20 msec */ + msleep(20); /* wait 20 msec */ PutByte(XIRCREG_CR, 0); /* clear */ - Wait(HZ/25); /* wait 40 msec */ + msleep(40); /* wait 40 msec */ if (local->mohawk) { SelectPage(4); /* set pin GP1 and GP2 to output (0x0c) @@ -1748,7 +1613,7 @@ do_reset(struct net_device *dev, int full) } /* give the circuits some time to power up */ - Wait(HZ/2); /* about 500ms */ + msleep(500); /* about 500ms */ local->last_ptr_value = 0; local->silicon = local->mohawk ? (GetByte(XIRCREG4_BOV) & 0x70) >> 4 @@ -1767,7 +1632,7 @@ do_reset(struct net_device *dev, int full) SelectPage(0x42); PutByte(XIRCREG42_SWC1, 0x80); } - Wait(HZ/25); /* wait 40 msec to let it complete */ + msleep(40); /* wait 40 msec to let it complete */ #ifdef PCMCIA_DEBUG if (pc_debug) { @@ -1826,7 +1691,7 @@ do_reset(struct net_device *dev, int full) printk(KERN_INFO "%s: MII selected\n", dev->name); SelectPage(2); PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08); - Wait(HZ/50); + msleep(20); } else { printk(KERN_INFO "%s: MII detected; using 10mbs\n", dev->name); @@ -1835,7 +1700,7 @@ do_reset(struct net_device *dev, int full) PutByte(XIRCREG42_SWC1, 0xC0); else /* enable 10BaseT */ PutByte(XIRCREG42_SWC1, 0x80); - Wait(HZ/25); /* wait 40 msec to let it complete */ + msleep(40); /* wait 40 msec to let it complete */ } if (full_duplex) PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR | FullDuplex)); @@ -1889,7 +1754,7 @@ static int init_mii(struct net_device *dev) { local_info_t *local = netdev_priv(dev); - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; unsigned control, status, linkpartner; int i; @@ -1928,7 +1793,7 @@ init_mii(struct net_device *dev) * Fixme: Better to use a timer here! */ for (i=0; i < 35; i++) { - Wait(HZ/10); /* wait 100 msec */ + msleep(100); /* wait 100 msec */ status = mii_rd(ioaddr, 0, 1); if ((status & 0x0020) && (status & 0x0004)) break; @@ -1962,7 +1827,7 @@ static void do_powerdown(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; DEBUG(0, "do_powerdown(%p)\n", dev); @@ -1974,9 +1839,9 @@ do_powerdown(struct net_device *dev) static int do_stop(struct net_device *dev) { - ioaddr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr = dev->base_addr; local_info_t *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + struct pcmcia_device *link = lp->p_dev; DEBUG(0, "do_stop(%p)\n", dev); @@ -1997,13 +1862,43 @@ do_stop(struct net_device *dev) return 0; } +static struct pcmcia_device_id xirc2ps_ids[] = { + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0089, 0x110a), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0138, 0x110a), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM33", 0x2e3ee845, 0x80609023), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), + PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf), + PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x010a), + PCMCIA_DEVICE_PROD_ID13("Toshiba Information Systems", "TPCENET", 0x1b3b94fe, 0xf381c1a2), + PCMCIA_DEVICE_PROD_ID13("Xircom", "CE3-10/100", 0x2e3ee845, 0x0ec0ac37), + PCMCIA_DEVICE_PROD_ID13("Xircom", "PS-CE2-10", 0x2e3ee845, 0x947d9073), + PCMCIA_DEVICE_PROD_ID13("Xircom", "R2E-100BTX", 0x2e3ee845, 0x2464a6e3), + PCMCIA_DEVICE_PROD_ID13("Xircom", "RE-10", 0x2e3ee845, 0x3e08d609), + PCMCIA_DEVICE_PROD_ID13("Xircom", "XE2000", 0x2e3ee845, 0xf7188e46), + PCMCIA_DEVICE_PROD_ID12("Compaq", "Ethernet LAN Card", 0x54f7c49c, 0x9fd2f0a2), + PCMCIA_DEVICE_PROD_ID12("Compaq", "Netelligent 10/100 PC Card", 0x54f7c49c, 0xefe96769), + PCMCIA_DEVICE_PROD_ID12("Intel", "EtherExpress(TM) PRO/100 PC Card Mobile Adapter16", 0x816cc815, 0x174397db), + PCMCIA_DEVICE_PROD_ID12("Toshiba", "10/100 Ethernet PC Card", 0x44a09d9c, 0xb44deecf), + /* also matches CFE-10 cards! */ + /* PCMCIA_DEVICE_MANF_CARD(0x0105, 0x010a), */ + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids); + + static struct pcmcia_driver xirc2ps_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "xirc2ps_cs", }, - .attach = xirc2ps_attach, - .detach = xirc2ps_detach, + .probe = xirc2ps_probe, + .remove = xirc2ps_detach, + .id_table = xirc2ps_ids, + .suspend = xirc2ps_suspend, + .resume = xirc2ps_resume, }; static int __init @@ -2016,9 +1911,6 @@ static void __exit exit_xirc2ps_cs(void) { pcmcia_unregister_driver(&xirc2ps_cs_driver); - - while (dev_list) - xirc2ps_detach(dev_list); } module_init(init_xirc2ps_cs); @@ -2027,26 +1919,20 @@ module_exit(exit_xirc2ps_cs); #ifndef MODULE static int __init setup_xirc2ps_cs(char *str) { - /* irq, irq_mask, if_port, full_duplex, do_sound, lockup_hack - * [,irq2 [,irq3 [,irq4]]] + /* if_port, full_duplex, do_sound, lockup_hack */ int ints[10] = { -1 }; str = get_options(str, 9, ints); #define MAYBE_SET(X,Y) if (ints[0] >= Y && ints[Y] != -1) { X = ints[Y]; } - MAYBE_SET(irq_list[0], 1); - MAYBE_SET(irq_mask, 2); MAYBE_SET(if_port, 3); MAYBE_SET(full_duplex, 4); MAYBE_SET(do_sound, 5); MAYBE_SET(lockup_hack, 6); - MAYBE_SET(irq_list[1], 7); - MAYBE_SET(irq_list[2], 8); - MAYBE_SET(irq_list[3], 9); #undef MAYBE_SET - return 0; + return 1; } __setup("xirc2ps_cs=", setup_xirc2ps_cs);