diff options
author | Chris Larson <clarson@kergoth.com> | 2004-12-09 09:47:41 +0000 |
---|---|---|
committer | Chris Larson <clarson@kergoth.com> | 2004-12-09 09:47:41 +0000 |
commit | 2c5b8ec6d95cf68650265941530e5ce38c8dd6d9 (patch) | |
tree | bf879bea7ef8517ba8c3d1286ef300401d3d484c /linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bt950_cs.patch | |
parent | 101e2f1623def0a355d20aacb8bd93810703e834 (diff) |
Merge oe-devel@oe-devel.bkbits.net:openembedded
into hyperion.kergoth.com:/home/kergoth/code/openembedded
2004/12/09 03:39:39-06:00 kergoth.com!kergoth
Break people's builds again.. this time moving the packages into a packages/ subdir to clean things up a bit.
BKrev: 41b81f3dvlp3rU7_8MUXLcI8LDdDoA
Diffstat (limited to 'linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bt950_cs.patch')
-rw-r--r-- | linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bt950_cs.patch | 1174 |
1 files changed, 0 insertions, 1174 deletions
diff --git a/linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bt950_cs.patch b/linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bt950_cs.patch deleted file mode 100644 index c29f0d02f2..0000000000 --- a/linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/bt950_cs.patch +++ /dev/null @@ -1,1174 +0,0 @@ -diff -Nur linux-orig/drivers/bluetooth/bt950_cs.c linux/drivers/bluetooth/bt950_cs.c ---- linux-orig/drivers/bluetooth/bt950_cs.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux/drivers/bluetooth/bt950_cs.c 2004-02-04 09:55:04.000000000 +0300 -@@ -0,0 +1,1133 @@ -+/* -+ * -+ * Driver for Bluetooth cards with OXCF950 UART interface -+ * -+ * Copyright (C) 2001-2002 Marcel Holtmann <marcel@holtmann.org> -+ * Albert Rybalkin <albertr@iral.com> -+ * -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation; -+ * -+ * Software distributed under the License is distributed on an "AS -+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -+ * implied. See the License for the specific language governing -+ * rights and limitations under the License. -+ * -+ * The initial developer of the original code is David A. Hinds -+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds -+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. -+ * -+ */ -+ -+#include <linux/config.h> -+ -+#ifdef CONFIG_MODVERSIONS -+#ifndef MODVERSIONS -+#define MODVERSIONS -+#endif -+#include <linux/modversions.h> -+#endif -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+#include <linux/sched.h> -+#include <linux/timer.h> -+#include <linux/errno.h> -+#include <linux/ptrace.h> -+#include <linux/ioport.h> -+#include <linux/spinlock.h> -+#include <linux/delay.h> -+ -+#include <linux/skbuff.h> -+#include <linux/string.h> -+#include <linux/serial.h> -+#include <linux/serial_reg.h> -+#include <asm/system.h> -+#include <asm/bitops.h> -+#include <asm/io.h> -+ -+#include <pcmcia/version.h> -+#include <pcmcia/cs_types.h> -+#include <pcmcia/cs.h> -+#include <pcmcia/cistpl.h> -+#include <pcmcia/ciscode.h> -+#include <pcmcia/ds.h> -+#include <pcmcia/cisreg.h> -+ -+#include <net/bluetooth/bluetooth.h> -+#include <net/bluetooth/hci_core.h> -+ -+/* Default baud rate: 57600, 115200, 230400 or 460800 */ -+#define DEFAULT_BAUD_RATE 460800 -+ -+ -+/* ======================== Module parameters ======================== */ -+ -+ -+/* Bit map of interrupts to choose from */ -+static u_int irq_mask = 0x86bc; -+static int irq_list[4] = { -1 }; -+static long baud_rate = DEFAULT_BAUD_RATE; -+ -+MODULE_PARM(irq_mask, "i"); -+MODULE_PARM(irq_list, "1-4i"); -+MODULE_PARM(baud_rate, "l"); -+ -+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Albert Rybalkin <albertr@iral.com>"); -+MODULE_DESCRIPTION("BlueZ driver for Bluetooth cards with OXCF950 UART interface"); -+MODULE_LICENSE("GPL"); -+ -+ -+ -+/* ======================== Local structures ======================== */ -+ -+ -+typedef struct bt950_info_t { -+ dev_link_t link; -+ dev_node_t node; -+ -+ struct hci_dev hdev; -+ -+ spinlock_t lock; /* For serializing operations */ -+ -+ struct sk_buff_head txq; -+ unsigned long tx_state; -+ -+ unsigned long rx_state; -+ unsigned long rx_count; -+ struct sk_buff *rx_skb; -+} bt950_info_t; -+ -+ -+static void bt950_config(dev_link_t *link); -+static void bt950_release(u_long arg); -+static int bt950_event(event_t event, int priority, event_callback_args_t *args); -+ -+static dev_info_t dev_info = "bt950_cs"; -+ -+static dev_link_t *bt950_attach(void); -+static void bt950_detach(dev_link_t *); -+ -+static dev_link_t *dev_list = NULL; -+ -+/* Transmit states */ -+#define XMIT_SENDING 1 -+#define XMIT_WAKEUP 2 -+#define XMIT_WAITING 8 -+ -+/* Receiver states */ -+#define RECV_WAIT_PACKET_TYPE 0 -+#define RECV_WAIT_EVENT_HEADER 1 -+#define RECV_WAIT_ACL_HEADER 2 -+#define RECV_WAIT_SCO_HEADER 3 -+#define RECV_WAIT_DATA 4 -+ -+/* Special packet types */ -+#define PKT_BAUD_RATE_57600 0x80 -+#define PKT_BAUD_RATE_115200 0x81 -+#define PKT_BAUD_RATE_230400 0x82 -+#define PKT_BAUD_RATE_460800 0x83 -+ -+/* 950-specific stuff */ -+#define MAX_WAIT 0xFFFF -+#define FIFO_SIZE 128 -+ -+#define TR_TX_INT 0x10 /* TTL: TX interrupt trigger level (0-127) */ -+#define TR_RX_INT 0x40 /* RTL: RX interrupt trigger level (1-127) */ -+#define TR_CTL_LO 0x08 /* FCL: auto flow control LOWER trigger level (0-127) */ -+#define TR_CTL_HI 0x60 /* FCH: auto flow control HIGH trigger level (1-127) */ -+ -+/* 950-specific registers and values we use. It should -+ * eventually go to include/linux/serial_reg.h */ -+#define UART_IER_CTS 0x80 /* enable CTS interrupt */ -+#define UART_IER_RTS 0x40 /* enable RTS interrupt */ -+#define UART_IER_SLP 0x10 /* enable sleep mode */ -+#define UART_LCR_650 0xBF /* enable 650-compatible registers access */ -+#define UART_LSR_DE 0x80 /* data error */ -+#define UART_LSR_ERR (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE) -+#define UART_IIR_RXTOUT 0x0C /* RX timeout interrupt */ -+#define UART_IIR_CTSRTS 0x20 /* CTS or RTS change interrupt */ -+#define UART_IIR_RTS 0x40 -+#define UART_IIR_CTS 0x80 -+#define UART_IIR_MASK 0x3E /* interrupt mask */ -+#define UART_SRT 0x0D /* soft reset register */ -+ -+ -+ -+/* ======================== Interrupt handling ======================== */ -+ -+ -+static int bt950_write(unsigned int iobase, int fifo_size, const unsigned char *buf, int len) -+{ -+ int i, actual = 0; -+ -+ /* Activate DTR and RTS */ -+ outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, iobase + UART_MCR); -+ -+ /* Wait for CTS flow control */ -+ for (i = MAX_WAIT; i; i--) -+ if (inb(iobase + UART_MSR) & UART_MSR_CTS) -+ break; -+ -+ if (!i) { -+ printk(KERN_WARNING "bt950_cs: Timeout waiting for CTS on write.\n"); -+ return 0; -+ } -+ -+ /* The TX FIFO should be empty */ -+ for (i = MAX_WAIT; i; i--) -+ if (inb(iobase + UART_LSR) & UART_LSR_THRE) -+ break; -+ -+ if (!i) { -+ printk(KERN_WARNING "bt950_cs: Timeout waiting for empty TX FIFO on write.\n"); -+ return 0; -+ } -+ -+ /* Fill FIFO with current frame */ -+ while ((fifo_size-- > 0) && (actual < len)) { -+ /* Transmit next byte */ -+ outb(buf[actual], iobase + UART_TX); -+ actual++; -+ } -+ -+ return actual; -+} -+ -+ -+static void bt950_write_wakeup(bt950_info_t *info) -+{ -+ unsigned char lcr; -+ unsigned int divisor; -+ -+ if (!info) { -+ printk(KERN_WARNING "bt950_cs: Call of write_wakeup for unknown device.\n"); -+ return; -+ } -+ -+ if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { -+ set_bit(XMIT_WAKEUP, &(info->tx_state)); -+ return; -+ } -+ -+ do { -+ register unsigned int iobase = info->link.io.BasePort1; -+ register struct sk_buff *skb; -+ register int len; -+ -+ clear_bit(XMIT_WAKEUP, &(info->tx_state)); -+ -+ if (!(info->link.state & DEV_PRESENT)) -+ return; -+ -+ if (!(skb = skb_dequeue(&(info->txq)))) -+ break; -+ -+ if (skb->pkt_type & 0x80) { -+ /* Disable RTS */ -+ outb((inb(iobase + UART_MCR) & ~UART_MCR_RTS), iobase + UART_MCR); -+ } -+ -+ /* Send frame */ -+ len = bt950_write(iobase, FIFO_SIZE, skb->data, skb->len); -+ -+ set_bit(XMIT_WAKEUP, &(info->tx_state)); -+ -+ if (skb->pkt_type & 0x80) { -+ -+ wait_queue_head_t wait; -+ -+ switch (skb->pkt_type) { -+ -+ case PKT_BAUD_RATE_460800: -+ divisor = 1; -+ break; -+ -+ case PKT_BAUD_RATE_230400: -+ divisor = 2; -+ break; -+ -+ case PKT_BAUD_RATE_115200: -+ divisor = 4; -+ break; -+ -+ case PKT_BAUD_RATE_57600: -+ /* Fall through... */ -+ -+ default: -+ divisor = 8; -+ break; -+ } -+ -+ /* Wait until the command reaches the baseband */ -+ init_waitqueue_head(&wait); -+ interruptible_sleep_on_timeout(&wait, HZ / 10); -+ -+ /* Set baud on baseband */ -+ /* Enable divisor latch access */ -+ lcr = inb(iobase + UART_LCR) & 0x3F; -+ outb(lcr | UART_LCR_DLAB, iobase + UART_LCR); -+ -+ /* Setup divisor latch */ -+ outb(divisor & 0x00FF, iobase + UART_DLL); /* divisor latch LOW byte */ -+ outb((divisor & 0xFF00) >> 8, iobase + UART_DLM); /* divisor latch HI byte */ -+ -+ /* Disable divisor latch access */ -+ outb(lcr, iobase + UART_LCR); -+ -+ /* Enable RTS */ -+ outb((inb(iobase + UART_MCR) | UART_MCR_RTS), iobase + UART_MCR); -+ -+ /* Wait before the next HCI packet can be send */ -+ interruptible_sleep_on_timeout(&wait, HZ); -+ -+ } -+ -+ if (len == skb->len) { -+ kfree_skb(skb); -+ } else { -+ skb_pull(skb, len); -+ skb_queue_head(&(info->txq), skb); -+ } -+ -+ info->hdev.stat.byte_tx += len; -+ -+ } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); -+ -+ clear_bit(XMIT_SENDING, &(info->tx_state)); -+} -+ -+ -+static inline void bt950_receive(bt950_info_t *info) -+{ -+ unsigned int iobase; -+ int boguscount = 0; -+ -+ if (!info) { -+ printk(KERN_ERR "bt950_cs: Call of receive for unknown device.\n"); -+ return; -+ } -+ -+ iobase = info->link.io.BasePort1; -+ -+ /* Fixme: BUG? */ -+ inb(iobase + UART_MCR); -+ -+ do { -+ info->hdev.stat.byte_rx++; -+ -+ /* 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_ERR "bt950_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 = inb(iobase + UART_RX); -+ -+ switch (info->rx_skb->pkt_type) { -+ -+ 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 "bt950_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) = inb(iobase + UART_RX); -+ 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; -+ -+ } -+ -+ } -+ -+ } -+ -+ /* Make sure we don't stay here too long */ -+ if (boguscount++ > 16) -+ break; -+ -+ } while (inb(iobase + UART_LSR) & UART_LSR_DR); -+} -+ -+ -+static void bt950_interrupt(int irq, void *dev_inst, struct pt_regs *regs) -+{ -+ bt950_info_t *info = dev_inst; -+ unsigned int iobase; -+ int boguscount = 0; -+ int iir, lsr; -+ -+ if (!info) { -+ printk(KERN_ERR "bt950_cs: Call of irq %d for unknown device.\n", irq); -+ return; -+ } -+ -+ iobase = info->link.io.BasePort1; -+ -+ spin_lock(&(info->lock)); -+ -+ iir = inb(iobase + UART_IIR); -+ -+ while (!(iir & UART_IIR_NO_INT)) { -+ -+ switch (iir & UART_IIR_ID) { -+ case UART_IIR_RLSI: -+ /* Clear RLSI interrupt */ -+ lsr = inb(iobase + UART_LSR); -+ printk(KERN_NOTICE "bt950_cs: RLSI interrupt, LSR=%#x\n", lsr); -+ /* Fixme: we need to process errors ... */ -+ break; -+ case UART_IIR_RDI: -+ /* Receive interrupt */ -+ bt950_receive(info); -+ break; -+ case UART_IIR_THRI: -+ /* Transmitter ready for data */ -+ bt950_write_wakeup(info); -+ break; -+ default: -+ printk(KERN_NOTICE "bt950_cs: Unhandled IIR=%#x\n", iir); -+ break; -+ } -+ -+ /* Make sure we don't stay here too long */ -+ if (boguscount++ > 100) -+ break; -+ -+ iir = inb(iobase + UART_IIR); -+ -+ } -+ -+ spin_unlock(&(info->lock)); -+} -+ -+/* ======================== Device specific HCI commands ======================== */ -+ -+ -+static int bt950_hci_set_baud_rate(struct hci_dev *hdev, int baud) -+{ -+ bt950_info_t *info = (bt950_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 "bt950_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: -+ baud = 57600; -+ 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); -+ -+ printk(KERN_WARNING "bt950_cs: setting baud rate: %d.\n", baud); -+ -+ bt950_write_wakeup(info); -+ -+ return 0; -+} -+ -+ -+/* ======================== HCI interface ======================== */ -+ -+ -+static int bt950_hci_flush(struct hci_dev *hdev) -+{ -+ bt950_info_t *info = (bt950_info_t *)(hdev->driver_data); -+ -+ /* Drop TX queue */ -+ skb_queue_purge(&(info->txq)); -+ -+ return 0; -+} -+ -+ -+static int bt950_hci_open(struct hci_dev *hdev) -+{ -+ bt950_hci_set_baud_rate(hdev, baud_rate); -+ set_bit(HCI_RUNNING, &(hdev->flags)); -+ -+ return 0; -+} -+ -+ -+static int bt950_hci_close(struct hci_dev *hdev) -+{ -+ if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) -+ return 0; -+ -+ bt950_hci_flush(hdev); -+ -+ return 0; -+} -+ -+ -+static int bt950_hci_send_frame(struct sk_buff *skb) -+{ -+ bt950_info_t *info; -+ struct hci_dev *hdev = (struct hci_dev *)(skb->dev); -+ -+ if (!hdev) { -+ printk(KERN_ERR "bt950_cs: Frame for unknown HCI device (hdev=NULL)."); -+ return -ENODEV; -+ } -+ -+ info = (bt950_info_t *)(hdev->driver_data); -+ -+ switch (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), &(skb->pkt_type), 1); -+ skb_queue_tail(&(info->txq), skb); -+ -+ bt950_write_wakeup(info); -+ -+ return 0; -+} -+ -+ -+static void bt950_hci_destruct(struct hci_dev *hdev) -+{ -+} -+ -+ -+static int bt950_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) -+{ -+ return -ENOIOCTLCMD; -+} -+ -+ -+ -+/* ======================== Card services HCI interaction ======================== */ -+ -+ -+static int bt950_setup_uart(bt950_info_t *info) -+{ -+ unsigned long flags; -+ unsigned int iobase = info->link.io.BasePort1; -+ unsigned char lcr, ier = UART_IER_RDI | UART_IER_RLSI | UART_IER_SLP; -+ unsigned int divisor = 8; /* Fixme: divisor == 0x0c ??? */ -+ unsigned char id1, id2, id3, rev; -+ register int i; -+ -+ spin_lock_irqsave(&(info->lock), flags); -+ -+ /* Disable interrupts */ -+ outb(0, iobase + UART_IER); -+ -+ /* Activate RTS and OUT2 */ -+ /* Fixme: is OUT2 used to enable interrupts? */ -+ outb(UART_MCR_RTS | UART_MCR_OUT2, iobase + UART_MCR); -+ -+ /* Setup the FIFO's */ -+ outb(0, iobase + UART_FCR); -+ inb(iobase + UART_RX); -+ outb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | -+ UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_14, iobase + UART_FCR); -+ -+ /* Disable divisor latch access */ -+ lcr = inb(iobase + UART_LCR) & 0x3F; /* mask out UART_LCR_DLAB and UART_LCR_SBC */ -+ outb(lcr, iobase + UART_LCR); -+ -+ /* Read up to 4 bytes from RX FIFO */ -+ for (i = 0; i < 4; i++) { -+ inb(iobase + UART_RX); -+ if (!(inb(iobase + UART_LSR) & UART_LSR_DR)) -+ break; -+ } -+ -+ /* Wait if CTS/DSR/DCD changing */ -+ for (i = 1; i < 0x3E8; i++) { -+ if (!(inb(iobase + UART_MSR) & UART_MSR_ANY_DELTA)) -+ break; -+ } -+ -+ /* Enable divisor latch access */ -+ outb(lcr | UART_LCR_DLAB, iobase + UART_LCR); -+ -+ /* Setup divisor latch */ -+ outb(divisor & 0x00FF, iobase + UART_DLL); /* divisor latch LOW byte */ -+ outb((divisor & 0xFF00) >> 8, iobase + UART_DLM); /* divisor latch HIGH byte */ -+ -+ /* Disable divisor latch access */ -+ outb(lcr, iobase + UART_LCR); -+ -+ /* Setup interrupts, enable sleep mode */ -+ outb(ier, iobase + UART_IER); /* we don't want to handle TX interrupts */ -+ -+ /* Skip pending interrupts */ -+ for (i = 0; i < 4; i++) { -+ if (inb(iobase + UART_IIR) & UART_IIR_NO_INT) -+ break; -+ } -+ -+ /* 8N1 */ -+ lcr = UART_LCR_WLEN8; -+ outb(lcr, iobase + UART_LCR); -+ -+ /* Setup CTS/RTS flow control and 950 enhanced mode */ -+ outb(UART_LCR_650, iobase + UART_LCR); -+ outb(UART_EFR_CTS | UART_EFR_RTS | UART_EFR_ECB, -+ iobase + UART_EFR); -+ outb(lcr, iobase + UART_LCR); -+ -+ /* Read core id and revision */ -+ outb(UART_ACR, iobase + UART_EMSR); -+ outb(UART_ACR_ICRRD, iobase + UART_LSR); /* enable ICR read access, we don't need to save the old value of ACR */ -+ -+ outb(UART_ID1, iobase + UART_EMSR); -+ id1 = inb(iobase + UART_LSR); -+ -+ outb(UART_ID2, iobase + UART_EMSR); -+ id2 = inb(iobase + UART_LSR); -+ -+ outb(UART_ID3, iobase + UART_EMSR); -+ id3 = inb(iobase + UART_LSR); -+ -+ outb(UART_REV, iobase + UART_EMSR); -+ rev = inb(iobase + UART_LSR); -+ -+ if (id1 != 0x16 || id2 != 0xC9 || id3 != 0x50) { -+ printk(KERN_ERR "bt950_cs: Unknown UART core %02X%02X%02X found.\n", id1, id2, id3); -+ spin_unlock_irqrestore(&(info->lock), flags); -+ return -ENODEV; -+ } -+ -+ -+ /* Init ICR registers */ -+ outb(UART_TTL, iobase + UART_EMSR); -+ outb(TR_TX_INT, iobase + UART_LSR); /* TX interrupt trigger level (0-127) */ -+ -+ outb(UART_RTL, iobase + UART_EMSR); -+ outb(TR_RX_INT, iobase + UART_LSR); /* RX interrupt trigger level (1-127) */ -+ -+ outb(UART_FCL, iobase + UART_EMSR); -+ outb(TR_CTL_LO, iobase + UART_LSR); /* auto flow control LOWER trigger level (0-127) */ -+ -+ outb(UART_FCH, iobase + UART_EMSR); -+ outb(TR_CTL_HI, iobase + UART_LSR); /* auto flow control HIGH trigger level (1-127) */ -+ -+ outb(UART_ACR, iobase + UART_EMSR); -+ outb(UART_ACR_TLENB, iobase + UART_LSR); /* disable ICR read access, enable trigger levels */ -+ -+ spin_unlock_irqrestore(&(info->lock), flags); -+ -+ return 0; -+} -+ -+ -+static void bt950_stop_uart(bt950_info_t *info) -+{ -+ unsigned long flags; -+ unsigned int iobase = info->link.io.BasePort1; -+ -+ spin_lock_irqsave(&(info->lock), flags); -+ -+ /* Disable interrupts */ -+ outb(0, iobase + UART_IER); -+ -+ /* Set RTS and OUT2 low */ -+ outb(0, iobase + UART_MCR); -+ -+ spin_unlock_irqrestore(&(info->lock), flags); -+} -+ -+ -+static int bt950_open(bt950_info_t *info) -+{ -+ struct hci_dev *hdev; -+ int err; -+ -+ spin_lock_init(&(info->lock)); -+ -+ skb_queue_head_init(&(info->txq)); -+ -+ info->rx_state = RECV_WAIT_PACKET_TYPE; -+ info->rx_count = 0; -+ info->rx_skb = NULL; -+ -+ /* Setup hardware */ -+ if ((err = bt950_setup_uart(info)) < 0) -+ return err; -+ -+ /* Timeout before it is safe to send the first HCI packet */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(HZ); -+ -+ -+ /* Initialize and register HCI device */ -+ -+ hdev = &(info->hdev); -+ -+ hdev->type = HCI_PCCARD; -+ hdev->driver_data = info; -+ -+ hdev->open = bt950_hci_open; -+ hdev->close = bt950_hci_close; -+ hdev->flush = bt950_hci_flush; -+ hdev->send = bt950_hci_send_frame; -+ hdev->destruct = bt950_hci_destruct; -+ hdev->ioctl = bt950_hci_ioctl; -+ -+ if (hci_register_dev(hdev) < 0) { -+ printk(KERN_ERR "bt950_cs: Can't register HCI device %s.\n", hdev->name); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+ -+static int bt950_close(bt950_info_t *info) -+{ -+ struct hci_dev *hdev = &(info->hdev); -+ -+ bt950_hci_close(hdev); -+ -+ /* Stop hardware */ -+ bt950_stop_uart(info); -+ -+ if (hci_unregister_dev(hdev) < 0) -+ printk(KERN_ERR "bt950_cs: Can't unregister HCI device %s.\n", hdev->name); -+ -+ return 0; -+} -+ -+ -+ -+/* ======================== Card services ======================== */ -+ -+ -+static void cs_error(client_handle_t handle, int func, int ret) -+{ -+ error_info_t err = { func, ret }; -+ -+ CardServices(ReportError, handle, &err); -+} -+ -+ -+static dev_link_t *bt950_attach(void) -+{ -+ bt950_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); -+ if (!info) -+ return NULL; -+ memset(info, 0, sizeof(*info)); -+ -+ link = &info->link; -+ link->priv = info; -+ -+ link->release.function = &bt950_release; -+ link->release.data = (u_long)link; -+ 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.Handler = bt950_interrupt; -+ link->irq.Instance = info; -+ -+ link->conf.Attributes = CONF_ENABLE_IRQ; -+ link->conf.IntType = INT_MEMORY_AND_IO; -+ link->conf.Present = -+ PRESENT_OPTION | PRESENT_STATUS | PRESENT_PIN_REPLACE | -+ PRESENT_COPY; -+ -+ /* 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 = &bt950_event; -+ client_reg.Version = 0x0210; -+ client_reg.event_callback_args.client_data = link; -+ -+ ret = CardServices(RegisterClient, &link->handle, &client_reg); -+ if (ret != CS_SUCCESS) { -+ cs_error(link->handle, RegisterClient, ret); -+ bt950_detach(link); -+ return NULL; -+ } -+ -+ return link; -+} -+ -+ -+static void bt950_detach(dev_link_t *link) -+{ -+ bt950_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; -+ -+ del_timer(&link->release); -+ if (link->state & DEV_CONFIG) -+ bt950_release((u_long) link); -+ -+ if (link->handle) { -+ ret = CardServices(DeregisterClient, link->handle); -+ if (ret != CS_SUCCESS) -+ cs_error(link->handle, DeregisterClient, ret); -+ } -+ -+ /* Unlink device structure, free bits */ -+ *linkp = link->next; -+ -+ kfree(info); -+} -+ -+ -+static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse) -+{ -+ int i; -+ -+ i = CardServices(fn, handle, tuple); -+ if (i != CS_SUCCESS) -+ return CS_NO_MORE_ITEMS; -+ -+ i = CardServices(GetTupleData, handle, tuple); -+ if (i != CS_SUCCESS) -+ return i; -+ -+ return CardServices(ParseTuple, handle, tuple, parse); -+} -+ -+ -+#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) -+#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) -+ -+static void bt950_config(dev_link_t *link) -+{ -+ static ioaddr_t base[4] = { 0x2f8, 0x3e8, 0x2e8, 0x0 }; -+ client_handle_t handle = link->handle; -+ bt950_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; -+ tuple.TupleOffset = 0; -+ tuple.TupleDataMax = 255; -+ tuple.Attributes = 0; -+ -+ /* Get configuration register information */ -+ tuple.DesiredTuple = CISTPL_CONFIG; -+ last_ret = first_tuple(handle, &tuple, &parse); -+ if (last_ret != CS_SUCCESS) { -+ last_fn = ParseTuple; -+ goto cs_failed; -+ } -+ link->conf.ConfigBase = parse.config.base; -+ link->conf.Present = parse.config.rmask[0]; -+ -+ /* Configure card */ -+ link->state |= DEV_CONFIG; -+ i = CardServices(GetConfigurationInfo, 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; -+ 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(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.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 = CardServices(RequestIO, link->handle, &link->io); -+ if (i == CS_SUCCESS) -+ goto found_port; -+ } -+next_entry: -+ 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(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 = CardServices(RequestIO, link->handle, &link->io); -+ if (i == CS_SUCCESS) -+ goto found_port; -+ } -+ } -+ i = next_tuple(handle, &tuple, &parse); -+ } -+ -+found_port: -+ if (i != CS_SUCCESS) { -+ printk(KERN_ERR "bt950_cs: No usable port range found. Giving up.\n"); -+ cs_error(link->handle, RequestIO, i); -+ goto failed; -+ } -+ -+ i = CardServices(RequestIRQ, link->handle, &link->irq); -+ if (i != CS_SUCCESS) { -+ cs_error(link->handle, RequestIRQ, i); -+ link->irq.AssignedIRQ = 0; -+ } -+ -+ i = CardServices(RequestConfiguration, link->handle, &link->conf); -+ if (i != CS_SUCCESS) { -+ cs_error(link->handle, RequestConfiguration, i); -+ goto failed; -+ } -+ -+ MOD_INC_USE_COUNT; -+ -+ if (bt950_open(info) != 0) -+ goto failed; -+ -+ strcpy(info->node.dev_name, info->hdev.name); -+ link->dev = &info->node; -+ link->state &= ~DEV_CONFIG_PENDING; -+ -+ return; -+ -+cs_failed: -+ cs_error(link->handle, last_fn, last_ret); -+ -+failed: -+ bt950_release((u_long)link); -+ link->state &= ~DEV_CONFIG_PENDING; -+} -+ -+ -+static void bt950_release(u_long arg) -+{ -+ dev_link_t *link = (dev_link_t *) arg; -+ bt950_info_t *info = link->priv; -+ -+ if (link->state & DEV_PRESENT) -+ bt950_close(info); -+ -+ MOD_DEC_USE_COUNT; -+ -+ link->dev = NULL; -+ -+ CardServices(ReleaseConfiguration, link->handle); -+ CardServices(ReleaseIO, link->handle, &link->io); -+ CardServices(ReleaseIRQ, link->handle, &link->irq); -+ -+ link->state &= ~DEV_CONFIG; -+} -+ -+ -+static int bt950_event(event_t event, int priority, event_callback_args_t *args) -+{ -+ dev_link_t *link = args->client_data; -+ bt950_info_t *info = link->priv; -+ -+ switch (event) { -+ case CS_EVENT_CARD_REMOVAL: -+ link->state &= ~DEV_PRESENT; -+ if (link->state & DEV_CONFIG) { -+ bt950_close(info); -+ link->state |= DEV_RELEASE_PENDING; -+ mod_timer(&link->release, jiffies + HZ / 20); -+ } -+ break; -+ case CS_EVENT_CARD_INSERTION: -+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; -+ bt950_config(link); -+ break; -+ case CS_EVENT_PM_SUSPEND: -+ link->state |= DEV_SUSPEND; -+ /* Fall through... */ -+ case CS_EVENT_RESET_PHYSICAL: -+ if (link->state & DEV_CONFIG) { -+ bt950_stop_uart(info); -+ CardServices(ReleaseConfiguration, link->handle); -+ } -+ break; -+ case CS_EVENT_PM_RESUME: -+ link->state &= ~DEV_SUSPEND; -+ /* Fall through... */ -+ case CS_EVENT_CARD_RESET: -+ if (link->state & DEV_CONFIG) { -+ CardServices(RequestConfiguration, link->handle, &link->conf); -+ bt950_setup_uart(info); -+ } -+ break; -+ } -+ -+ return 0; -+} -+ -+ -+ -+/* ======================== Module initialization ======================== */ -+ -+ -+int __init init_bt950_cs(void) -+{ -+ servinfo_t serv; -+ int err; -+ -+ CardServices(GetCardServicesInfo, &serv); -+ if (serv.Revision != CS_RELEASE_CODE) { -+ printk(KERN_NOTICE "bt950_cs: Card Services release does not match!\n"); -+// return -1; -+ } -+ -+ err = register_pccard_driver(&dev_info, &bt950_attach, &bt950_detach); -+ -+ return err; -+} -+ -+ -+void __exit exit_bt950_cs(void) -+{ -+ unregister_pccard_driver(&dev_info); -+ -+ while (dev_list != NULL) -+ bt950_detach(dev_list); -+} -+ -+ -+module_init(init_bt950_cs); -+module_exit(exit_bt950_cs); -+ -+EXPORT_NO_SYMBOLS; -diff -Nur linux-orig/drivers/bluetooth/Config.in linux/drivers/bluetooth/Config.in ---- linux-orig/drivers/bluetooth/Config.in 2004-02-16 08:45:33.000000000 +0300 -+++ linux/drivers/bluetooth/Config.in 2004-02-16 08:50:36.000000000 +0300 -@@ -21,7 +21,7 @@ - - dep_tristate 'HCI DTL1 (PC Card) driver' CONFIG_BLUEZ_HCIDTL1 $CONFIG_PCMCIA $CONFIG_BLUEZ - --dep_tristate 'HCI BT3C (PC Card) driver' CONFIG_BLUEZ_HCIBT3C $CONFIG_PCMCIA $CONFIG_BLUEZ -+# dep_tristate 'HCI BT3C (PC Card) driver' CONFIG_BLUEZ_HCIBT3C $CONFIG_PCMCIA $CONFIG_BLUEZ - - dep_tristate 'HCI BlueCard (PC Card) driver' CONFIG_BLUEZ_HCIBLUECARD $CONFIG_PCMCIA $CONFIG_BLUEZ - -@@ -29,5 +29,7 @@ - - dep_tristate 'HCI VHCI (Virtual HCI device) driver' CONFIG_BLUEZ_HCIVHCI $CONFIG_BLUEZ - -+dep_tristate 'HCI BT950 (BT950 device) driver' CONFIG_BLUEZ_BT950 $CONFIG_BLUEZ -+ - endmenu - -diff -Nur linux-orig/drivers/bluetooth/Makefile linux/drivers/bluetooth/Makefile ---- linux-orig/drivers/bluetooth/Makefile 2004-02-16 08:45:33.000000000 +0300 -+++ linux/drivers/bluetooth/Makefile 2004-02-16 08:50:47.000000000 +0300 -@@ -17,10 +17,12 @@ - obj-$(CONFIG_BLUEZ_HCIBFUSB) += bfusb.o - - obj-$(CONFIG_BLUEZ_HCIDTL1) += dtl1_cs.o --obj-$(CONFIG_BLUEZ_HCIBT3C) += bt3c_cs.o -+# obj-$(CONFIG_BLUEZ_HCIBT3C) += bt3c_cs.o - obj-$(CONFIG_BLUEZ_HCIBLUECARD) += bluecard_cs.o - obj-$(CONFIG_BLUEZ_HCIBTUART) += btuart_cs.o - -+obj-$(CONFIG_BLUEZ_BT950) += bt950_cs.o -+ - include $(TOPDIR)/Rules.make - - hci_uart.o: $(uart-y) |