X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fbluetooth%2Fbt3c_cs.c;h=b94ac2f9f7baf2d5e9cc0641e52de23cd1536d13;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=8cd5d0e2c0a886604d8dfabc7e6f8f469bd28092;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 8cd5d0e2c..b94ac2f9f 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -25,29 +25,28 @@ #include #include -#include #include #include -#include #include #include +#include #include #include #include #include +#include #include #include #include #include +#include #include -#include #include #include #include -#include #include #include #include @@ -63,13 +62,6 @@ /* ======================== Module parameters ======================== */ -/* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xffff; -static int irq_list[4] = { -1 }; - -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); - MODULE_AUTHOR("Marcel Holtmann , Jose Orlando Pereira "); MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card"); MODULE_LICENSE("GPL"); @@ -80,7 +72,7 @@ MODULE_LICENSE("GPL"); typedef struct bt3c_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct hci_dev *hdev; @@ -96,16 +88,10 @@ typedef struct bt3c_info_t { } bt3c_info_t; -void bt3c_config(dev_link_t *link); -void bt3c_release(dev_link_t *link); -int bt3c_event(event_t event, int priority, event_callback_args_t *args); +static int bt3c_config(struct pcmcia_device *link); +static void bt3c_release(struct pcmcia_device *link); -static dev_info_t dev_info = "bt3c_cs"; - -dev_link_t *bt3c_attach(void); -void bt3c_detach(dev_link_t *); - -static dev_link_t *dev_list = NULL; +static void bt3c_detach(struct pcmcia_device *p_dev); /* Transmit states */ @@ -132,28 +118,28 @@ static dev_link_t *dev_list = NULL; #define CONTROL 4 -inline void bt3c_address(unsigned int iobase, unsigned short addr) +static inline void bt3c_address(unsigned int iobase, unsigned short addr) { outb(addr & 0xff, iobase + ADDR_L); outb((addr >> 8) & 0xff, iobase + ADDR_H); } -inline void bt3c_put(unsigned int iobase, unsigned short value) +static inline void bt3c_put(unsigned int iobase, unsigned short value) { outb(value & 0xff, iobase + DATA_L); outb((value >> 8) & 0xff, iobase + DATA_H); } -inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value) +static inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value) { bt3c_address(iobase, addr); bt3c_put(iobase, value); } -inline unsigned short bt3c_get(unsigned int iobase) +static inline unsigned short bt3c_get(unsigned int iobase) { unsigned short value = inb(iobase + DATA_L); @@ -163,7 +149,7 @@ inline unsigned short bt3c_get(unsigned int iobase) } -inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr) +static inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr) { bt3c_address(iobase, addr); @@ -194,10 +180,8 @@ static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) } -static void bt3c_write_wakeup(bt3c_info_t *info, int from) +static void bt3c_write_wakeup(bt3c_info_t *info) { - unsigned long flags; - if (!info) { BT_ERR("Unknown device"); return; @@ -206,14 +190,12 @@ static void bt3c_write_wakeup(bt3c_info_t *info, int from) if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) return; - spin_lock_irqsave(&(info->lock), flags); - do { - register unsigned int iobase = info->link.io.BasePort1; + register unsigned int iobase = info->p_dev->io.BasePort1; register struct sk_buff *skb; register int len; - if (!(info->link.state & DEV_PRESENT)) + if (!pcmcia_dev_present(info->p_dev)) break; @@ -234,8 +216,6 @@ static void bt3c_write_wakeup(bt3c_info_t *info, int from) info->hdev->stat.byte_tx += len; } while (0); - - spin_unlock_irqrestore(&(info->lock), flags); } @@ -249,7 +229,7 @@ static void bt3c_receive(bt3c_info_t *info) return; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; avail = bt3c_read(iobase, 0x7006); //printk("bt3c_cs: receiving %d bytes\n", avail); @@ -273,11 +253,11 @@ static void bt3c_receive(bt3c_info_t *info) if (info->rx_state == RECV_WAIT_PACKET_TYPE) { info->rx_skb->dev = (void *) info->hdev; - info->rx_skb->pkt_type = inb(iobase + DATA_L); + bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L); inb(iobase + DATA_H); - //printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type); + //printk("bt3c: PACKET_TYPE=%02x\n", bt_cb(info->rx_skb)->pkt_type); - switch (info->rx_skb->pkt_type) { + switch (bt_cb(info->rx_skb)->pkt_type) { case HCI_EVENT_PKT: info->rx_state = RECV_WAIT_EVENT_HEADER; @@ -296,7 +276,7 @@ static void bt3c_receive(bt3c_info_t *info) default: /* Unknown packet */ - BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); + BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type); info->hdev->stat.err_rx++; clear_bit(HCI_RUNNING, &(info->hdev->flags)); @@ -370,7 +350,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs) return IRQ_NONE; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; spin_lock(&(info->lock)); @@ -391,7 +371,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs) if (stat & 0x0002) { //BT_ERR("Ack (stat=0x%04x)", stat); clear_bit(XMIT_SENDING, &(info->tx_state)); - bt3c_write_wakeup(info, 1); + bt3c_write_wakeup(info); } bt3c_io_write(iobase, 0x7001, 0x0000); @@ -444,6 +424,7 @@ static int bt3c_hci_send_frame(struct sk_buff *skb) { bt3c_info_t *info; struct hci_dev *hdev = (struct hci_dev *)(skb->dev); + unsigned long flags; if (!hdev) { BT_ERR("Frame for unknown HCI device (hdev=NULL)"); @@ -452,7 +433,7 @@ static int bt3c_hci_send_frame(struct sk_buff *skb) info = (bt3c_info_t *) (hdev->driver_data); - switch (skb->pkt_type) { + switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: hdev->stat.cmd_tx++; break; @@ -465,10 +446,14 @@ static int bt3c_hci_send_frame(struct sk_buff *skb) }; /* Prepend skb with frame type */ - memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); + memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); skb_queue_tail(&(info->txq), skb); - bt3c_write_wakeup(info, 0); + spin_lock_irqsave(&(info->lock), flags); + + bt3c_write_wakeup(info); + + spin_unlock_irqrestore(&(info->lock), flags); return 0; } @@ -489,11 +474,6 @@ static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long /* ======================== Card services HCI interaction ======================== */ -static struct device bt3c_device = { - .bus_id = "pcmcia", -}; - - static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count) { char *ptr = (char *) firmware; @@ -501,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->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; /* Reset */ bt3c_io_write(iobase, 0x8040, 0x0404); @@ -578,7 +558,7 @@ error: } -int bt3c_open(bt3c_info_t *info) +static int bt3c_open(bt3c_info_t *info) { const struct firmware *firmware; struct hci_dev *hdev; @@ -614,7 +594,7 @@ int bt3c_open(bt3c_info_t *info) hdev->owner = THIS_MODULE; /* Load firmware */ - err = request_firmware(&firmware, "BT3CPCC.bin", &bt3c_device); + err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev); if (err < 0) { BT_ERR("Firmware request failed"); goto error; @@ -630,8 +610,7 @@ int bt3c_open(bt3c_info_t *info) } /* Timeout before it is safe to send the first HCI packet */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep(1000); /* Register HCI device */ err = hci_register_dev(hdev); @@ -649,7 +628,7 @@ error: } -int bt3c_close(bt3c_info_t *info) +static int bt3c_close(bt3c_info_t *info) { struct hci_dev *hdev = info->hdev; @@ -666,94 +645,42 @@ int bt3c_close(bt3c_info_t *info) return 0; } -dev_link_t *bt3c_attach(void) +static int bt3c_probe(struct pcmcia_device *link) { bt3c_info_t *info; - client_reg_t client_reg; - dev_link_t *link; - int i, ret; /* Create new info device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) - return NULL; - memset(info, 0, sizeof(*info)); + return -ENOMEM; - link = &info->link; + info->p_dev = link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; - - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = bt3c_interrupt; link->irq.Instance = info; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &bt3c_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - - ret = pcmcia_register_client(&link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - bt3c_detach(link); - return NULL; - } - - return link; + return bt3c_config(link); } -void bt3c_detach(dev_link_t *link) +static void bt3c_detach(struct pcmcia_device *link) { bt3c_info_t *info = link->priv; - dev_link_t **linkp; - int ret; - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) - break; - - if (*linkp == NULL) - return; - - if (link->state & DEV_CONFIG) - bt3c_release(link); - - if (link->handle) { - ret = pcmcia_deregister_client(link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - /* Unlink device structure, free bits */ - *linkp = link->next; + bt3c_release(link); kfree(info); } -static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -764,30 +691,28 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int first_tuple(struct pcmcia_device *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(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int next_tuple(struct pcmcia_device *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); } -void bt3c_config(dev_link_t *link) +static int bt3c_config(struct pcmcia_device *link) { - static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; - client_handle_t handle = link->handle; + static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; 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; @@ -797,7 +722,7 @@ void bt3c_config(dev_link_t *link) /* Get configuration register information */ tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); + last_ret = first_tuple(link, &tuple, &parse); if (last_ret != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -805,11 +730,6 @@ void bt3c_config(dev_link_t *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; @@ -818,59 +738,59 @@ void bt3c_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; /* Two tries: without IO aliases, then with aliases */ for (try = 0; try < 2; try++) { - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &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.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + link->conf.Vpp = 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->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } next_entry: - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &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(handle, &tuple, &parse); + i = first_tuple(link, &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->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { BT_ERR("No usable port range found"); - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); + cs_error(link, RequestConfiguration, i); goto failed; } @@ -878,79 +798,43 @@ found_port: goto failed; strcpy(info->node.dev_name, info->hdev->name); - link->dev = &info->node; - link->state &= ~DEV_CONFIG_PENDING; + link->dev_node = &info->node; - return; + return 0; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: bt3c_release(link); + return -ENODEV; } -void bt3c_release(dev_link_t *link) +static void bt3c_release(struct pcmcia_device *link) { bt3c_info_t *info = link->priv; - if (link->state & DEV_PRESENT) - bt3c_close(info); - - link->dev = NULL; + bt3c_close(info); - 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); } -int bt3c_event(event_t event, int priority, event_callback_args_t *args) -{ - dev_link_t *link = args->client_data; - bt3c_info_t *info = link->priv; - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) { - bt3c_close(info); - bt3c_release(link); - } - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - bt3c_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - break; - } - - return 0; -} +static struct pcmcia_device_id bt3c_ids[] = { + PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, bt3c_ids); static struct pcmcia_driver bt3c_driver = { .owner = THIS_MODULE, .drv = { .name = "bt3c_cs", }, - .attach = bt3c_attach, - .detach = bt3c_detach, + .probe = bt3c_probe, + .remove = bt3c_detach, + .id_table = bt3c_ids, }; static int __init init_bt3c_cs(void) @@ -962,10 +846,6 @@ static int __init init_bt3c_cs(void) static void __exit exit_bt3c_cs(void) { pcmcia_unregister_driver(&bt3c_driver); - - /* XXX: this really needs to move into generic code.. */ - while (dev_list != NULL) - bt3c_detach(dev_list); } module_init(init_bt3c_cs);