X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fbluetooth%2Fbt3c_cs.c;h=7e21b1ff27c4213fb78de899fc03f11fe7fe0e58;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=b94ac2f9f7baf2d5e9cc0641e52de23cd1536d13;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index b94ac2f9f..7e21b1ff2 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -72,7 +72,7 @@ MODULE_LICENSE("GPL"); typedef struct bt3c_info_t { - struct pcmcia_device *p_dev; + dev_link_t link; dev_node_t node; struct hci_dev *hdev; @@ -88,8 +88,8 @@ typedef struct bt3c_info_t { } bt3c_info_t; -static int bt3c_config(struct pcmcia_device *link); -static void bt3c_release(struct pcmcia_device *link); +static void bt3c_config(dev_link_t *link); +static void bt3c_release(dev_link_t *link); static void bt3c_detach(struct pcmcia_device *p_dev); @@ -191,11 +191,11 @@ static void bt3c_write_wakeup(bt3c_info_t *info) return; do { - register unsigned int iobase = info->p_dev->io.BasePort1; + register unsigned int iobase = info->link.io.BasePort1; register struct sk_buff *skb; register int len; - if (!pcmcia_dev_present(info->p_dev)) + if (!(info->link.state & DEV_PRESENT)) break; @@ -229,7 +229,7 @@ static void bt3c_receive(bt3c_info_t *info) return; } - iobase = info->p_dev->io.BasePort1; + iobase = info->link.io.BasePort1; avail = bt3c_read(iobase, 0x7006); //printk("bt3c_cs: receiving %d bytes\n", avail); @@ -350,7 +350,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs) return IRQ_NONE; } - iobase = info->p_dev->io.BasePort1; + iobase = info->link.io.BasePort1; spin_lock(&(info->lock)); @@ -481,7 +481,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int co unsigned int iobase, size, addr, fcs, tmp; int i, err = 0; - iobase = info->p_dev->io.BasePort1; + iobase = info->link.io.BasePort1; /* Reset */ bt3c_io_write(iobase, 0x8040, 0x0404); @@ -562,6 +562,7 @@ static int bt3c_open(bt3c_info_t *info) { const struct firmware *firmware; struct hci_dev *hdev; + client_handle_t handle; int err; spin_lock_init(&(info->lock)); @@ -593,8 +594,10 @@ static int bt3c_open(bt3c_info_t *info) hdev->owner = THIS_MODULE; + handle = info->link.handle; + /* Load firmware */ - err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev); + err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle)); if (err < 0) { BT_ERR("Firmware request failed"); goto error; @@ -645,16 +648,17 @@ static int bt3c_close(bt3c_info_t *info) return 0; } -static int bt3c_probe(struct pcmcia_device *link) +static int bt3c_attach(struct pcmcia_device *p_dev) { bt3c_info_t *info; + dev_link_t *link; /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - info->p_dev = link; + link = &info->link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -666,21 +670,31 @@ static int bt3c_probe(struct pcmcia_device *link) link->irq.Instance = info; link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; - return bt3c_config(link); + link->handle = p_dev; + p_dev->instance = link; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + bt3c_config(link); + + return 0; } -static void bt3c_detach(struct pcmcia_device *link) +static void bt3c_detach(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); bt3c_info_t *info = link->priv; - bt3c_release(link); + if (link->state & DEV_CONFIG) + bt3c_release(link); + kfree(info); } -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) +static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -691,28 +705,30 @@ static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *p return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) +static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) { if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; return get_tuple(handle, tuple, parse); } -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) +static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) { if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; return get_tuple(handle, tuple, parse); } -static int bt3c_config(struct pcmcia_device *link) +static void bt3c_config(dev_link_t *link) { static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + client_handle_t handle = link->handle; bt3c_info_t *info = link->priv; tuple_t tuple; u_short buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; int i, j, try, last_ret, last_fn; tuple.TupleData = (cisdata_t *)buf; @@ -722,7 +738,7 @@ static int bt3c_config(struct pcmcia_device *link) /* Get configuration register information */ tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(link, &tuple, &parse); + last_ret = first_tuple(handle, &tuple, &parse); if (last_ret != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -730,6 +746,11 @@ static int bt3c_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; + /* Configure card */ + link->state |= DEV_CONFIG; + i = pcmcia_get_configuration_info(handle, &config); + link->conf.Vcc = config.Vcc; + /* First pass: look for a config entry that looks normal. */ tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; @@ -738,59 +759,59 @@ static int bt3c_config(struct pcmcia_device *link) tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; /* Two tries: without IO aliases, then with aliases */ for (try = 0; try < 2; try++) { - i = first_tuple(link, &tuple, &parse); + i = first_tuple(handle, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if (i != CS_SUCCESS) goto next_entry; if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link, &link->io); + i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) goto found_port; } next_entry: - i = next_tuple(link, &tuple, &parse); + i = next_tuple(handle, &tuple, &parse); } } /* Second pass: try to find an entry that isn't picky about its base address, then try to grab any standard serial port address, and finally try to get any free port. */ - i = first_tuple(link, &tuple, &parse); + i = first_tuple(handle, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { link->conf.ConfigIndex = cf->index; for (j = 0; j < 5; j++) { link->io.BasePort1 = base[j]; link->io.IOAddrLines = base[j] ? 16 : 3; - i = pcmcia_request_io(link, &link->io); + i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) goto found_port; } } - i = next_tuple(link, &tuple, &parse); + i = next_tuple(handle, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { BT_ERR("No usable port range found"); - cs_error(link, RequestIO, i); + cs_error(link->handle, RequestIO, i); goto failed; } - i = pcmcia_request_irq(link, &link->irq); + i = pcmcia_request_irq(link->handle, &link->irq); if (i != CS_SUCCESS) { - cs_error(link, RequestIRQ, i); + cs_error(link->handle, RequestIRQ, i); link->irq.AssignedIRQ = 0; } - i = pcmcia_request_configuration(link, &link->conf); + i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { - cs_error(link, RequestConfiguration, i); + cs_error(link->handle, RequestConfiguration, i); goto failed; } @@ -798,26 +819,55 @@ found_port: goto failed; strcpy(info->node.dev_name, info->hdev->name); - link->dev_node = &info->node; + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; - return 0; + return; cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link->handle, last_fn, last_ret); failed: bt3c_release(link); - return -ENODEV; } -static void bt3c_release(struct pcmcia_device *link) +static void bt3c_release(dev_link_t *link) { bt3c_info_t *info = link->priv; - bt3c_close(info); + if (link->state & DEV_PRESENT) + bt3c_close(info); + + 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; +} + +static int bt3c_suspend(struct pcmcia_device *dev) +{ + dev_link_t *link = dev_to_instance(dev); - pcmcia_disable_device(link); + link->state |= DEV_SUSPEND; + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + + return 0; +} + +static int bt3c_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; } @@ -832,9 +882,11 @@ static struct pcmcia_driver bt3c_driver = { .drv = { .name = "bt3c_cs", }, - .probe = bt3c_probe, + .probe = bt3c_attach, .remove = bt3c_detach, .id_table = bt3c_ids, + .suspend = bt3c_suspend, + .resume = bt3c_resume, }; static int __init init_bt3c_cs(void)