static irqreturn_t bluecard_interrupt(int irq, void *dev_inst) { bluecard_info_t *info = dev_inst; unsigned int iobase; unsigned char reg; if (!info || !info->hdev) { BT_ERR("Call of irq %d for unknown device", irq); return IRQ_NONE; } if (!test_bit(CARD_READY, &(info->hw_state))) return IRQ_HANDLED; iobase = info->p_dev->io.BasePort1; spin_lock(&(info->lock)); /* Disable interrupt */ info->ctrl_reg &= ~REG_CONTROL_INTERRUPT; outb(info->ctrl_reg, iobase + REG_CONTROL); reg = inb(iobase + REG_INTERRUPT); if ((reg != 0x00) && (reg != 0xff)) { if (reg & 0x04) { bluecard_receive(info, 0x00); outb(0x04, iobase + REG_INTERRUPT); outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND); } if (reg & 0x08) { bluecard_receive(info, 0x10); outb(0x08, iobase + REG_INTERRUPT); outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND); } if (reg & 0x01) { set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); outb(0x01, iobase + REG_INTERRUPT); bluecard_write_wakeup(info); } if (reg & 0x02) { set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); outb(0x02, iobase + REG_INTERRUPT); bluecard_write_wakeup(info); } } /* Enable interrupt */ info->ctrl_reg |= REG_CONTROL_INTERRUPT; outb(info->ctrl_reg, iobase + REG_CONTROL); spin_unlock(&(info->lock)); return IRQ_HANDLED; }
static irqreturn_t bluecard_interrupt(int irq, void *dev_inst) { struct bluecard_info *info = dev_inst; unsigned int iobase; unsigned char reg; if (!info || !info->hdev) /* our irq handler is shared */ return IRQ_NONE; if (!test_bit(CARD_READY, &(info->hw_state))) return IRQ_HANDLED; iobase = info->p_dev->resource[0]->start; spin_lock(&(info->lock)); /* Disable interrupt */ info->ctrl_reg &= ~REG_CONTROL_INTERRUPT; outb(info->ctrl_reg, iobase + REG_CONTROL); reg = inb(iobase + REG_INTERRUPT); if ((reg != 0x00) && (reg != 0xff)) { if (reg & 0x04) { bluecard_receive(info, 0x00); outb(0x04, iobase + REG_INTERRUPT); outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND); } if (reg & 0x08) { bluecard_receive(info, 0x10); outb(0x08, iobase + REG_INTERRUPT); outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND); } if (reg & 0x01) { set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); outb(0x01, iobase + REG_INTERRUPT); bluecard_write_wakeup(info); } if (reg & 0x02) { set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); outb(0x02, iobase + REG_INTERRUPT); bluecard_write_wakeup(info); } } /* Enable interrupt */ info->ctrl_reg |= REG_CONTROL_INTERRUPT; outb(info->ctrl_reg, iobase + REG_CONTROL); spin_unlock(&(info->lock)); return IRQ_HANDLED; }
void bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *regs) { bluecard_info_t *info = dev_inst; unsigned int iobase; unsigned char reg; if (!info) { printk(KERN_WARNING "bluecard_cs: Call of irq %d for unknown device.\n", irq); return; } if (!test_bit(CARD_READY, &(info->hw_state))) return; iobase = info->link.io.BasePort1; spin_lock(&(info->lock)); /* Disable interrupt */ info->ctrl_reg &= ~REG_CONTROL_INTERRUPT; outb(info->ctrl_reg, iobase + REG_CONTROL); reg = inb(iobase + REG_INTERRUPT); if ((reg != 0x00) && (reg != 0xff)) { if (reg & 0x04) { bluecard_receive(info, 0x00); outb(0x04, iobase + REG_INTERRUPT); outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND); } if (reg & 0x08) { bluecard_receive(info, 0x10); outb(0x08, iobase + REG_INTERRUPT); outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND); } if (reg & 0x01) { set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); outb(0x01, iobase + REG_INTERRUPT); bluecard_write_wakeup(info); } if (reg & 0x02) { set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); outb(0x02, iobase + REG_INTERRUPT); bluecard_write_wakeup(info); } } /* Enable interrupt */ info->ctrl_reg |= REG_CONTROL_INTERRUPT; outb(info->ctrl_reg, iobase + REG_CONTROL); spin_unlock(&(info->lock)); }
static int bluecard_hci_send_frame(struct sk_buff *skb) { bluecard_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 = (bluecard_info_t *)(hdev->driver_data); switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: hdev->stat.acl_tx++; break; 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); skb_queue_tail(&(info->txq), skb); bluecard_write_wakeup(info); return 0; }
static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud) { struct bluecard_info *info = hci_get_drvdata(hdev); struct sk_buff *skb; /* Ericsson baud rate command */ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); if (!skb) { BT_ERR("Can't allocate mem for new packet"); return -1; } switch (baud) { case 460800: cmd[4] = 0x00; bt_cb(skb)->pkt_type = PKT_BAUD_RATE_460800; break; case 230400: cmd[4] = 0x01; bt_cb(skb)->pkt_type = PKT_BAUD_RATE_230400; break; case 115200: cmd[4] = 0x02; bt_cb(skb)->pkt_type = PKT_BAUD_RATE_115200; break; case 57600: /* Fall through... */ default: cmd[4] = 0x03; bt_cb(skb)->pkt_type = PKT_BAUD_RATE_57600; break; } memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd)); skb_queue_tail(&(info->txq), skb); bluecard_write_wakeup(info); return 0; }
static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud) { bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); struct sk_buff *skb; /* Ericsson baud rate command */ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; if (!(skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n"); return -1; } switch (baud) { case 460800: cmd[4] = 0x00; skb->pkt_type = PKT_BAUD_RATE_460800; break; case 230400: cmd[4] = 0x01; skb->pkt_type = PKT_BAUD_RATE_230400; break; case 115200: cmd[4] = 0x02; skb->pkt_type = PKT_BAUD_RATE_115200; break; case 57600: /* Fall through... */ default: cmd[4] = 0x03; skb->pkt_type = PKT_BAUD_RATE_57600; break; } memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd)); skb_queue_tail(&(info->txq), skb); bluecard_write_wakeup(info); return 0; }
static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { struct bluecard_info *info = hci_get_drvdata(hdev); switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: hdev->stat.acl_tx++; break; 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); skb_queue_tail(&(info->txq), skb); bluecard_write_wakeup(info); return 0; }
static void bluecard_receive(struct bluecard_info *info, unsigned int offset) { unsigned int iobase; unsigned char buf[31]; int i, len; if (!info) { BT_ERR("Unknown device"); return; } iobase = info->p_dev->resource[0]->start; if (test_bit(XMIT_SENDING_READY, &(info->tx_state))) bluecard_enable_activity_led(info); len = bluecard_read(iobase, offset, buf, sizeof(buf)); for (i = 0; i < len; i++) { /* Allocate packet */ if (info->rx_skb == NULL) { info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_count = 0; 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; } } if (info->rx_state == RECV_WAIT_PACKET_TYPE) { bt_cb(info->rx_skb)->pkt_type = buf[i]; switch (bt_cb(info->rx_skb)->pkt_type) { case 0x00: /* init packet */ if (offset != 0x00) { set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); set_bit(XMIT_SENDING_READY, &(info->tx_state)); bluecard_write_wakeup(info); } kfree_skb(info->rx_skb); info->rx_skb = NULL; break; case HCI_EVENT_PKT: info->rx_state = RECV_WAIT_EVENT_HEADER; info->rx_count = HCI_EVENT_HDR_SIZE; break; case HCI_ACLDATA_PKT: info->rx_state = RECV_WAIT_ACL_HEADER; info->rx_count = HCI_ACL_HDR_SIZE; break; case HCI_SCODATA_PKT: info->rx_state = RECV_WAIT_SCO_HEADER; info->rx_count = HCI_SCO_HDR_SIZE; break; default: /* unknown packet */ BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type); info->hdev->stat.err_rx++; kfree_skb(info->rx_skb); info->rx_skb = NULL; break; } } else { *skb_put(info->rx_skb, 1) = buf[i]; info->rx_count--; if (info->rx_count == 0) { int dlen; struct hci_event_hdr *eh; struct hci_acl_hdr *ah; struct hci_sco_hdr *sh; switch (info->rx_state) { case RECV_WAIT_EVENT_HEADER: eh = hci_event_hdr(info->rx_skb); info->rx_state = RECV_WAIT_DATA; info->rx_count = eh->plen; break; case RECV_WAIT_ACL_HEADER: ah = hci_acl_hdr(info->rx_skb); dlen = __le16_to_cpu(ah->dlen); info->rx_state = RECV_WAIT_DATA; info->rx_count = dlen; break; case RECV_WAIT_SCO_HEADER: sh = hci_sco_hdr(info->rx_skb); info->rx_state = RECV_WAIT_DATA; info->rx_count = sh->dlen; break; case RECV_WAIT_DATA: hci_recv_frame(info->hdev, info->rx_skb); info->rx_skb = NULL; break; } } } } info->hdev->stat.byte_rx += len; }
static void bluecard_receive(bluecard_info_t *info, unsigned int offset) { unsigned int iobase; unsigned char buf[31]; int i, len; if (!info) { printk(KERN_WARNING "bluecard_cs: Call of receive for unknown device.\n"); return; } iobase = info->link.io.BasePort1; if (test_bit(XMIT_SENDING_READY, &(info->tx_state))) bluecard_enable_activity_led(info); len = bluecard_read(iobase, offset, buf, sizeof(buf)); for (i = 0; i < len; i++) { /* Allocate packet */ if (info->rx_skb == NULL) { info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_count = 0; if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n"); return; } } if (info->rx_state == RECV_WAIT_PACKET_TYPE) { info->rx_skb->dev = (void *)&(info->hdev); info->rx_skb->pkt_type = buf[i]; switch (info->rx_skb->pkt_type) { case 0x00: /* init packet */ if (offset != 0x00) { set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); set_bit(XMIT_SENDING_READY, &(info->tx_state)); bluecard_write_wakeup(info); } kfree_skb(info->rx_skb); info->rx_skb = NULL; break; case HCI_EVENT_PKT: info->rx_state = RECV_WAIT_EVENT_HEADER; info->rx_count = HCI_EVENT_HDR_SIZE; break; case HCI_ACLDATA_PKT: info->rx_state = RECV_WAIT_ACL_HEADER; info->rx_count = HCI_ACL_HDR_SIZE; break; case HCI_SCODATA_PKT: info->rx_state = RECV_WAIT_SCO_HEADER; info->rx_count = HCI_SCO_HDR_SIZE; break; default: /* unknown packet */ printk(KERN_WARNING "bluecard_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); info->hdev.stat.err_rx++; kfree_skb(info->rx_skb); info->rx_skb = NULL; break; } } else { *skb_put(info->rx_skb, 1) = buf[i]; info->rx_count--; if (info->rx_count == 0) { int dlen; hci_event_hdr *eh; hci_acl_hdr *ah; hci_sco_hdr *sh; switch (info->rx_state) { case RECV_WAIT_EVENT_HEADER: eh = (hci_event_hdr *)(info->rx_skb->data); info->rx_state = RECV_WAIT_DATA; info->rx_count = eh->plen; break; case RECV_WAIT_ACL_HEADER: ah = (hci_acl_hdr *)(info->rx_skb->data); dlen = __le16_to_cpu(ah->dlen); info->rx_state = RECV_WAIT_DATA; info->rx_count = dlen; break; case RECV_WAIT_SCO_HEADER: sh = (hci_sco_hdr *)(info->rx_skb->data); info->rx_state = RECV_WAIT_DATA; info->rx_count = sh->dlen; break; case RECV_WAIT_DATA: hci_recv_frame(info->rx_skb); info->rx_skb = NULL; break; } } } } info->hdev.stat.byte_rx += len; }