X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fpcmcia%2Fnsp_cs.c;fp=drivers%2Fscsi%2Fpcmcia%2Fnsp_cs.c;h=9e3ab3fd53555528471ef7d489c877c001ffab58;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=0d4c04e1f3de3f941655ec67a023992e77d46f04;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 0d4c04e1f..9e3ab3fd5 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1593,11 +1593,11 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt) configure the card at this point -- we wait until we receive a card insertion event. ======================================================================*/ -static int nsp_cs_probe(struct pcmcia_device *link) +static int nsp_cs_attach(struct pcmcia_device *p_dev) { scsi_info_t *info; + dev_link_t *link; nsp_hw_data *data = &nsp_data_base; - int ret; nsp_dbg(NSP_DEBUG_INIT, "in"); @@ -1605,7 +1605,7 @@ static int nsp_cs_probe(struct pcmcia_device *link) info = kmalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { return -ENOMEM; } memset(info, 0, sizeof(*info)); - info->p_dev = link; + link = &info->link; link->priv = info; data->ScsiInfo = info; @@ -1623,17 +1623,22 @@ static int nsp_cs_probe(struct pcmcia_device *link) /* Interrupt handler */ link->irq.Handler = &nspintr; link->irq.Instance = info; - link->irq.Attributes |= IRQF_SHARED; + link->irq.Attributes |= (SA_SHIRQ | SA_SAMPLE_RANDOM); /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - ret = nsp_cs_config(link); + link->handle = p_dev; + p_dev->instance = link; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + nsp_cs_config(link); nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); - return ret; + return 0; } /* nsp_cs_attach */ @@ -1643,12 +1648,16 @@ static int nsp_cs_probe(struct pcmcia_device *link) structures are freed. Otherwise, the structures will be freed when the device is released. ======================================================================*/ -static void nsp_cs_detach(struct pcmcia_device *link) +static void nsp_cs_detach(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); + nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); - ((scsi_info_t *)link->priv)->stop = 1; - nsp_cs_release(link); + if (link->state & DEV_CONFIG) { + ((scsi_info_t *)link->priv)->stop = 1; + nsp_cs_release(link); + } kfree(link->priv); link->priv = NULL; @@ -1663,9 +1672,9 @@ static void nsp_cs_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 nsp_cs_config(struct pcmcia_device *link) +static void nsp_cs_config(dev_link_t *link) { - int ret; + client_handle_t handle = link->handle; scsi_info_t *info = link->priv; tuple_t tuple; cisparse_t parse; @@ -1689,22 +1698,26 @@ static int nsp_cs_config(struct pcmcia_device *link) tuple.TupleData = tuple_data; tuple.TupleDataMax = sizeof(tuple_data); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); + 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; + /* Look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); + link->conf.Vcc = conf.Vcc; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(link, &tuple) != 0 || - pcmcia_parse_tuple(link, &tuple, &parse) != 0) + 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; } @@ -1730,10 +1743,10 @@ static int nsp_cs_config(struct pcmcia_device *link) } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) { - link->conf.Vpp = + link->conf.Vpp1 = link->conf.Vpp2 = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) { - link->conf.Vpp = + link->conf.Vpp1 = link->conf.Vpp2 = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; } @@ -1760,7 +1773,7 @@ static int nsp_cs_config(struct pcmcia_device *link) link->io.NumPorts2 = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link, &link->io) != 0) + if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; } @@ -1775,7 +1788,7 @@ static int nsp_cs_config(struct pcmcia_device *link) req.Size = 0x1000; } req.AccessSpeed = 0; - if (pcmcia_request_window(&link, &req, &link->win) != 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) @@ -1789,14 +1802,17 @@ static int nsp_cs_config(struct pcmcia_device *link) next_entry: nsp_dbg(NSP_DEBUG_INIT, "next"); - pcmcia_disable_device(link); - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); + + if (link->io.NumPorts1) { + pcmcia_release_io(link->handle, &link->io); + } + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } if (link->conf.Attributes & CONF_ENABLE_IRQ) { - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); } - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); if (free_ports) { if (link->io.BasePort1) { @@ -1838,19 +1854,16 @@ static int nsp_cs_config(struct pcmcia_device *link) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)) - ret = scsi_add_host (host, NULL); - if (ret) - goto cs_failed; - + scsi_add_host (host, NULL); scsi_scan_host(host); snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no); - link->dev_node = &info->node; + link->dev = &info->node; info->host = host; #else nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO"); - tail = &link->dev_node; + tail = &link->dev; info->ndev = 0; nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host); @@ -1895,10 +1908,11 @@ static int nsp_cs_config(struct pcmcia_device *link) #endif /* Finally, report what we've done */ - printk(KERN_INFO "nsp_cs: index 0x%02x: ", - link->conf.ConfigIndex); - if (link->conf.Vpp) { - printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); + printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d", + link->conf.ConfigIndex, + link->conf.Vcc/10, link->conf.Vcc%10); + if (link->conf.Vpp1) { + printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); } if (link->conf.Attributes & CONF_ENABLE_IRQ) { printk(", irq %d", link->irq.AssignedIRQ); @@ -1915,14 +1929,15 @@ static int nsp_cs_config(struct pcmcia_device *link) req.Base+req.Size-1); printk("\n"); - return 0; + link->state &= ~DEV_CONFIG_PENDING; + return; cs_failed: nsp_dbg(NSP_DEBUG_INIT, "config fail"); - cs_error(link, last_fn, last_ret); + cs_error(link->handle, last_fn, last_ret); nsp_cs_release(link); - return -ENODEV; + return; } /* nsp_cs_config */ #undef CS_CHECK @@ -1932,7 +1947,7 @@ static int nsp_cs_config(struct pcmcia_device *link) device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. ======================================================================*/ -static void nsp_cs_release(struct pcmcia_device *link) +static void nsp_cs_release(dev_link_t *link) { scsi_info_t *info = link->priv; nsp_hw_data *data = NULL; @@ -1953,15 +1968,22 @@ static void nsp_cs_release(struct pcmcia_device *link) #else scsi_unregister_host(&nsp_driver_template); #endif - link->dev_node = NULL; + link->dev = NULL; if (link->win) { if (data != NULL) { iounmap((void *)(data->MmioAddress)); } + pcmcia_release_window(link->win); } - pcmcia_disable_device(link); - + pcmcia_release_configuration(link->handle); + if (link->io.NumPorts1) { + pcmcia_release_io(link->handle, &link->io); + } + if (link->irq.AssignedIRQ) { + pcmcia_release_irq(link->handle, &link->irq); + } + link->state &= ~DEV_CONFIG; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2)) if (info->host != NULL) { scsi_host_put(info->host); @@ -1969,11 +1991,14 @@ static void nsp_cs_release(struct pcmcia_device *link) #endif } /* nsp_cs_release */ -static int nsp_cs_suspend(struct pcmcia_device *link) +static int nsp_cs_suspend(struct pcmcia_device *dev) { + dev_link_t *link = dev_to_instance(dev); scsi_info_t *info = link->priv; nsp_hw_data *data; + link->state |= DEV_SUSPEND; + nsp_dbg(NSP_DEBUG_INIT, "event: suspend"); if (info->host != NULL) { @@ -1986,16 +2011,25 @@ static int nsp_cs_suspend(struct pcmcia_device *link) info->stop = 1; + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + return 0; } -static int nsp_cs_resume(struct pcmcia_device *link) +static int nsp_cs_resume(struct pcmcia_device *dev) { + dev_link_t *link = dev_to_instance(dev); scsi_info_t *info = link->priv; nsp_hw_data *data; nsp_dbg(NSP_DEBUG_INIT, "event: resume"); + link->state &= ~DEV_SUSPEND; + + if (link->state & DEV_CONFIG) + pcmcia_request_configuration(link->handle, &link->conf); + info->stop = 0; if (info->host != NULL) { @@ -2031,7 +2065,7 @@ static struct pcmcia_driver nsp_driver = { .drv = { .name = "nsp_cs", }, - .probe = nsp_cs_probe, + .probe = nsp_cs_attach, .remove = nsp_cs_detach, .id_table = nsp_cs_ids, .suspend = nsp_cs_suspend, @@ -2064,7 +2098,19 @@ static int __init nsp_cs_init(void) static void __exit nsp_cs_exit(void) { nsp_msg(KERN_INFO, "unloading..."); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) pcmcia_unregister_driver(&nsp_driver); +#else + unregister_pcmcia_driver(&dev_info); + /* XXX: this really needs to move into generic code.. */ + while (dev_list != NULL) { + if (dev_list->state & DEV_CONFIG) { + nsp_cs_release(dev_list); + } + nsp_cs_detach(dev_list); + } +#endif }