X-Git-Url: http://git.onelab.eu/?p=linux-2.6.git;a=blobdiff_plain;f=drivers%2Fide%2Flegacy%2Fide-cs.c;fp=drivers%2Fide%2Flegacy%2Fide-cs.c;h=6213bd3caee5033552ea7bf20104564676c3b013;hp=602797a4420877f6fc74e659a05b4c50be8d54d6;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 602797a44..6213bd3ca 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -81,14 +81,14 @@ static const char ide_major[] = { }; typedef struct ide_info_t { - struct pcmcia_device *p_dev; + dev_link_t link; int ndev; dev_node_t node; int hd; } ide_info_t; -static void ide_release(struct pcmcia_device *); -static int ide_config(struct pcmcia_device *); +static void ide_release(dev_link_t *); +static void ide_config(dev_link_t *); static void ide_detach(struct pcmcia_device *p_dev); @@ -103,9 +103,10 @@ static void ide_detach(struct pcmcia_device *p_dev); ======================================================================*/ -static int ide_probe(struct pcmcia_device *link) +static int ide_attach(struct pcmcia_device *p_dev) { ide_info_t *info; + dev_link_t *link; DEBUG(0, "ide_attach()\n"); @@ -113,9 +114,7 @@ static int ide_probe(struct pcmcia_device *link) info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - - info->p_dev = link; - link->priv = info; + link = &info->link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; @@ -123,9 +122,16 @@ static int ide_probe(struct pcmcia_device *link) 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; - return ide_config(link); + link->handle = p_dev; + p_dev->instance = link; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + ide_config(link); + + return 0; } /* ide_attach */ /*====================================================================== @@ -137,11 +143,14 @@ static int ide_probe(struct pcmcia_device *link) ======================================================================*/ -static void ide_detach(struct pcmcia_device *link) +static void ide_detach(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); + DEBUG(0, "ide_detach(0x%p)\n", link); - ide_release(link); + if (link->state & DEV_CONFIG) + ide_release(link); kfree(link->priv); } /* ide_detach */ @@ -168,8 +177,9 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int ide_config(struct pcmcia_device *link) +static void ide_config(dev_link_t *link) { + client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; struct { @@ -193,30 +203,34 @@ static int ide_config(struct pcmcia_device *link) tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - 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, &stk->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, &stk->parse)); link->conf.ConfigBase = stk->parse.config.base; link->conf.Present = stk->parse.config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; - if (!pcmcia_get_first_tuple(link, &tuple) && - !pcmcia_get_tuple_data(link, &tuple) && - !pcmcia_parse_tuple(link, &tuple, &stk->parse)) + if (!pcmcia_get_first_tuple(handle, &tuple) && + !pcmcia_get_tuple_data(handle, &tuple) && + !pcmcia_parse_tuple(handle, &tuple, &stk->parse)) is_kme = ((stk->parse.manfid.manf == MANFID_KME) && ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); + /* Configure card */ + link->state |= DEV_CONFIG; + /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf)); + link->conf.Vcc = stk->conf.Vcc; pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; - 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) goto next_entry; - if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry; + if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; + if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { @@ -230,10 +244,10 @@ static int ide_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 (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp = + link->conf.Vpp1 = link->conf.Vpp2 = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { @@ -247,14 +261,14 @@ static int ide_config(struct pcmcia_device *link) link->io.NumPorts1 = 8; link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = (is_kme) ? 2 : 1; - if (pcmcia_request_io(link, &link->io) != 0) + if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; ctl_base = link->io.BasePort2; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { link->io.NumPorts1 = io->win[0].len; link->io.NumPorts2 = 0; - if (pcmcia_request_io(link, &link->io) != 0) + if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; ctl_base = link->io.BasePort1 + 0x0e; @@ -267,16 +281,16 @@ static int ide_config(struct pcmcia_device *link) if (cfg->flags & CISTPL_CFTABLE_DEFAULT) memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); if (pass) { - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); - } else if (pcmcia_get_next_tuple(link, &tuple) != 0) { - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); memset(&stk->dflt, 0, sizeof(stk->dflt)); pass++; } } - 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)); /* disable drive interrupts during IDE probe */ outb(0x02, ctl_base); @@ -287,12 +301,12 @@ static int ide_config(struct pcmcia_device *link) /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { - hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); + hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, handle); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { outb(0x02, ctl_base + 0x10); hd = idecs_register(io_base + 0x10, ctl_base + 0x10, - link->irq.AssignedIRQ, link); + link->irq.AssignedIRQ, handle); if (hd >= 0) { io_base += 0x10; ctl_base += 0x10; @@ -314,23 +328,25 @@ static int ide_config(struct pcmcia_device *link) info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; - link->dev_node = &info->node; - printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); + link->dev = &info->node; + printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", + info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, + link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); + link->state &= ~DEV_CONFIG_PENDING; kfree(stk); - return 0; + return; err_mem: printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); goto failed; cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link->handle, last_fn, last_ret); failed: kfree(stk); ide_release(link); - return -ENODEV; + link->state &= ~DEV_CONFIG_PENDING; } /* ide_config */ /*====================================================================== @@ -341,7 +357,7 @@ failed: ======================================================================*/ -void ide_release(struct pcmcia_device *link) +void ide_release(dev_link_t *link) { ide_info_t *info = link->priv; @@ -353,10 +369,37 @@ void ide_release(struct pcmcia_device *link) ide_unregister(info->hd); } info->ndev = 0; + link->dev = NULL; + + pcmcia_release_configuration(link->handle); + pcmcia_release_io(link->handle, &link->io); + pcmcia_release_irq(link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; - pcmcia_disable_device(link); } /* ide_release */ +static int ide_suspend(struct pcmcia_device *dev) +{ + 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 ide_resume(struct pcmcia_device *dev) +{ + dev_link_t *link = dev_to_instance(dev); + + link->state &= ~DEV_SUSPEND; + if (DEV_OK(link)) + pcmcia_request_configuration(link->handle, &link->conf); + + return 0; +} /*====================================================================== @@ -392,7 +435,6 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), - PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), @@ -417,9 +459,11 @@ static struct pcmcia_driver ide_cs_driver = { .drv = { .name = "ide-cs", }, - .probe = ide_probe, + .probe = ide_attach, .remove = ide_detach, .id_table = ide_ids, + .suspend = ide_suspend, + .resume = ide_resume, }; static int __init init_ide_cs(void)