aboutsummaryrefslogtreecommitdiff
path: root/drivers/bluetooth/btuart_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/btuart_cs.c')
-rw-r--r--drivers/bluetooth/btuart_cs.c248
1 files changed, 82 insertions, 166 deletions
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 68d1d258e6a..fb948f02eda 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -38,11 +38,8 @@
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <linux/bitops.h>
-#include <asm/system.h>
#include <asm/io.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -67,7 +64,6 @@ MODULE_LICENSE("GPL");
typedef struct btuart_info_t {
struct pcmcia_device *p_dev;
- dev_node_t node;
struct hci_dev *hdev;
@@ -144,16 +140,17 @@ static void btuart_write_wakeup(btuart_info_t *info)
}
do {
- register unsigned int iobase = info->p_dev->io.BasePort1;
+ unsigned int iobase = info->p_dev->resource[0]->start;
register struct sk_buff *skb;
- register int len;
+ int len;
clear_bit(XMIT_WAKEUP, &(info->tx_state));
if (!pcmcia_dev_present(info->p_dev))
return;
- if (!(skb = skb_dequeue(&(info->txq))))
+ skb = skb_dequeue(&(info->txq));
+ if (!skb)
break;
/* Send frame */
@@ -185,7 +182,7 @@ static void btuart_receive(btuart_info_t *info)
return;
}
- iobase = info->p_dev->io.BasePort1;
+ iobase = info->p_dev->resource[0]->start;
do {
info->hdev->stat.byte_rx++;
@@ -194,7 +191,8 @@ static void btuart_receive(btuart_info_t *info)
if (info->rx_skb == NULL) {
info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0;
- if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
+ info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
+ if (!info->rx_skb) {
BT_ERR("Can't allocate mem for new packet");
return;
}
@@ -202,7 +200,6 @@ static void btuart_receive(btuart_info_t *info)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
- info->rx_skb->dev = (void *) info->hdev;
bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX);
switch (bt_cb(info->rx_skb)->pkt_type) {
@@ -269,7 +266,7 @@ static void btuart_receive(btuart_info_t *info)
break;
case RECV_WAIT_DATA:
- hci_recv_frame(info->rx_skb);
+ hci_recv_frame(info->hdev, info->rx_skb);
info->rx_skb = NULL;
break;
@@ -293,15 +290,19 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
unsigned int iobase;
int boguscount = 0;
int iir, lsr;
+ irqreturn_t r = IRQ_NONE;
- BUG_ON(!info->hdev);
+ if (!info || !info->hdev)
+ /* our irq handler is shared */
+ return IRQ_NONE;
- iobase = info->p_dev->io.BasePort1;
+ iobase = info->p_dev->resource[0]->start;
spin_lock(&(info->lock));
iir = inb(iobase + UART_IIR) & UART_IIR_ID;
while (iir) {
+ r = IRQ_HANDLED;
/* Clear interrupt */
lsr = inb(iobase + UART_LSR);
@@ -335,7 +336,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
spin_unlock(&(info->lock));
- return IRQ_HANDLED;
+ return r;
}
@@ -352,7 +353,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
return;
}
- iobase = info->p_dev->io.BasePort1;
+ iobase = info->p_dev->resource[0]->start;
spin_lock_irqsave(&(info->lock), flags);
@@ -396,7 +397,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
static int btuart_hci_flush(struct hci_dev *hdev)
{
- btuart_info_t *info = (btuart_info_t *)(hdev->driver_data);
+ btuart_info_t *info = hci_get_drvdata(hdev);
/* Drop TX queue */
skb_queue_purge(&(info->txq));
@@ -424,17 +425,9 @@ static int btuart_hci_close(struct hci_dev *hdev)
}
-static int btuart_hci_send_frame(struct sk_buff *skb)
+static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
- btuart_info_t *info;
- struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
-
- if (!hdev) {
- BT_ERR("Frame for unknown HCI device (hdev=NULL)");
- return -ENODEV;
- }
-
- info = (btuart_info_t *)(hdev->driver_data);
+ btuart_info_t *info = hci_get_drvdata(hdev);
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
@@ -446,7 +439,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
case HCI_SCODATA_PKT:
hdev->stat.sco_tx++;
break;
- };
+ }
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
@@ -458,17 +451,6 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
}
-static void btuart_hci_destruct(struct hci_dev *hdev)
-{
-}
-
-
-static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
-}
-
-
/* ======================== Card services HCI interaction ======================== */
@@ -476,7 +458,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon
static int btuart_open(btuart_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->p_dev->io.BasePort1;
+ unsigned int iobase = info->p_dev->resource[0]->start;
struct hci_dev *hdev;
spin_lock_init(&(info->lock));
@@ -496,18 +478,14 @@ static int btuart_open(btuart_info_t *info)
info->hdev = hdev;
- hdev->type = HCI_PCCARD;
- hdev->driver_data = info;
+ hdev->bus = HCI_PCCARD;
+ hci_set_drvdata(hdev, info);
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
- hdev->open = btuart_hci_open;
- hdev->close = btuart_hci_close;
- hdev->flush = btuart_hci_flush;
- hdev->send = btuart_hci_send_frame;
- hdev->destruct = btuart_hci_destruct;
- hdev->ioctl = btuart_hci_ioctl;
-
- hdev->owner = THIS_MODULE;
+ hdev->open = btuart_hci_open;
+ hdev->close = btuart_hci_close;
+ hdev->flush = btuart_hci_flush;
+ hdev->send = btuart_hci_send_frame;
spin_lock_irqsave(&(info->lock), flags);
@@ -546,7 +524,7 @@ static int btuart_open(btuart_info_t *info)
static int btuart_close(btuart_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->p_dev->io.BasePort1;
+ unsigned int iobase = info->p_dev->resource[0]->start;
struct hci_dev *hdev = info->hdev;
if (!hdev)
@@ -564,9 +542,7 @@ static int btuart_close(btuart_info_t *info)
spin_unlock_irqrestore(&(info->lock), flags);
- if (hci_unregister_dev(hdev) < 0)
- BT_ERR("Can't unregister HCI device %s", hdev->name);
-
+ hci_unregister_dev(hdev);
hci_free_dev(hdev);
return 0;
@@ -577,23 +553,15 @@ static int btuart_probe(struct pcmcia_device *link)
btuart_info_t *info;
/* Create new info device */
- info = kzalloc(sizeof(*info), GFP_KERNEL);
+ info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
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_LEVEL_ID;
-
- link->irq.Handler = btuart_interrupt;
- link->irq.Instance = info;
-
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+ CONF_AUTO_SET_IO;
return btuart_config(link);
}
@@ -601,118 +569,81 @@ static int btuart_probe(struct pcmcia_device *link)
static void btuart_detach(struct pcmcia_device *link)
{
- btuart_info_t *info = link->priv;
-
btuart_release(link);
- kfree(info);
}
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
- int i;
+ int *try = priv_data;
- i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS)
- return i;
+ if (!try)
+ p_dev->io_lines = 16;
- return pcmcia_parse_tuple(handle, tuple, parse);
-}
+ if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+ return -EINVAL;
-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);
+ p_dev->resource[0]->end = 8;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+ return pcmcia_request_io(p_dev);
}
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
+ void *priv_data)
{
- if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
+ static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ int j;
+
+ if (p_dev->io_lines > 3)
+ return -ENODEV;
+
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->resource[0]->end = 8;
+
+ for (j = 0; j < 5; j++) {
+ p_dev->resource[0]->start = base[j];
+ p_dev->io_lines = base[j] ? 16 : 3;
+ if (!pcmcia_request_io(p_dev))
+ return 0;
+ }
+ return -ENODEV;
}
static int btuart_config(struct pcmcia_device *link)
{
- static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
btuart_info_t *info = link->priv;
- tuple_t tuple;
- u_short buf[256];
- cisparse_t parse;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- int i, j, try;
-
- /* First pass: look for a config entry that looks normal. */
- tuple.TupleData = (cisdata_t *) buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- 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);
- 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;
- 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);
- if (i == CS_SUCCESS)
- goto found_port;
- }
-next_entry:
- i = next_tuple(link, &tuple, &parse);
- }
- }
+ int i;
+ int try;
+
+ /* First pass: look for a config entry that looks normal.
+ Two tries: without IO aliases, then with aliases */
+ for (try = 0; try < 2; try++)
+ if (!pcmcia_loop_config(link, btuart_check_config, &try))
+ goto found_port;
/* 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);
- 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);
- if (i == CS_SUCCESS)
- goto found_port;
- }
- }
- i = next_tuple(link, &tuple, &parse);
- }
+ if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL))
+ goto found_port;
+
+ BT_ERR("No usable port range found");
+ goto failed;
found_port:
- if (i != CS_SUCCESS) {
- BT_ERR("No usable port range found");
- cs_error(link, RequestIO, i);
+ i = pcmcia_request_irq(link, btuart_interrupt);
+ if (i != 0)
goto failed;
- }
-
- i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
- cs_error(link, RequestIRQ, i);
- link->irq.AssignedIRQ = 0;
- }
- i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
- cs_error(link, RequestConfiguration, i);
+ i = pcmcia_enable_device(link);
+ if (i != 0)
goto failed;
- }
if (btuart_open(info) != 0)
goto failed;
- strcpy(info->node.dev_name, info->hdev->name);
- link->dev_node = &info->node;
-
return 0;
failed:
@@ -730,7 +661,7 @@ static void btuart_release(struct pcmcia_device *link)
pcmcia_disable_device(link);
}
-static struct pcmcia_device_id btuart_ids[] = {
+static const struct pcmcia_device_id btuart_ids[] = {
/* don't use this driver. Use serial_cs + hci_uart instead */
PCMCIA_DEVICE_NULL
};
@@ -738,24 +669,9 @@ MODULE_DEVICE_TABLE(pcmcia, btuart_ids);
static struct pcmcia_driver btuart_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "btuart_cs",
- },
+ .name = "btuart_cs",
.probe = btuart_probe,
.remove = btuart_detach,
.id_table = btuart_ids,
};
-
-static int __init init_btuart_cs(void)
-{
- return pcmcia_register_driver(&btuart_driver);
-}
-
-
-static void __exit exit_btuart_cs(void)
-{
- pcmcia_unregister_driver(&btuart_driver);
-}
-
-module_init(init_btuart_cs);
-module_exit(exit_btuart_cs);
+module_pcmcia_driver(btuart_driver);