X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fairo_cs.c;h=27696c20f4c2cf4d8fd10a8abaa41d843fd0974e;hb=c52f33d05e5f8d59f02722fbc308f5f391575ca5;hp=836c71ff776278b97c1e67a5b1d99dfa9bba0baa;hpb=fd238232cd0ff4840ae6946bb338502154096d88;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 836c71f..27696c2 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -20,7 +20,6 @@ ======================================================================*/ -#include #ifdef __IN_PCMCIA_PACKAGE__ #include #endif @@ -80,8 +79,8 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); event handler. */ -static void airo_config(dev_link_t *link); -static void airo_release(dev_link_t *link); +static int airo_config(struct pcmcia_device *link); +static void airo_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -101,10 +100,10 @@ static void airo_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the aironet 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. */ @@ -114,7 +113,7 @@ static void airo_detach(struct pcmcia_device *p_dev); 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 shouldn't be allocated dynamically. @@ -141,14 +140,14 @@ typedef struct local_info_t { ======================================================================*/ -static int airo_attach(struct pcmcia_device *p_dev) +static int airo_probe(struct pcmcia_device *p_dev) { local_info_t *local; DEBUG(0, "airo_attach()\n"); /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; p_dev->irq.Handler = NULL; @@ -170,10 +169,7 @@ static int airo_attach(struct pcmcia_device *p_dev) } p_dev->priv = local; - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - airo_config(p_dev); - - return 0; + return airo_config(p_dev); } /* airo_attach */ /*====================================================================== @@ -185,14 +181,11 @@ static int airo_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void airo_detach(struct pcmcia_device *p_dev) +static void airo_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "airo_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - airo_release(link); + airo_release(link); if ( ((local_info_t*)link->priv)->eth_dev ) { stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); @@ -213,154 +206,135 @@ static void airo_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void airo_config(dev_link_t *link) +static int airo_cs_config_check(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data) +{ + win_req_t *req = priv_data; + + if (cfg->index == 0) + return -ENODEV; + + /* Does this card need audio output? */ + if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + p_dev->conf.Attributes |= CONF_ENABLE_SPKR; + p_dev->conf.Status = CCSR_AUDIO_ENA; + } + + /* Use power settings for Vcc and Vpp if present */ + /* Note that the CIS values need to be rescaled */ + if (cfg->vpp1.present & (1<conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; + else if (dflt->vpp1.present & (1<conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; + + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) + p_dev->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.BasePort1 = io->win[0].base; + p_dev->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + p_dev->io.Attributes2 = p_dev->io.Attributes1; + p_dev->io.BasePort2 = io->win[1].base; + p_dev->io.NumPorts2 = io->win[1].len; + } + } + + /* This reserves IO space but doesn't actually enable it */ + if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + return -ENODEV; + + /* + Now set up a common memory window, if needed. There is room + in the struct pcmcia_device structure for one memory window handle, + but if the base addresses need to be saved, or if multiple + windows are needed, the info should go in the private data + structure for this device. + + Note that the memory window base is a physical address, and + needs to be mapped to virtual space with ioremap() before it + is used. + */ + if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { + cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; + memreq_t map; + req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; + req->Base = mem->win[0].host_addr; + req->Size = mem->win[0].len; + req->AccessSpeed = 0; + if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) + return -ENODEV; + map.Page = 0; + map.CardOffset = mem->win[0].card_addr; + if (pcmcia_map_mem_page(p_dev->win, &map) != 0) + return -ENODEV; + } + /* If we got this far, we're cool! */ + return 0; +} + + +static int airo_config(struct pcmcia_device *link) { - client_handle_t handle; - tuple_t tuple; - cisparse_t parse; local_info_t *dev; + win_req_t *req; int last_fn, last_ret; - u_char buf[64]; - win_req_t req; - memreq_t map; - - handle = link->handle; + dev = link->priv; DEBUG(0, "airo_config(0x%p)\n", link); - + + req = kzalloc(sizeof(win_req_t), GFP_KERNEL); + if (!req) + return -ENOMEM; + /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - 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; - + * In this loop, we scan the CIS for configuration table + * entries, each of which describes a valid card + * configuration, including voltage, IO window, memory window, + * and interrupt settings. + * + * We make no assumptions about the card to be configured: we + * use just the information available in the CIS. In an ideal + * world, this would work for any PCMCIA card, but it requires + * a complete and accurate CIS. In practice, a driver usually + * "knows" most of these things without consulting the CIS, + * and most client drivers will only use the CIS to fill in + * implementation-defined details. + */ + last_ret = pcmcia_loop_config(link, airo_cs_config_check, req); + if (last_ret) + goto failed; + /* - In this loop, we scan the CIS for configuration table entries, - each of which describes a valid card configuration, including - voltage, IO window, memory window, and interrupt settings. - - We make no assumptions about the card to be configured: we use - just the information available in the CIS. In an ideal world, - this would work for any PCMCIA card, but it requires a complete - and accurate CIS. In practice, a driver usually "knows" most of - these things without consulting the CIS, and most client drivers - will only use the CIS to fill in implementation-defined details. + Allocate an interrupt line. Note that this does not assign a + handler to the interrupt, unless the 'Handler' member of the + irq structure is initialized. */ - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - while (1) { - cistpl_cftable_entry_t dflt = { 0 }; - cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) - goto next_entry; - - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; - if (cfg->index == 0) goto next_entry; - link->conf.ConfigIndex = cfg->index; - - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vpp1.present & (1<conf.Vpp = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<conf.Vpp = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - /* Do we need to allocate an interrupt? */ - if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) - link->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - link->io.NumPorts1 = link->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.BasePort1 = io->win[0].base; - link->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - link->io.Attributes2 = link->io.Attributes1; - link->io.BasePort2 = io->win[1].base; - link->io.NumPorts2 = io->win[1].len; - } - } - - /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link->handle, &link->io) != 0) - goto next_entry; - - /* - Now set up a common memory window, if needed. There is room - in the dev_link_t structure for one memory window handle, - but if the base addresses need to be saved, or if multiple - windows are needed, the info should go in the private data - structure for this device. - - Note that the memory window base is a physical address, and - needs to be mapped to virtual space with ioremap() before it - is used. - */ - if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { - cistpl_mem_t *mem = - (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; - req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; - req.Base = mem->win[0].host_addr; - req.Size = mem->win[0].len; - req.AccessSpeed = 0; - if (pcmcia_request_window(&link->handle, &req, &link->win) != 0) - goto next_entry; - map.Page = 0; map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(link->win, &map) != 0) - goto next_entry; - } - /* If we got this far, we're cool! */ - break; - - next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); - } - - /* - Allocate an interrupt line. Note that this does not assign a - handler to the interrupt, unless the 'Handler' member of the - irq structure is initialized. - */ if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); ((local_info_t*)link->priv)->eth_dev = init_airo_card( link->irq.AssignedIRQ, - link->io.BasePort1, 1, &handle_to_dev(handle) ); + link->io.BasePort1, 1, &handle_to_dev(link) ); if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; /* @@ -385,17 +359,18 @@ static void airo_config(dev_link_t *link) printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2+link->io.NumPorts2-1); if (link->win) - printk(", mem 0x%06lx-0x%06lx", req.Base, - req.Base+req.Size-1); + printk(", mem 0x%06lx-0x%06lx", req->Base, + req->Base+req->Size-1); printk("\n"); - - link->state &= ~DEV_CONFIG_PENDING; - return; - + kfree(req); + return 0; + cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); + failed: airo_release(link); - + kfree(req); + return -ENODEV; } /* airo_config */ /*====================================================================== @@ -406,29 +381,26 @@ static void airo_config(dev_link_t *link) ======================================================================*/ -static void airo_release(dev_link_t *link) +static void airo_release(struct pcmcia_device *link) { DEBUG(0, "airo_release(0x%p)\n", link); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int airo_suspend(struct pcmcia_device *p_dev) +static int airo_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *local = link->priv; - if (link->state & DEV_CONFIG) - netif_device_detach(local->eth_dev); + netif_device_detach(local->eth_dev); return 0; } -static int airo_resume(struct pcmcia_device *p_dev) +static int airo_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *local = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { reset_airo_card(local->eth_dev); netif_device_attach(local->eth_dev); } @@ -450,7 +422,7 @@ static struct pcmcia_driver airo_driver = { .drv = { .name = "airo_cs", }, - .probe = airo_attach, + .probe = airo_probe, .remove = airo_detach, .id_table = airo_ids, .suspend = airo_suspend,