public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: "Christophe Leroy (CS GROUP)" <chleroy@kernel.org>
To: Ethan Nelson-Moore <enelsonmoore@gmail.com>,
	linux-mips@vger.kernel.org, linux-bluetooth@vger.kernel.org
Cc: "Dominik Brodowski" <linux@dominikbrodowski.net>,
	"Ondrej Zary" <linux@rainbow-software.org>,
	"Russell King" <linux@armlinux.org.uk>,
	"Huacai Chen" <chenhuacai@kernel.org>,
	"WANG Xuerui" <kernel@xen0n.name>,
	"Thomas Bogendoerfer" <tsbogend@alpha.franken.de>,
	"Madhavan Srinivasan" <maddy@linux.ibm.com>,
	"Michael Ellerman" <mpe@ellerman.id.au>,
	"Nicholas Piggin" <npiggin@gmail.com>,
	"Marcel Holtmann" <marcel@holtmann.org>,
	"Luiz Augusto von Dentz" <luiz.dentz@gmail.com>,
	"Eric Biggers" <ebiggers@kernel.org>,
	"Ard Biesheuvel" <ardb@kernel.org>,
	"Herbert Xu" <herbert@gondor.apana.org.au>,
	"Martin K. Petersen" <martin.petersen@oracle.com>,
	"Theodore Ts'o" <tytso@mit.edu>,
	"André Draszik" <andre.draszik@linaro.org>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Johannes Weiner" <hannes@cmpxchg.org>,
	"Yosry Ahmed" <yosry.ahmed@linux.dev>,
	"Jakub Kicinski" <kuba@kernel.org>,
	"Paul Moore" <paul@paul-moore.com>,
	"Simon Horman" <horms@kernel.org>,
	"Casey Schaufler" <casey@schaufler-ca.com>,
	"Kuniyuki Iwashima" <kuniyu@google.com>
Subject: Re: [RFC PATCH] bluetooth: remove all PCMCIA drivers
Date: Wed, 11 Feb 2026 21:40:34 +0100	[thread overview]
Message-ID: <9085df16-4de4-49d6-9b9b-ba27367619ee@kernel.org> (raw)
In-Reply-To: <20260211082246.41148-1-enelsonmoore@gmail.com>



Le 11/02/2026 à 09:22, Ethan Nelson-Moore a écrit :
> PCMCIA is almost completely obsolete (the last computers supporting it
> natively were from ~2009), and the general consensus [1] seems to be
> that support for it should be gradually removed from the kernel.
> 
> In 2023, an initial step of removing all the PCMCIA char drivers was
> taken in commit 9b12f050c76f ("char: pcmcia: remove all the drivers"),
> and that has not been reverted, so it seems logical to continue this
> process by removing more low-hanging fruit.
> 
> These three Bluetooth drivers have had no meaningful changes since
> their status was discussed in 2022 [2], and are unlikely to have any
> remaining users. The latest functional change to any of them was a
> patch to bluecard_cs to fix LED blinking behavior in 2017. The other
> two drivers have not had any meaningful changes made since 2007. Remove
> them.
> 
> Note that even with these drivers removed, it is still possible to use
> other PCMCIA Bluetooth cards that present themselves as a standard
> serial port via serial_cs and hciattach while the serial_cs driver is
> still present.
> 
> [1] https://lore.kernel.org/all/c5b39544-a4fb-4796-a046-0b9be9853787@app.fastmail.com/
> [2] https://lore.kernel.org/all/Y07d7rMvd5++85BJ@owl.dominikbrodowski.net/
> 
> Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
> ---
>   arch/arm/configs/pxa_defconfig              |   3 -
>   arch/arm/configs/spitz_defconfig            |   3 -
>   arch/loongarch/configs/loongson32_defconfig |   3 -
>   arch/loongarch/configs/loongson64_defconfig |   3 -
>   arch/mips/configs/mtx1_defconfig            |   3 -
>   arch/powerpc/configs/ppc6xx_defconfig       |   3 -


Acked-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org> # powerpc/32



>   drivers/bluetooth/Kconfig                   |  40 -
>   drivers/bluetooth/Makefile                  |   3 -
>   drivers/bluetooth/bluecard_cs.c             | 908 --------------------
>   drivers/bluetooth/bt3c_cs.c                 | 749 ----------------
>   drivers/bluetooth/dtl1_cs.c                 | 614 -------------
>   11 files changed, 2332 deletions(-)
>   delete mode 100644 drivers/bluetooth/bluecard_cs.c
>   delete mode 100644 drivers/bluetooth/bt3c_cs.c
>   delete mode 100644 drivers/bluetooth/dtl1_cs.c
> 
> diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig
> index eacd08fd87ad..ec06f41b9df0 100644
> --- a/arch/arm/configs/pxa_defconfig
> +++ b/arch/arm/configs/pxa_defconfig
> @@ -77,9 +77,6 @@ CONFIG_BT_HCIUART_BCSP=y
>   CONFIG_BT_HCIBCM203X=m
>   CONFIG_BT_HCIBPA10X=m
>   CONFIG_BT_HCIBFUSB=m
> -CONFIG_BT_HCIDTL1=m
> -CONFIG_BT_HCIBT3C=m
> -CONFIG_BT_HCIBLUECARD=m
>   CONFIG_BT_HCIBTUART=m
>   CONFIG_BT_HCIVHCI=m
>   CONFIG_BT_MRVL=m
> diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
> index c130af6d44d4..a071f579b87d 100644
> --- a/arch/arm/configs/spitz_defconfig
> +++ b/arch/arm/configs/spitz_defconfig
> @@ -62,9 +62,6 @@ CONFIG_BT_HCIUART_BCSP=y
>   CONFIG_BT_HCIBCM203X=m
>   CONFIG_BT_HCIBPA10X=m
>   CONFIG_BT_HCIBFUSB=m
> -CONFIG_BT_HCIDTL1=m
> -CONFIG_BT_HCIBT3C=m
> -CONFIG_BT_HCIBLUECARD=m
>   CONFIG_BT_HCIBTUART=m
>   CONFIG_BT_HCIVHCI=m
>   CONFIG_PCCARD=y
> diff --git a/arch/loongarch/configs/loongson32_defconfig b/arch/loongarch/configs/loongson32_defconfig
> index 276b1577e0be..62e16600a987 100644
> --- a/arch/loongarch/configs/loongson32_defconfig
> +++ b/arch/loongarch/configs/loongson32_defconfig
> @@ -383,9 +383,6 @@ CONFIG_BT_HCIUART_AG6XX=y
>   CONFIG_BT_HCIBCM203X=m
>   CONFIG_BT_HCIBPA10X=m
>   CONFIG_BT_HCIBFUSB=m
> -CONFIG_BT_HCIDTL1=m
> -CONFIG_BT_HCIBT3C=m
> -CONFIG_BT_HCIBLUECARD=m
>   CONFIG_BT_HCIVHCI=m
>   CONFIG_BT_MRVL=m
>   CONFIG_BT_ATH3K=m
> diff --git a/arch/loongarch/configs/loongson64_defconfig b/arch/loongarch/configs/loongson64_defconfig
> index a14db1a95e7e..0124be356b8c 100644
> --- a/arch/loongarch/configs/loongson64_defconfig
> +++ b/arch/loongarch/configs/loongson64_defconfig
> @@ -399,9 +399,6 @@ CONFIG_BT_HCIUART_AG6XX=y
>   CONFIG_BT_HCIBCM203X=m
>   CONFIG_BT_HCIBPA10X=m
>   CONFIG_BT_HCIBFUSB=m
> -CONFIG_BT_HCIDTL1=m
> -CONFIG_BT_HCIBT3C=m
> -CONFIG_BT_HCIBLUECARD=m
>   CONFIG_BT_HCIVHCI=m
>   CONFIG_BT_MRVL=m
>   CONFIG_BT_ATH3K=m
> diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
> index c58d1a61d528..8ed504f80530 100644
> --- a/arch/mips/configs/mtx1_defconfig
> +++ b/arch/mips/configs/mtx1_defconfig
> @@ -200,9 +200,6 @@ CONFIG_BT_HCIUART_BCSP=y
>   CONFIG_BT_HCIBCM203X=m
>   CONFIG_BT_HCIBPA10X=m
>   CONFIG_BT_HCIBFUSB=m
> -CONFIG_BT_HCIDTL1=m
> -CONFIG_BT_HCIBT3C=m
> -CONFIG_BT_HCIBLUECARD=m
>   CONFIG_BT_HCIVHCI=m
>   CONFIG_CONNECTOR=m
>   CONFIG_MTD=y
> diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
> index 787d707f64a4..86812dbb4318 100644
> --- a/arch/powerpc/configs/ppc6xx_defconfig
> +++ b/arch/powerpc/configs/ppc6xx_defconfig
> @@ -287,9 +287,6 @@ CONFIG_BT_HCIUART_BCSP=y
>   CONFIG_BT_HCIBCM203X=m
>   CONFIG_BT_HCIBPA10X=m
>   CONFIG_BT_HCIBFUSB=m
> -CONFIG_BT_HCIDTL1=m
> -CONFIG_BT_HCIBT3C=m
> -CONFIG_BT_HCIBLUECARD=m
>   CONFIG_BT_HCIVHCI=m
>   CONFIG_CFG80211=m
>   CONFIG_MAC80211=m
> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
> index c5d45cf91f88..c94e8833ac8e 100644
> --- a/drivers/bluetooth/Kconfig
> +++ b/drivers/bluetooth/Kconfig
> @@ -337,46 +337,6 @@ config BT_HCIBFUSB
>   	  Say Y here to compile support for HCI BFUSB devices into the
>   	  kernel or say M to compile it as module (bfusb).
>   
> -config BT_HCIDTL1
> -	tristate "HCI DTL1 (PC Card) driver"
> -	depends on PCMCIA && HAS_IOPORT
> -	help
> -	  Bluetooth HCI DTL1 (PC Card) driver.
> -	  This driver provides support for Bluetooth PCMCIA devices with
> -	  Nokia DTL1 interface:
> -	     Nokia Bluetooth Card
> -	     Socket Bluetooth CF Card
> -
> -	  Say Y here to compile support for HCI DTL1 devices into the
> -	  kernel or say M to compile it as module (dtl1_cs).
> -
> -config BT_HCIBT3C
> -	tristate "HCI BT3C (PC Card) driver"
> -	depends on PCMCIA && HAS_IOPORT
> -	select FW_LOADER
> -	help
> -	  Bluetooth HCI BT3C (PC Card) driver.
> -	  This driver provides support for Bluetooth PCMCIA devices with
> -	  3Com BT3C interface:
> -	     3Com Bluetooth Card (3CRWB6096)
> -	     HP Bluetooth Card
> -
> -	  Say Y here to compile support for HCI BT3C devices into the
> -	  kernel or say M to compile it as module (bt3c_cs).
> -
> -config BT_HCIBLUECARD
> -	tristate "HCI BlueCard (PC Card) driver"
> -	depends on PCMCIA && HAS_IOPORT
> -	help
> -	  Bluetooth HCI BlueCard (PC Card) driver.
> -	  This driver provides support for Bluetooth PCMCIA devices with
> -	  Anycom BlueCard interface:
> -	     Anycom Bluetooth PC Card
> -	     Anycom Bluetooth CF Card
> -
> -	  Say Y here to compile support for HCI BlueCard devices into the
> -	  kernel or say M to compile it as module (bluecard_cs).
> -
>   config BT_HCIVHCI
>   	tristate "HCI VHCI (Virtual HCI device) driver"
>   	select WANT_DEV_COREDUMP
> diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
> index 81856512ddd0..bafc26250b63 100644
> --- a/drivers/bluetooth/Makefile
> +++ b/drivers/bluetooth/Makefile
> @@ -9,9 +9,6 @@ obj-$(CONFIG_BT_HCIBCM203X)	+= bcm203x.o
>   obj-$(CONFIG_BT_HCIBCM4377)	+= hci_bcm4377.o
>   obj-$(CONFIG_BT_HCIBPA10X)	+= bpa10x.o
>   obj-$(CONFIG_BT_HCIBFUSB)	+= bfusb.o
> -obj-$(CONFIG_BT_HCIDTL1)	+= dtl1_cs.o
> -obj-$(CONFIG_BT_HCIBT3C)	+= bt3c_cs.o
> -obj-$(CONFIG_BT_HCIBLUECARD)	+= bluecard_cs.o
>   
>   obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o
>   obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o
> diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
> deleted file mode 100644
> index 1e3a56e9b139..000000000000
> --- a/drivers/bluetooth/bluecard_cs.c
> +++ /dev/null
> @@ -1,908 +0,0 @@
> -/*
> - *
> - *  Bluetooth driver for the Anycom BlueCard (LSE039/LSE041)
> - *
> - *  Copyright (C) 2001-2002  Marcel Holtmann <marcel@holtmann.org>
> - *
> - *
> - *  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/module.h>
> -
> -#include <linux/kernel.h>
> -#include <linux/init.h>
> -#include <linux/slab.h>
> -#include <linux/types.h>
> -#include <linux/sched.h>
> -#include <linux/delay.h>
> -#include <linux/timer.h>
> -#include <linux/errno.h>
> -#include <linux/ptrace.h>
> -#include <linux/ioport.h>
> -#include <linux/spinlock.h>
> -#include <linux/moduleparam.h>
> -#include <linux/wait.h>
> -
> -#include <linux/skbuff.h>
> -#include <linux/io.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>
> -
> -
> -
> -/* ======================== Module parameters ======================== */
> -
> -
> -MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
> -MODULE_DESCRIPTION("Bluetooth driver for the Anycom BlueCard (LSE039/LSE041)");
> -MODULE_LICENSE("GPL");
> -
> -
> -
> -/* ======================== Local structures ======================== */
> -
> -
> -struct bluecard_info {
> -	struct pcmcia_device *p_dev;
> -
> -	struct hci_dev *hdev;
> -
> -	spinlock_t lock;		/* For serializing operations */
> -	struct timer_list timer;	/* For LED control */
> -
> -	struct sk_buff_head txq;
> -	unsigned long tx_state;
> -
> -	unsigned long rx_state;
> -	unsigned long rx_count;
> -	struct sk_buff *rx_skb;
> -
> -	unsigned char ctrl_reg;
> -	unsigned long hw_state;		/* Status of the hardware and LED control */
> -};
> -
> -
> -static int bluecard_config(struct pcmcia_device *link);
> -static void bluecard_release(struct pcmcia_device *link);
> -
> -static void bluecard_detach(struct pcmcia_device *p_dev);
> -
> -
> -/* Default baud rate: 57600, 115200, 230400 or 460800 */
> -#define DEFAULT_BAUD_RATE  230400
> -
> -
> -/* Hardware states */
> -#define CARD_READY             1
> -#define CARD_ACTIVITY	       2
> -#define CARD_HAS_PCCARD_ID     4
> -#define CARD_HAS_POWER_LED     5
> -#define CARD_HAS_ACTIVITY_LED  6
> -
> -/* Transmit states  */
> -#define XMIT_SENDING         1
> -#define XMIT_WAKEUP          2
> -#define XMIT_BUFFER_NUMBER   5	/* unset = buffer one, set = buffer two */
> -#define XMIT_BUF_ONE_READY   6
> -#define XMIT_BUF_TWO_READY   7
> -#define XMIT_SENDING_READY   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
> -
> -
> -/* These are the register offsets */
> -#define REG_COMMAND     0x20
> -#define REG_INTERRUPT   0x21
> -#define REG_CONTROL     0x22
> -#define REG_RX_CONTROL  0x24
> -#define REG_CARD_RESET  0x30
> -#define REG_LED_CTRL    0x30
> -
> -/* REG_COMMAND */
> -#define REG_COMMAND_TX_BUF_ONE  0x01
> -#define REG_COMMAND_TX_BUF_TWO  0x02
> -#define REG_COMMAND_RX_BUF_ONE  0x04
> -#define REG_COMMAND_RX_BUF_TWO  0x08
> -#define REG_COMMAND_RX_WIN_ONE  0x00
> -#define REG_COMMAND_RX_WIN_TWO  0x10
> -
> -/* REG_CONTROL */
> -#define REG_CONTROL_BAUD_RATE_57600   0x00
> -#define REG_CONTROL_BAUD_RATE_115200  0x01
> -#define REG_CONTROL_BAUD_RATE_230400  0x02
> -#define REG_CONTROL_BAUD_RATE_460800  0x03
> -#define REG_CONTROL_RTS               0x04
> -#define REG_CONTROL_BT_ON             0x08
> -#define REG_CONTROL_BT_RESET          0x10
> -#define REG_CONTROL_BT_RES_PU         0x20
> -#define REG_CONTROL_INTERRUPT         0x40
> -#define REG_CONTROL_CARD_RESET        0x80
> -
> -/* REG_RX_CONTROL */
> -#define RTS_LEVEL_SHIFT_BITS  0x02
> -
> -
> -
> -/* ======================== LED handling routines ======================== */
> -
> -
> -static void bluecard_activity_led_timeout(struct timer_list *t)
> -{
> -	struct bluecard_info *info = timer_container_of(info, t, timer);
> -	unsigned int iobase = info->p_dev->resource[0]->start;
> -
> -	if (test_bit(CARD_ACTIVITY, &(info->hw_state))) {
> -		/* leave LED in inactive state for HZ/10 for blink effect */
> -		clear_bit(CARD_ACTIVITY, &(info->hw_state));
> -		mod_timer(&(info->timer), jiffies + HZ / 10);
> -	}
> -
> -	/* Disable activity LED, enable power LED */
> -	outb(0x08 | 0x20, iobase + 0x30);
> -}
> -
> -
> -static void bluecard_enable_activity_led(struct bluecard_info *info)
> -{
> -	unsigned int iobase = info->p_dev->resource[0]->start;
> -
> -	/* don't disturb running blink timer */
> -	if (timer_pending(&(info->timer)))
> -		return;
> -
> -	set_bit(CARD_ACTIVITY, &(info->hw_state));
> -
> -	if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) {
> -		/* Enable activity LED, keep power LED enabled */
> -		outb(0x18 | 0x60, iobase + 0x30);
> -	} else {
> -		/* Disable power LED */
> -		outb(0x00, iobase + 0x30);
> -	}
> -
> -	/* Stop the LED after HZ/10 */
> -	mod_timer(&(info->timer), jiffies + HZ / 10);
> -}
> -
> -
> -
> -/* ======================== Interrupt handling ======================== */
> -
> -
> -static int bluecard_write(unsigned int iobase, unsigned int offset, __u8 *buf, int len)
> -{
> -	int i, actual;
> -
> -	actual = (len > 15) ? 15 : len;
> -
> -	outb_p(actual, iobase + offset);
> -
> -	for (i = 0; i < actual; i++)
> -		outb_p(buf[i], iobase + offset + i + 1);
> -
> -	return actual;
> -}
> -
> -
> -static void bluecard_write_wakeup(struct bluecard_info *info)
> -{
> -	if (!info) {
> -		BT_ERR("Unknown device");
> -		return;
> -	}
> -
> -	if (!test_bit(XMIT_SENDING_READY, &(info->tx_state)))
> -		return;
> -
> -	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
> -		set_bit(XMIT_WAKEUP, &(info->tx_state));
> -		return;
> -	}
> -
> -	do {
> -		unsigned int iobase = info->p_dev->resource[0]->start;
> -		unsigned int offset;
> -		unsigned char command;
> -		unsigned long ready_bit;
> -		register struct sk_buff *skb;
> -		int len;
> -
> -		clear_bit(XMIT_WAKEUP, &(info->tx_state));
> -
> -		if (!pcmcia_dev_present(info->p_dev))
> -			return;
> -
> -		if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
> -			if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state)))
> -				break;
> -			offset = 0x10;
> -			command = REG_COMMAND_TX_BUF_TWO;
> -			ready_bit = XMIT_BUF_TWO_READY;
> -		} else {
> -			if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state)))
> -				break;
> -			offset = 0x00;
> -			command = REG_COMMAND_TX_BUF_ONE;
> -			ready_bit = XMIT_BUF_ONE_READY;
> -		}
> -
> -		skb = skb_dequeue(&(info->txq));
> -		if (!skb)
> -			break;
> -
> -		if (hci_skb_pkt_type(skb) & 0x80) {
> -			/* Disable RTS */
> -			info->ctrl_reg |= REG_CONTROL_RTS;
> -			outb(info->ctrl_reg, iobase + REG_CONTROL);
> -		}
> -
> -		/* Activate LED */
> -		bluecard_enable_activity_led(info);
> -
> -		/* Send frame */
> -		len = bluecard_write(iobase, offset, skb->data, skb->len);
> -
> -		/* Tell the FPGA to send the data */
> -		outb_p(command, iobase + REG_COMMAND);
> -
> -		/* Mark the buffer as dirty */
> -		clear_bit(ready_bit, &(info->tx_state));
> -
> -		if (hci_skb_pkt_type(skb) & 0x80) {
> -			DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
> -			DEFINE_WAIT(wait);
> -
> -			unsigned char baud_reg;
> -
> -			switch (hci_skb_pkt_type(skb)) {
> -			case PKT_BAUD_RATE_460800:
> -				baud_reg = REG_CONTROL_BAUD_RATE_460800;
> -				break;
> -			case PKT_BAUD_RATE_230400:
> -				baud_reg = REG_CONTROL_BAUD_RATE_230400;
> -				break;
> -			case PKT_BAUD_RATE_115200:
> -				baud_reg = REG_CONTROL_BAUD_RATE_115200;
> -				break;
> -			case PKT_BAUD_RATE_57600:
> -			default:
> -				baud_reg = REG_CONTROL_BAUD_RATE_57600;
> -				break;
> -			}
> -
> -			/* Wait until the command reaches the baseband */
> -			mdelay(100);
> -
> -			/* Set baud on baseband */
> -			info->ctrl_reg &= ~0x03;
> -			info->ctrl_reg |= baud_reg;
> -			outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -			/* Enable RTS */
> -			info->ctrl_reg &= ~REG_CONTROL_RTS;
> -			outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -			/* Wait before the next HCI packet can be send */
> -			mdelay(1000);
> -		}
> -
> -		if (len == skb->len) {
> -			kfree_skb(skb);
> -		} else {
> -			skb_pull(skb, len);
> -			skb_queue_head(&(info->txq), skb);
> -		}
> -
> -		info->hdev->stat.byte_tx += len;
> -
> -		/* Change buffer */
> -		change_bit(XMIT_BUFFER_NUMBER, &(info->tx_state));
> -
> -	} while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
> -
> -	clear_bit(XMIT_SENDING, &(info->tx_state));
> -}
> -
> -
> -static int bluecard_read(unsigned int iobase, unsigned int offset, __u8 *buf, int size)
> -{
> -	int i, n, len;
> -
> -	outb(REG_COMMAND_RX_WIN_ONE, iobase + REG_COMMAND);
> -
> -	len = inb(iobase + offset);
> -	n = 0;
> -	i = 1;
> -
> -	while (n < len) {
> -
> -		if (i == 16) {
> -			outb(REG_COMMAND_RX_WIN_TWO, iobase + REG_COMMAND);
> -			i = 0;
> -		}
> -
> -		buf[n] = inb(iobase + offset + i);
> -
> -		n++;
> -		i++;
> -
> -	}
> -
> -	return len;
> -}
> -
> -
> -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) {
> -			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) {
> -
> -			hci_skb_pkt_type(info->rx_skb) = buf[i];
> -
> -			switch (hci_skb_pkt_type(info->rx_skb)) {
> -
> -			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",
> -				       hci_skb_pkt_type(info->rx_skb));
> -				info->hdev->stat.err_rx++;
> -
> -				kfree_skb(info->rx_skb);
> -				info->rx_skb = NULL;
> -				break;
> -
> -			}
> -
> -		} else {
> -
> -			skb_put_u8(info->rx_skb, 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 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;
> -}
> -
> -
> -
> -/* ======================== Device specific HCI commands ======================== */
> -
> -
> -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_KERNEL);
> -	if (!skb) {
> -		BT_ERR("Can't allocate mem for new packet");
> -		return -1;
> -	}
> -
> -	switch (baud) {
> -	case 460800:
> -		cmd[4] = 0x00;
> -		hci_skb_pkt_type(skb) = PKT_BAUD_RATE_460800;
> -		break;
> -	case 230400:
> -		cmd[4] = 0x01;
> -		hci_skb_pkt_type(skb) = PKT_BAUD_RATE_230400;
> -		break;
> -	case 115200:
> -		cmd[4] = 0x02;
> -		hci_skb_pkt_type(skb) = PKT_BAUD_RATE_115200;
> -		break;
> -	case 57600:
> -	default:
> -		cmd[4] = 0x03;
> -		hci_skb_pkt_type(skb) = PKT_BAUD_RATE_57600;
> -		break;
> -	}
> -
> -	skb_put_data(skb, cmd, sizeof(cmd));
> -
> -	skb_queue_tail(&(info->txq), skb);
> -
> -	bluecard_write_wakeup(info);
> -
> -	return 0;
> -}
> -
> -
> -
> -/* ======================== HCI interface ======================== */
> -
> -
> -static int bluecard_hci_flush(struct hci_dev *hdev)
> -{
> -	struct bluecard_info *info = hci_get_drvdata(hdev);
> -
> -	/* Drop TX queue */
> -	skb_queue_purge(&(info->txq));
> -
> -	return 0;
> -}
> -
> -
> -static int bluecard_hci_open(struct hci_dev *hdev)
> -{
> -	struct bluecard_info *info = hci_get_drvdata(hdev);
> -	unsigned int iobase = info->p_dev->resource[0]->start;
> -
> -	if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
> -		bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
> -
> -	/* Enable power LED */
> -	outb(0x08 | 0x20, iobase + 0x30);
> -
> -	return 0;
> -}
> -
> -
> -static int bluecard_hci_close(struct hci_dev *hdev)
> -{
> -	struct bluecard_info *info = hci_get_drvdata(hdev);
> -	unsigned int iobase = info->p_dev->resource[0]->start;
> -
> -	bluecard_hci_flush(hdev);
> -
> -	/* Stop LED timer */
> -	timer_delete_sync(&(info->timer));
> -
> -	/* Disable power LED */
> -	outb(0x00, iobase + 0x30);
> -
> -	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 (hci_skb_pkt_type(skb)) {
> -	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), &hci_skb_pkt_type(skb), 1);
> -	skb_queue_tail(&(info->txq), skb);
> -
> -	bluecard_write_wakeup(info);
> -
> -	return 0;
> -}
> -
> -
> -
> -/* ======================== Card services HCI interaction ======================== */
> -
> -
> -static int bluecard_open(struct bluecard_info *info)
> -{
> -	unsigned int iobase = info->p_dev->resource[0]->start;
> -	struct hci_dev *hdev;
> -	unsigned char id;
> -
> -	spin_lock_init(&(info->lock));
> -
> -	timer_setup(&info->timer, bluecard_activity_led_timeout, 0);
> -
> -	skb_queue_head_init(&(info->txq));
> -
> -	info->rx_state = RECV_WAIT_PACKET_TYPE;
> -	info->rx_count = 0;
> -	info->rx_skb = NULL;
> -
> -	/* Initialize HCI device */
> -	hdev = hci_alloc_dev();
> -	if (!hdev) {
> -		BT_ERR("Can't allocate HCI device");
> -		return -ENOMEM;
> -	}
> -
> -	info->hdev = hdev;
> -
> -	hdev->bus = HCI_PCCARD;
> -	hci_set_drvdata(hdev, info);
> -	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
> -
> -	hdev->open  = bluecard_hci_open;
> -	hdev->close = bluecard_hci_close;
> -	hdev->flush = bluecard_hci_flush;
> -	hdev->send  = bluecard_hci_send_frame;
> -
> -	id = inb(iobase + 0x30);
> -
> -	if ((id & 0x0f) == 0x02)
> -		set_bit(CARD_HAS_PCCARD_ID, &(info->hw_state));
> -
> -	if (id & 0x10)
> -		set_bit(CARD_HAS_POWER_LED, &(info->hw_state));
> -
> -	if (id & 0x20)
> -		set_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state));
> -
> -	/* Reset card */
> -	info->ctrl_reg = REG_CONTROL_BT_RESET | REG_CONTROL_CARD_RESET;
> -	outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -	/* Turn FPGA off */
> -	outb(0x80, iobase + 0x30);
> -
> -	/* Wait some time */
> -	msleep(10);
> -
> -	/* Turn FPGA on */
> -	outb(0x00, iobase + 0x30);
> -
> -	/* Activate card */
> -	info->ctrl_reg = REG_CONTROL_BT_ON | REG_CONTROL_BT_RES_PU;
> -	outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -	/* Enable interrupt */
> -	outb(0xff, iobase + REG_INTERRUPT);
> -	info->ctrl_reg |= REG_CONTROL_INTERRUPT;
> -	outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -	if ((id & 0x0f) == 0x03) {
> -		/* Disable RTS */
> -		info->ctrl_reg |= REG_CONTROL_RTS;
> -		outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -		/* Set baud rate */
> -		info->ctrl_reg |= 0x03;
> -		outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -		/* Enable RTS */
> -		info->ctrl_reg &= ~REG_CONTROL_RTS;
> -		outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -		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));
> -	}
> -
> -	/* Start the RX buffers */
> -	outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND);
> -	outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND);
> -
> -	/* Signal that the hardware is ready */
> -	set_bit(CARD_READY, &(info->hw_state));
> -
> -	/* Drop TX queue */
> -	skb_queue_purge(&(info->txq));
> -
> -	/* Control the point at which RTS is enabled */
> -	outb((0x0f << RTS_LEVEL_SHIFT_BITS) | 1, iobase + REG_RX_CONTROL);
> -
> -	/* Timeout before it is safe to send the first HCI packet */
> -	msleep(1250);
> -
> -	/* Register HCI device */
> -	if (hci_register_dev(hdev) < 0) {
> -		BT_ERR("Can't register HCI device");
> -		info->hdev = NULL;
> -		hci_free_dev(hdev);
> -		return -ENODEV;
> -	}
> -
> -	return 0;
> -}
> -
> -
> -static int bluecard_close(struct bluecard_info *info)
> -{
> -	unsigned int iobase = info->p_dev->resource[0]->start;
> -	struct hci_dev *hdev = info->hdev;
> -
> -	if (!hdev)
> -		return -ENODEV;
> -
> -	bluecard_hci_close(hdev);
> -
> -	clear_bit(CARD_READY, &(info->hw_state));
> -
> -	/* Reset card */
> -	info->ctrl_reg = REG_CONTROL_BT_RESET | REG_CONTROL_CARD_RESET;
> -	outb(info->ctrl_reg, iobase + REG_CONTROL);
> -
> -	/* Turn FPGA off */
> -	outb(0x80, iobase + 0x30);
> -
> -	hci_unregister_dev(hdev);
> -	hci_free_dev(hdev);
> -
> -	return 0;
> -}
> -
> -static int bluecard_probe(struct pcmcia_device *link)
> -{
> -	struct bluecard_info *info;
> -
> -	/* Create new info device */
> -	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
> -	if (!info)
> -		return -ENOMEM;
> -
> -	info->p_dev = link;
> -	link->priv = info;
> -
> -	link->config_flags |= CONF_ENABLE_IRQ;
> -
> -	return bluecard_config(link);
> -}
> -
> -
> -static void bluecard_detach(struct pcmcia_device *link)
> -{
> -	bluecard_release(link);
> -}
> -
> -
> -static int bluecard_config(struct pcmcia_device *link)
> -{
> -	struct bluecard_info *info = link->priv;
> -	int i, n;
> -
> -	link->config_index = 0x20;
> -
> -	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
> -	link->resource[0]->end = 64;
> -	link->io_lines = 6;
> -
> -	for (n = 0; n < 0x400; n += 0x40) {
> -		link->resource[0]->start = n ^ 0x300;
> -		i = pcmcia_request_io(link);
> -		if (i == 0)
> -			break;
> -	}
> -
> -	if (i != 0)
> -		goto failed;
> -
> -	i = pcmcia_request_irq(link, bluecard_interrupt);
> -	if (i != 0)
> -		goto failed;
> -
> -	i = pcmcia_enable_device(link);
> -	if (i != 0)
> -		goto failed;
> -
> -	if (bluecard_open(info) != 0)
> -		goto failed;
> -
> -	return 0;
> -
> -failed:
> -	bluecard_release(link);
> -	return -ENODEV;
> -}
> -
> -
> -static void bluecard_release(struct pcmcia_device *link)
> -{
> -	struct bluecard_info *info = link->priv;
> -
> -	bluecard_close(info);
> -
> -	timer_delete_sync(&(info->timer));
> -
> -	pcmcia_disable_device(link);
> -}
> -
> -static const struct pcmcia_device_id bluecard_ids[] = {
> -	PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e),
> -	PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c),
> -	PCMCIA_DEVICE_PROD_ID12("WSS", "LSE039", 0x0a0736ec, 0x24e6dfab),
> -	PCMCIA_DEVICE_NULL
> -};
> -MODULE_DEVICE_TABLE(pcmcia, bluecard_ids);
> -
> -static struct pcmcia_driver bluecard_driver = {
> -	.owner		= THIS_MODULE,
> -	.name		= "bluecard_cs",
> -	.probe		= bluecard_probe,
> -	.remove		= bluecard_detach,
> -	.id_table	= bluecard_ids,
> -};
> -module_pcmcia_driver(bluecard_driver);
> diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
> deleted file mode 100644
> index 54713833951a..000000000000
> --- a/drivers/bluetooth/bt3c_cs.c
> +++ /dev/null
> @@ -1,749 +0,0 @@
> -/*
> - *
> - *  Driver for the 3Com Bluetooth PCMCIA card
> - *
> - *  Copyright (C) 2001-2002  Marcel Holtmann <marcel@holtmann.org>
> - *                           Jose Orlando Pereira <jop@di.uminho.pt>
> - *
> - *
> - *  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/module.h>
> -
> -#include <linux/kernel.h>
> -#include <linux/init.h>
> -#include <linux/slab.h>
> -#include <linux/types.h>
> -#include <linux/delay.h>
> -#include <linux/errno.h>
> -#include <linux/ptrace.h>
> -#include <linux/ioport.h>
> -#include <linux/spinlock.h>
> -#include <linux/moduleparam.h>
> -
> -#include <linux/skbuff.h>
> -#include <linux/string.h>
> -#include <linux/serial.h>
> -#include <linux/serial_reg.h>
> -#include <linux/bitops.h>
> -#include <asm/io.h>
> -
> -#include <linux/device.h>
> -#include <linux/firmware.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>
> -
> -
> -
> -/* ======================== Module parameters ======================== */
> -
> -
> -MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
> -MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
> -MODULE_LICENSE("GPL");
> -MODULE_FIRMWARE("BT3CPCC.bin");
> -
> -
> -
> -/* ======================== Local structures ======================== */
> -
> -
> -struct bt3c_info {
> -	struct pcmcia_device *p_dev;
> -
> -	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;
> -};
> -
> -
> -static int bt3c_config(struct pcmcia_device *link);
> -static void bt3c_release(struct pcmcia_device *link);
> -
> -static void bt3c_detach(struct pcmcia_device *p_dev);
> -
> -
> -/* 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 I/O functions ======================== */
> -
> -
> -#define DATA_L   0
> -#define DATA_H   1
> -#define ADDR_L   2
> -#define ADDR_H   3
> -#define CONTROL  4
> -
> -
> -static inline void bt3c_address(unsigned int iobase, unsigned short addr)
> -{
> -	outb(addr & 0xff, iobase + ADDR_L);
> -	outb((addr >> 8) & 0xff, iobase + ADDR_H);
> -}
> -
> -
> -static inline void bt3c_put(unsigned int iobase, unsigned short value)
> -{
> -	outb(value & 0xff, iobase + DATA_L);
> -	outb((value >> 8) & 0xff, iobase + DATA_H);
> -}
> -
> -
> -static inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value)
> -{
> -	bt3c_address(iobase, addr);
> -	bt3c_put(iobase, value);
> -}
> -
> -
> -static inline unsigned short bt3c_get(unsigned int iobase)
> -{
> -	unsigned short value = inb(iobase + DATA_L);
> -
> -	value |= inb(iobase + DATA_H) << 8;
> -
> -	return value;
> -}
> -
> -
> -static inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr)
> -{
> -	bt3c_address(iobase, addr);
> -
> -	return bt3c_get(iobase);
> -}
> -
> -
> -
> -/* ======================== Interrupt handling ======================== */
> -
> -
> -static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
> -{
> -	int actual = 0;
> -
> -	bt3c_address(iobase, 0x7080);
> -
> -	/* Fill FIFO with current frame */
> -	while (actual < len) {
> -		/* Transmit next byte */
> -		bt3c_put(iobase, buf[actual]);
> -		actual++;
> -	}
> -
> -	bt3c_io_write(iobase, 0x7005, actual);
> -
> -	return actual;
> -}
> -
> -
> -static void bt3c_write_wakeup(struct bt3c_info *info)
> -{
> -	if (!info) {
> -		BT_ERR("Unknown device");
> -		return;
> -	}
> -
> -	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state)))
> -		return;
> -
> -	do {
> -		unsigned int iobase = info->p_dev->resource[0]->start;
> -		register struct sk_buff *skb;
> -		int len;
> -
> -		if (!pcmcia_dev_present(info->p_dev))
> -			break;
> -
> -		skb = skb_dequeue(&(info->txq));
> -		if (!skb) {
> -			clear_bit(XMIT_SENDING, &(info->tx_state));
> -			break;
> -		}
> -
> -		/* Send frame */
> -		len = bt3c_write(iobase, 256, skb->data, skb->len);
> -
> -		if (len != skb->len)
> -			BT_ERR("Very strange");
> -
> -		kfree_skb(skb);
> -
> -		info->hdev->stat.byte_tx += len;
> -
> -	} while (0);
> -}
> -
> -
> -static void bt3c_receive(struct bt3c_info *info)
> -{
> -	unsigned int iobase;
> -	int size = 0, avail;
> -
> -	if (!info) {
> -		BT_ERR("Unknown device");
> -		return;
> -	}
> -
> -	iobase = info->p_dev->resource[0]->start;
> -
> -	avail = bt3c_read(iobase, 0x7006);
> -
> -	bt3c_address(iobase, 0x7480);
> -	while (size < avail) {
> -		size++;
> -		info->hdev->stat.byte_rx++;
> -
> -		/* Allocate packet */
> -		if (!info->rx_skb) {
> -			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) {
> -
> -			hci_skb_pkt_type(info->rx_skb) = inb(iobase + DATA_L);
> -			inb(iobase + DATA_H);
> -
> -			switch (hci_skb_pkt_type(info->rx_skb)) {
> -
> -			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",
> -				       hci_skb_pkt_type(info->rx_skb));
> -				info->hdev->stat.err_rx++;
> -
> -				kfree_skb(info->rx_skb);
> -				info->rx_skb = NULL;
> -				break;
> -
> -			}
> -
> -		} else {
> -
> -			__u8 x = inb(iobase + DATA_L);
> -
> -			skb_put_u8(info->rx_skb, x);
> -			inb(iobase + DATA_H);
> -			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;
> -
> -				}
> -
> -			}
> -
> -		}
> -
> -	}
> -
> -	bt3c_io_write(iobase, 0x7006, 0x0000);
> -}
> -
> -
> -static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
> -{
> -	struct bt3c_info *info = dev_inst;
> -	unsigned int iobase;
> -	int iir;
> -	irqreturn_t r = IRQ_NONE;
> -
> -	if (!info || !info->hdev)
> -		/* our irq handler is shared */
> -		return IRQ_NONE;
> -
> -	iobase = info->p_dev->resource[0]->start;
> -
> -	spin_lock(&(info->lock));
> -
> -	iir = inb(iobase + CONTROL);
> -	if (iir & 0x80) {
> -		int stat = bt3c_read(iobase, 0x7001);
> -
> -		if ((stat & 0xff) == 0x7f) {
> -			BT_ERR("Very strange (stat=0x%04x)", stat);
> -		} else if ((stat & 0xff) != 0xff) {
> -			if (stat & 0x0020) {
> -				int status = bt3c_read(iobase, 0x7002) & 0x10;
> -				bt_dev_info(info->hdev, "Antenna %s",
> -							status ? "out" : "in");
> -			}
> -			if (stat & 0x0001)
> -				bt3c_receive(info);
> -			if (stat & 0x0002) {
> -				clear_bit(XMIT_SENDING, &(info->tx_state));
> -				bt3c_write_wakeup(info);
> -			}
> -
> -			bt3c_io_write(iobase, 0x7001, 0x0000);
> -
> -			outb(iir, iobase + CONTROL);
> -		}
> -		r = IRQ_HANDLED;
> -	}
> -
> -	spin_unlock(&(info->lock));
> -
> -	return r;
> -}
> -
> -
> -
> -/* ======================== HCI interface ======================== */
> -
> -
> -static int bt3c_hci_flush(struct hci_dev *hdev)
> -{
> -	struct bt3c_info *info = hci_get_drvdata(hdev);
> -
> -	/* Drop TX queue */
> -	skb_queue_purge(&(info->txq));
> -
> -	return 0;
> -}
> -
> -
> -static int bt3c_hci_open(struct hci_dev *hdev)
> -{
> -	return 0;
> -}
> -
> -
> -static int bt3c_hci_close(struct hci_dev *hdev)
> -{
> -	bt3c_hci_flush(hdev);
> -
> -	return 0;
> -}
> -
> -
> -static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
> -{
> -	struct bt3c_info *info = hci_get_drvdata(hdev);
> -	unsigned long flags;
> -
> -	switch (hci_skb_pkt_type(skb)) {
> -	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), &hci_skb_pkt_type(skb), 1);
> -	skb_queue_tail(&(info->txq), skb);
> -
> -	spin_lock_irqsave(&(info->lock), flags);
> -
> -	bt3c_write_wakeup(info);
> -
> -	spin_unlock_irqrestore(&(info->lock), flags);
> -
> -	return 0;
> -}
> -
> -
> -
> -/* ======================== Card services HCI interaction ======================== */
> -
> -
> -static int bt3c_load_firmware(struct bt3c_info *info,
> -			      const unsigned char *firmware,
> -			      int count)
> -{
> -	char *ptr = (char *) firmware;
> -	char b[9];
> -	unsigned int iobase, tmp, tn;
> -	unsigned long size, addr, fcs;
> -	int i, err = 0;
> -
> -	iobase = info->p_dev->resource[0]->start;
> -
> -	/* Reset */
> -	bt3c_io_write(iobase, 0x8040, 0x0404);
> -	bt3c_io_write(iobase, 0x8040, 0x0400);
> -
> -	udelay(1);
> -
> -	bt3c_io_write(iobase, 0x8040, 0x0404);
> -
> -	udelay(17);
> -
> -	/* Load */
> -	while (count) {
> -		if (ptr[0] != 'S') {
> -			BT_ERR("Bad address in firmware");
> -			err = -EFAULT;
> -			goto error;
> -		}
> -
> -		memset(b, 0, sizeof(b));
> -		memcpy(b, ptr + 2, 2);
> -		if (kstrtoul(b, 16, &size) < 0)
> -			return -EINVAL;
> -
> -		memset(b, 0, sizeof(b));
> -		memcpy(b, ptr + 4, 8);
> -		if (kstrtoul(b, 16, &addr) < 0)
> -			return -EINVAL;
> -
> -		memset(b, 0, sizeof(b));
> -		memcpy(b, ptr + (size * 2) + 2, 2);
> -		if (kstrtoul(b, 16, &fcs) < 0)
> -			return -EINVAL;
> -
> -		memset(b, 0, sizeof(b));
> -		for (tmp = 0, i = 0; i < size; i++) {
> -			memcpy(b, ptr + (i * 2) + 2, 2);
> -			if (kstrtouint(b, 16, &tn))
> -				return -EINVAL;
> -			tmp += tn;
> -		}
> -
> -		if (((tmp + fcs) & 0xff) != 0xff) {
> -			BT_ERR("Checksum error in firmware");
> -			err = -EILSEQ;
> -			goto error;
> -		}
> -
> -		if (ptr[1] == '3') {
> -			bt3c_address(iobase, addr);
> -
> -			memset(b, 0, sizeof(b));
> -			for (i = 0; i < (size - 4) / 2; i++) {
> -				memcpy(b, ptr + (i * 4) + 12, 4);
> -				if (kstrtouint(b, 16, &tmp))
> -					return -EINVAL;
> -				bt3c_put(iobase, tmp);
> -			}
> -		}
> -
> -		ptr   += (size * 2) + 6;
> -		count -= (size * 2) + 6;
> -	}
> -
> -	udelay(17);
> -
> -	/* Boot */
> -	bt3c_address(iobase, 0x3000);
> -	outb(inb(iobase + CONTROL) | 0x40, iobase + CONTROL);
> -
> -error:
> -	udelay(17);
> -
> -	/* Clear */
> -	bt3c_io_write(iobase, 0x7006, 0x0000);
> -	bt3c_io_write(iobase, 0x7005, 0x0000);
> -	bt3c_io_write(iobase, 0x7001, 0x0000);
> -
> -	return err;
> -}
> -
> -
> -static int bt3c_open(struct bt3c_info *info)
> -{
> -	const struct firmware *firmware;
> -	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;
> -
> -	/* Initialize HCI device */
> -	hdev = hci_alloc_dev();
> -	if (!hdev) {
> -		BT_ERR("Can't allocate HCI device");
> -		return -ENOMEM;
> -	}
> -
> -	info->hdev = hdev;
> -
> -	hdev->bus = HCI_PCCARD;
> -	hci_set_drvdata(hdev, info);
> -	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
> -
> -	hdev->open  = bt3c_hci_open;
> -	hdev->close = bt3c_hci_close;
> -	hdev->flush = bt3c_hci_flush;
> -	hdev->send  = bt3c_hci_send_frame;
> -
> -	/* Load firmware */
> -	err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
> -	if (err < 0) {
> -		BT_ERR("Firmware request failed");
> -		goto error;
> -	}
> -
> -	err = bt3c_load_firmware(info, firmware->data, firmware->size);
> -
> -	release_firmware(firmware);
> -
> -	if (err < 0) {
> -		BT_ERR("Firmware loading failed");
> -		goto error;
> -	}
> -
> -	/* Timeout before it is safe to send the first HCI packet */
> -	msleep(1000);
> -
> -	/* Register HCI device */
> -	err = hci_register_dev(hdev);
> -	if (err < 0) {
> -		BT_ERR("Can't register HCI device");
> -		goto error;
> -	}
> -
> -	return 0;
> -
> -error:
> -	info->hdev = NULL;
> -	hci_free_dev(hdev);
> -	return err;
> -}
> -
> -
> -static int bt3c_close(struct bt3c_info *info)
> -{
> -	struct hci_dev *hdev = info->hdev;
> -
> -	if (!hdev)
> -		return -ENODEV;
> -
> -	bt3c_hci_close(hdev);
> -
> -	hci_unregister_dev(hdev);
> -	hci_free_dev(hdev);
> -
> -	return 0;
> -}
> -
> -static int bt3c_probe(struct pcmcia_device *link)
> -{
> -	struct bt3c_info *info;
> -
> -	/* Create new info device */
> -	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
> -	if (!info)
> -		return -ENOMEM;
> -
> -	info->p_dev = link;
> -	link->priv = info;
> -
> -	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
> -		CONF_AUTO_SET_IO;
> -
> -	return bt3c_config(link);
> -}
> -
> -
> -static void bt3c_detach(struct pcmcia_device *link)
> -{
> -	bt3c_release(link);
> -}
> -
> -static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
> -{
> -	int *try = priv_data;
> -
> -	if (!try)
> -		p_dev->io_lines = 16;
> -
> -	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
> -		return -EINVAL;
> -
> -	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 bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
> -				      void *priv_data)
> -{
> -	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 bt3c_config(struct pcmcia_device *link)
> -{
> -	struct bt3c_info *info = link->priv;
> -	int i;
> -	unsigned long 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, bt3c_check_config, (void *) 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.
> -	 */
> -	if (!pcmcia_loop_config(link, bt3c_check_config_notpicky, NULL))
> -		goto found_port;
> -
> -	BT_ERR("No usable port range found");
> -	goto failed;
> -
> -found_port:
> -	i = pcmcia_request_irq(link, &bt3c_interrupt);
> -	if (i != 0)
> -		goto failed;
> -
> -	i = pcmcia_enable_device(link);
> -	if (i != 0)
> -		goto failed;
> -
> -	if (bt3c_open(info) != 0)
> -		goto failed;
> -
> -	return 0;
> -
> -failed:
> -	bt3c_release(link);
> -	return -ENODEV;
> -}
> -
> -
> -static void bt3c_release(struct pcmcia_device *link)
> -{
> -	struct bt3c_info *info = link->priv;
> -
> -	bt3c_close(info);
> -
> -	pcmcia_disable_device(link);
> -}
> -
> -
> -static const 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,
> -	.name		= "bt3c_cs",
> -	.probe		= bt3c_probe,
> -	.remove		= bt3c_detach,
> -	.id_table	= bt3c_ids,
> -};
> -module_pcmcia_driver(bt3c_driver);
> diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
> deleted file mode 100644
> index 2adfe4fade76..000000000000
> --- a/drivers/bluetooth/dtl1_cs.c
> +++ /dev/null
> @@ -1,614 +0,0 @@
> -/*
> - *
> - *  A driver for Nokia Connectivity Card DTL-1 devices
> - *
> - *  Copyright (C) 2001-2002  Marcel Holtmann <marcel@holtmann.org>
> - *
> - *
> - *  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/module.h>
> -
> -#include <linux/kernel.h>
> -#include <linux/init.h>
> -#include <linux/slab.h>
> -#include <linux/types.h>
> -#include <linux/delay.h>
> -#include <linux/errno.h>
> -#include <linux/ptrace.h>
> -#include <linux/ioport.h>
> -#include <linux/spinlock.h>
> -#include <linux/moduleparam.h>
> -
> -#include <linux/skbuff.h>
> -#include <linux/string.h>
> -#include <linux/serial.h>
> -#include <linux/serial_reg.h>
> -#include <linux/bitops.h>
> -#include <asm/io.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>
> -
> -
> -
> -/* ======================== Module parameters ======================== */
> -
> -
> -MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
> -MODULE_DESCRIPTION("Bluetooth driver for Nokia Connectivity Card DTL-1");
> -MODULE_LICENSE("GPL");
> -
> -
> -
> -/* ======================== Local structures ======================== */
> -
> -
> -struct dtl1_info {
> -	struct pcmcia_device *p_dev;
> -
> -	struct hci_dev *hdev;
> -
> -	spinlock_t lock;		/* For serializing operations */
> -
> -	unsigned long flowmask;		/* HCI flow mask */
> -	int ri_latch;
> -
> -	struct sk_buff_head txq;
> -	unsigned long tx_state;
> -
> -	unsigned long rx_state;
> -	unsigned long rx_count;
> -	struct sk_buff *rx_skb;
> -};
> -
> -
> -static int dtl1_config(struct pcmcia_device *link);
> -
> -
> -/* Transmit states  */
> -#define XMIT_SENDING  1
> -#define XMIT_WAKEUP   2
> -#define XMIT_WAITING  8
> -
> -/* Receiver States */
> -#define RECV_WAIT_NSH   0
> -#define RECV_WAIT_DATA  1
> -
> -
> -struct nsh {
> -	u8 type;
> -	u8 zero;
> -	u16 len;
> -} __packed;	/* Nokia Specific Header */
> -
> -#define NSHL  4				/* Nokia Specific Header Length */
> -
> -
> -
> -/* ======================== Interrupt handling ======================== */
> -
> -
> -static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
> -{
> -	int actual = 0;
> -
> -	/* Tx FIFO should be empty */
> -	if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
> -		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 dtl1_write_wakeup(struct dtl1_info *info)
> -{
> -	if (!info) {
> -		BT_ERR("Unknown device");
> -		return;
> -	}
> -
> -	if (test_bit(XMIT_WAITING, &(info->tx_state))) {
> -		set_bit(XMIT_WAKEUP, &(info->tx_state));
> -		return;
> -	}
> -
> -	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
> -		set_bit(XMIT_WAKEUP, &(info->tx_state));
> -		return;
> -	}
> -
> -	do {
> -		unsigned int iobase = info->p_dev->resource[0]->start;
> -		register struct sk_buff *skb;
> -		int len;
> -
> -		clear_bit(XMIT_WAKEUP, &(info->tx_state));
> -
> -		if (!pcmcia_dev_present(info->p_dev))
> -			return;
> -
> -		skb = skb_dequeue(&(info->txq));
> -		if (!skb)
> -			break;
> -
> -		/* Send frame */
> -		len = dtl1_write(iobase, 32, skb->data, skb->len);
> -
> -		if (len == skb->len) {
> -			set_bit(XMIT_WAITING, &(info->tx_state));
> -			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 void dtl1_control(struct dtl1_info *info, struct sk_buff *skb)
> -{
> -	u8 flowmask = *(u8 *)skb->data;
> -	int i;
> -
> -	printk(KERN_INFO "Bluetooth: Nokia control data =");
> -	for (i = 0; i < skb->len; i++)
> -		printk(" %02x", skb->data[i]);
> -
> -	printk("\n");
> -
> -	/* transition to active state */
> -	if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) {
> -		clear_bit(XMIT_WAITING, &(info->tx_state));
> -		dtl1_write_wakeup(info);
> -	}
> -
> -	info->flowmask = flowmask;
> -
> -	kfree_skb(skb);
> -}
> -
> -
> -static void dtl1_receive(struct dtl1_info *info)
> -{
> -	unsigned int iobase;
> -	struct nsh *nsh;
> -	int boguscount = 0;
> -
> -	if (!info) {
> -		BT_ERR("Unknown device");
> -		return;
> -	}
> -
> -	iobase = info->p_dev->resource[0]->start;
> -
> -	do {
> -		info->hdev->stat.byte_rx++;
> -
> -		/* Allocate packet */
> -		if (info->rx_skb == NULL) {
> -			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");
> -				info->rx_state = RECV_WAIT_NSH;
> -				info->rx_count = NSHL;
> -				return;
> -			}
> -		}
> -
> -		skb_put_u8(info->rx_skb, inb(iobase + UART_RX));
> -		nsh = (struct nsh *)info->rx_skb->data;
> -
> -		info->rx_count--;
> -
> -		if (info->rx_count == 0) {
> -
> -			switch (info->rx_state) {
> -			case RECV_WAIT_NSH:
> -				info->rx_state = RECV_WAIT_DATA;
> -				info->rx_count = nsh->len + (nsh->len & 0x0001);
> -				break;
> -			case RECV_WAIT_DATA:
> -				hci_skb_pkt_type(info->rx_skb) = nsh->type;
> -
> -				/* remove PAD byte if it exists */
> -				if (nsh->len & 0x0001) {
> -					info->rx_skb->tail--;
> -					info->rx_skb->len--;
> -				}
> -
> -				/* remove NSH */
> -				skb_pull(info->rx_skb, NSHL);
> -
> -				switch (hci_skb_pkt_type(info->rx_skb)) {
> -				case 0x80:
> -					/* control data for the Nokia Card */
> -					dtl1_control(info, info->rx_skb);
> -					break;
> -				case 0x82:
> -				case 0x83:
> -				case 0x84:
> -					/* send frame to the HCI layer */
> -					hci_skb_pkt_type(info->rx_skb) &= 0x0f;
> -					hci_recv_frame(info->hdev, info->rx_skb);
> -					break;
> -				default:
> -					/* unknown packet */
> -					BT_ERR("Unknown HCI packet with type 0x%02x received",
> -					       hci_skb_pkt_type(info->rx_skb));
> -					kfree_skb(info->rx_skb);
> -					break;
> -				}
> -
> -				info->rx_state = RECV_WAIT_NSH;
> -				info->rx_count = NSHL;
> -				info->rx_skb = NULL;
> -				break;
> -			}
> -
> -		}
> -
> -		/* Make sure we don't stay here too long */
> -		if (boguscount++ > 32)
> -			break;
> -
> -	} while (inb(iobase + UART_LSR) & UART_LSR_DR);
> -}
> -
> -
> -static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
> -{
> -	struct dtl1_info *info = dev_inst;
> -	unsigned int iobase;
> -	unsigned char msr;
> -	int boguscount = 0;
> -	int iir, lsr;
> -	irqreturn_t r = IRQ_NONE;
> -
> -	if (!info || !info->hdev)
> -		/* our irq handler is shared */
> -		return IRQ_NONE;
> -
> -	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);
> -
> -		switch (iir) {
> -		case UART_IIR_RLSI:
> -			BT_ERR("RLSI");
> -			break;
> -		case UART_IIR_RDI:
> -			/* Receive interrupt */
> -			dtl1_receive(info);
> -			break;
> -		case UART_IIR_THRI:
> -			if (lsr & UART_LSR_THRE) {
> -				/* Transmitter ready for data */
> -				dtl1_write_wakeup(info);
> -			}
> -			break;
> -		default:
> -			BT_ERR("Unhandled IIR=%#x", iir);
> -			break;
> -		}
> -
> -		/* Make sure we don't stay here too long */
> -		if (boguscount++ > 100)
> -			break;
> -
> -		iir = inb(iobase + UART_IIR) & UART_IIR_ID;
> -
> -	}
> -
> -	msr = inb(iobase + UART_MSR);
> -
> -	if (info->ri_latch ^ (msr & UART_MSR_RI)) {
> -		info->ri_latch = msr & UART_MSR_RI;
> -		clear_bit(XMIT_WAITING, &(info->tx_state));
> -		dtl1_write_wakeup(info);
> -		r = IRQ_HANDLED;
> -	}
> -
> -	spin_unlock(&(info->lock));
> -
> -	return r;
> -}
> -
> -
> -
> -/* ======================== HCI interface ======================== */
> -
> -
> -static int dtl1_hci_open(struct hci_dev *hdev)
> -{
> -	return 0;
> -}
> -
> -
> -static int dtl1_hci_flush(struct hci_dev *hdev)
> -{
> -	struct dtl1_info *info = hci_get_drvdata(hdev);
> -
> -	/* Drop TX queue */
> -	skb_queue_purge(&(info->txq));
> -
> -	return 0;
> -}
> -
> -
> -static int dtl1_hci_close(struct hci_dev *hdev)
> -{
> -	dtl1_hci_flush(hdev);
> -
> -	return 0;
> -}
> -
> -
> -static int dtl1_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
> -{
> -	struct dtl1_info *info = hci_get_drvdata(hdev);
> -	struct sk_buff *s;
> -	struct nsh nsh;
> -
> -	switch (hci_skb_pkt_type(skb)) {
> -	case HCI_COMMAND_PKT:
> -		hdev->stat.cmd_tx++;
> -		nsh.type = 0x81;
> -		break;
> -	case HCI_ACLDATA_PKT:
> -		hdev->stat.acl_tx++;
> -		nsh.type = 0x82;
> -		break;
> -	case HCI_SCODATA_PKT:
> -		hdev->stat.sco_tx++;
> -		nsh.type = 0x83;
> -		break;
> -	default:
> -		return -EILSEQ;
> -	}
> -
> -	nsh.zero = 0;
> -	nsh.len = skb->len;
> -
> -	s = bt_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC);
> -	if (!s)
> -		return -ENOMEM;
> -
> -	skb_reserve(s, NSHL);
> -	skb_copy_from_linear_data(skb, skb_put(s, skb->len), skb->len);
> -	if (skb->len & 0x0001)
> -		skb_put_u8(s, 0);	/* PAD */
> -
> -	/* Prepend skb with Nokia frame header and queue */
> -	memcpy(skb_push(s, NSHL), &nsh, NSHL);
> -	skb_queue_tail(&(info->txq), s);
> -
> -	dtl1_write_wakeup(info);
> -
> -	kfree_skb(skb);
> -
> -	return 0;
> -}
> -
> -
> -
> -/* ======================== Card services HCI interaction ======================== */
> -
> -
> -static int dtl1_open(struct dtl1_info *info)
> -{
> -	unsigned long flags;
> -	unsigned int iobase = info->p_dev->resource[0]->start;
> -	struct hci_dev *hdev;
> -
> -	spin_lock_init(&(info->lock));
> -
> -	skb_queue_head_init(&(info->txq));
> -
> -	info->rx_state = RECV_WAIT_NSH;
> -	info->rx_count = NSHL;
> -	info->rx_skb = NULL;
> -
> -	set_bit(XMIT_WAITING, &(info->tx_state));
> -
> -	/* Initialize HCI device */
> -	hdev = hci_alloc_dev();
> -	if (!hdev) {
> -		BT_ERR("Can't allocate HCI device");
> -		return -ENOMEM;
> -	}
> -
> -	info->hdev = hdev;
> -
> -	hdev->bus = HCI_PCCARD;
> -	hci_set_drvdata(hdev, info);
> -	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
> -
> -	hdev->open  = dtl1_hci_open;
> -	hdev->close = dtl1_hci_close;
> -	hdev->flush = dtl1_hci_flush;
> -	hdev->send  = dtl1_hci_send_frame;
> -
> -	spin_lock_irqsave(&(info->lock), flags);
> -
> -	/* Reset UART */
> -	outb(0, iobase + UART_MCR);
> -
> -	/* Turn off interrupts */
> -	outb(0, iobase + UART_IER);
> -
> -	/* Initialize UART */
> -	outb(UART_LCR_WLEN8, iobase + UART_LCR);	/* Reset DLAB */
> -	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
> -
> -	info->ri_latch = inb(info->p_dev->resource[0]->start + UART_MSR)
> -				& UART_MSR_RI;
> -
> -	/* Turn on interrupts */
> -	outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
> -
> -	spin_unlock_irqrestore(&(info->lock), flags);
> -
> -	/* Timeout before it is safe to send the first HCI packet */
> -	msleep(2000);
> -
> -	/* Register HCI device */
> -	if (hci_register_dev(hdev) < 0) {
> -		BT_ERR("Can't register HCI device");
> -		info->hdev = NULL;
> -		hci_free_dev(hdev);
> -		return -ENODEV;
> -	}
> -
> -	return 0;
> -}
> -
> -
> -static int dtl1_close(struct dtl1_info *info)
> -{
> -	unsigned long flags;
> -	unsigned int iobase = info->p_dev->resource[0]->start;
> -	struct hci_dev *hdev = info->hdev;
> -
> -	if (!hdev)
> -		return -ENODEV;
> -
> -	dtl1_hci_close(hdev);
> -
> -	spin_lock_irqsave(&(info->lock), flags);
> -
> -	/* Reset UART */
> -	outb(0, iobase + UART_MCR);
> -
> -	/* Turn off interrupts */
> -	outb(0, iobase + UART_IER);
> -
> -	spin_unlock_irqrestore(&(info->lock), flags);
> -
> -	hci_unregister_dev(hdev);
> -	hci_free_dev(hdev);
> -
> -	return 0;
> -}
> -
> -static int dtl1_probe(struct pcmcia_device *link)
> -{
> -	struct dtl1_info *info;
> -
> -	/* Create new info device */
> -	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
> -	if (!info)
> -		return -ENOMEM;
> -
> -	info->p_dev = link;
> -	link->priv = info;
> -
> -	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
> -
> -	return dtl1_config(link);
> -}
> -
> -
> -static void dtl1_detach(struct pcmcia_device *link)
> -{
> -	struct dtl1_info *info = link->priv;
> -
> -	dtl1_close(info);
> -	pcmcia_disable_device(link);
> -}
> -
> -static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
> -{
> -	if ((p_dev->resource[1]->end) || (p_dev->resource[1]->end < 8))
> -		return -ENODEV;
> -
> -	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 dtl1_config(struct pcmcia_device *link)
> -{
> -	struct dtl1_info *info = link->priv;
> -	int ret;
> -
> -	/* Look for a generic full-sized window */
> -	link->resource[0]->end = 8;
> -	ret = pcmcia_loop_config(link, dtl1_confcheck, NULL);
> -	if (ret)
> -		goto failed;
> -
> -	ret = pcmcia_request_irq(link, dtl1_interrupt);
> -	if (ret)
> -		goto failed;
> -
> -	ret = pcmcia_enable_device(link);
> -	if (ret)
> -		goto failed;
> -
> -	ret = dtl1_open(info);
> -	if (ret)
> -		goto failed;
> -
> -	return 0;
> -
> -failed:
> -	dtl1_detach(link);
> -	return ret;
> -}
> -
> -static const struct pcmcia_device_id dtl1_ids[] = {
> -	PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
> -	PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82),
> -	PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
> -	PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3),
> -	PCMCIA_DEVICE_NULL
> -};
> -MODULE_DEVICE_TABLE(pcmcia, dtl1_ids);
> -
> -static struct pcmcia_driver dtl1_driver = {
> -	.owner		= THIS_MODULE,
> -	.name		= "dtl1_cs",
> -	.probe		= dtl1_probe,
> -	.remove		= dtl1_detach,
> -	.id_table	= dtl1_ids,
> -};
> -module_pcmcia_driver(dtl1_driver);


      parent reply	other threads:[~2026-02-11 20:40 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-11  8:22 [RFC PATCH] bluetooth: remove all PCMCIA drivers Ethan Nelson-Moore
2026-02-11 10:02 ` Dominik Brodowski
2026-02-11 19:17   ` Luiz Augusto von Dentz
2026-02-11 11:04 ` [RFC] " bluez.test.bot
2026-02-11 20:40 ` Christophe Leroy (CS GROUP) [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9085df16-4de4-49d6-9b9b-ba27367619ee@kernel.org \
    --to=chleroy@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=andre.draszik@linaro.org \
    --cc=ardb@kernel.org \
    --cc=casey@schaufler-ca.com \
    --cc=chenhuacai@kernel.org \
    --cc=ebiggers@kernel.org \
    --cc=enelsonmoore@gmail.com \
    --cc=hannes@cmpxchg.org \
    --cc=herbert@gondor.apana.org.au \
    --cc=horms@kernel.org \
    --cc=kernel@xen0n.name \
    --cc=kuba@kernel.org \
    --cc=kuniyu@google.com \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=linux@dominikbrodowski.net \
    --cc=linux@rainbow-software.org \
    --cc=luiz.dentz@gmail.com \
    --cc=maddy@linux.ibm.com \
    --cc=marcel@holtmann.org \
    --cc=martin.petersen@oracle.com \
    --cc=mpe@ellerman.id.au \
    --cc=npiggin@gmail.com \
    --cc=paul@paul-moore.com \
    --cc=tsbogend@alpha.franken.de \
    --cc=tytso@mit.edu \
    --cc=yosry.ahmed@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox