X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fpcmcia%2Ffdomain_stub.c;fp=drivers%2Fscsi%2Fpcmcia%2Ffdomain_stub.c;h=788c58d805f39cbac64db4f4e601f19f70c43524;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=85f7ffac19a0ef589cbc9c4643c8ef9b6f7a0f71;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 85f7ffac1..788c58d80 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -73,48 +73,57 @@ static char *version = /*====================================================================*/ typedef struct scsi_info_t { - struct pcmcia_device *p_dev; + dev_link_t link; dev_node_t node; struct Scsi_Host *host; } scsi_info_t; -static void fdomain_release(struct pcmcia_device *link); +static void fdomain_release(dev_link_t *link); static void fdomain_detach(struct pcmcia_device *p_dev); -static int fdomain_config(struct pcmcia_device *link); +static void fdomain_config(dev_link_t *link); -static int fdomain_probe(struct pcmcia_device *link) +static int fdomain_attach(struct pcmcia_device *p_dev) { - scsi_info_t *info; - - DEBUG(0, "fdomain_attach()\n"); - - /* Create new SCSI device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->p_dev = link; - link->priv = info; - link->io.NumPorts1 = 0x10; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.Present = PRESENT_OPTION; - - return fdomain_config(link); + scsi_info_t *info; + dev_link_t *link; + + DEBUG(0, "fdomain_attach()\n"); + + /* Create new SCSI device */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) return -ENOMEM; + memset(info, 0, sizeof(*info)); + link = &info->link; link->priv = info; + link->io.NumPorts1 = 0x10; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.IOAddrLines = 10; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.Present = PRESENT_OPTION; + + link->handle = p_dev; + p_dev->instance = link; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + fdomain_config(link); + + return 0; } /* fdomain_attach */ /*====================================================================*/ -static void fdomain_detach(struct pcmcia_device *link) +static void fdomain_detach(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); + DEBUG(0, "fdomain_detach(0x%p)\n", link); - fdomain_release(link); + if (link->state & DEV_CONFIG) + fdomain_release(link); kfree(link->priv); } /* fdomain_detach */ @@ -124,8 +133,9 @@ static void fdomain_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 fdomain_config(struct pcmcia_device *link) +static void fdomain_config(dev_link_t *link) { + client_handle_t handle = link->handle; scsi_info_t *info = link->priv; tuple_t tuple; cisparse_t parse; @@ -140,75 +150,103 @@ static int fdomain_config(struct pcmcia_device *link) tuple.TupleData = tuple_data; tuple.TupleDataMax = 64; 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; + /* Configure card */ + link->state |= DEV_CONFIG; + 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) { - 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; link->conf.ConfigIndex = parse.cftable_entry.index; link->io.BasePort1 = parse.cftable_entry.io.win[0].base; - i = pcmcia_request_io(link, &link->io); + i = pcmcia_request_io(handle, &link->io); if (i == CS_SUCCESS) break; next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - + CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + /* A bad hack... */ release_region(link->io.BasePort1, link->io.NumPorts1); /* Set configuration options for the fdomain driver */ sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ); fdomain_setup(str); - + host = __fdomain_16x0_detect(&fdomain_driver_template); if (!host) { printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); goto cs_failed; } - - if (scsi_add_host(host, NULL)) - goto cs_failed; + + scsi_add_host(host, NULL); /* XXX handle failure */ scsi_scan_host(host); sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev_node = &info->node; + link->dev = &info->node; info->host = host; - - return 0; - + + link->state &= ~DEV_CONFIG_PENDING; + return; + cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link->handle, last_fn, last_ret); fdomain_release(link); - return -ENODEV; + return; + } /* fdomain_config */ /*====================================================================*/ -static void fdomain_release(struct pcmcia_device *link) +static void fdomain_release(dev_link_t *link) { - scsi_info_t *info = link->priv; + scsi_info_t *info = link->priv; - DEBUG(0, "fdomain_release(0x%p)\n", link); + DEBUG(0, "fdomain_release(0x%p)\n", link); - scsi_remove_host(info->host); - pcmcia_disable_device(link); - scsi_unregister(info->host); + scsi_remove_host(info->host); + link->dev = NULL; + + pcmcia_release_configuration(link->handle); + pcmcia_release_io(link->handle, &link->io); + pcmcia_release_irq(link->handle, &link->irq); + + scsi_unregister(info->host); + + link->state &= ~DEV_CONFIG; } /*====================================================================*/ -static int fdomain_resume(struct pcmcia_device *link) +static int fdomain_suspend(struct pcmcia_device *dev) { - fdomain_16x0_bus_reset(NULL); + dev_link_t *link = dev_to_instance(dev); + + link->state |= DEV_SUSPEND; + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + + return 0; +} + +static int fdomain_resume(struct pcmcia_device *dev) +{ + dev_link_t *link = dev_to_instance(dev); + + link->state &= ~DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + pcmcia_request_configuration(link->handle, &link->conf); + fdomain_16x0_bus_reset(NULL); + } return 0; } @@ -226,9 +264,10 @@ static struct pcmcia_driver fdomain_cs_driver = { .drv = { .name = "fdomain_cs", }, - .probe = fdomain_probe, + .probe = fdomain_attach, .remove = fdomain_detach, .id_table = fdomain_ids, + .suspend = fdomain_suspend, .resume = fdomain_resume, };