xref: /OK3568_Linux_fs/kernel/drivers/bluetooth/bluecard_cs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  *  Bluetooth driver for the Anycom BlueCard (LSE039/LSE041)
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (C) 2001-2002  Marcel Holtmann <marcel@holtmann.org>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *  This program is free software; you can redistribute it and/or modify
9*4882a593Smuzhiyun  *  it under the terms of the GNU General Public License version 2 as
10*4882a593Smuzhiyun  *  published by the Free Software Foundation;
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *  Software distributed under the License is distributed on an "AS
13*4882a593Smuzhiyun  *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14*4882a593Smuzhiyun  *  implied. See the License for the specific language governing
15*4882a593Smuzhiyun  *  rights and limitations under the License.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  *  The initial developer of the original code is David A. Hinds
18*4882a593Smuzhiyun  *  <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
19*4882a593Smuzhiyun  *  are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include <linux/module.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include <linux/kernel.h>
26*4882a593Smuzhiyun #include <linux/init.h>
27*4882a593Smuzhiyun #include <linux/slab.h>
28*4882a593Smuzhiyun #include <linux/types.h>
29*4882a593Smuzhiyun #include <linux/sched.h>
30*4882a593Smuzhiyun #include <linux/delay.h>
31*4882a593Smuzhiyun #include <linux/timer.h>
32*4882a593Smuzhiyun #include <linux/errno.h>
33*4882a593Smuzhiyun #include <linux/ptrace.h>
34*4882a593Smuzhiyun #include <linux/ioport.h>
35*4882a593Smuzhiyun #include <linux/spinlock.h>
36*4882a593Smuzhiyun #include <linux/moduleparam.h>
37*4882a593Smuzhiyun #include <linux/wait.h>
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #include <linux/skbuff.h>
40*4882a593Smuzhiyun #include <linux/io.h>
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #include <pcmcia/cistpl.h>
43*4882a593Smuzhiyun #include <pcmcia/ciscode.h>
44*4882a593Smuzhiyun #include <pcmcia/ds.h>
45*4882a593Smuzhiyun #include <pcmcia/cisreg.h>
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #include <net/bluetooth/bluetooth.h>
48*4882a593Smuzhiyun #include <net/bluetooth/hci_core.h>
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun /* ======================== Module parameters ======================== */
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
56*4882a593Smuzhiyun MODULE_DESCRIPTION("Bluetooth driver for the Anycom BlueCard (LSE039/LSE041)");
57*4882a593Smuzhiyun MODULE_LICENSE("GPL");
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun /* ======================== Local structures ======================== */
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun struct bluecard_info {
65*4882a593Smuzhiyun 	struct pcmcia_device *p_dev;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	struct hci_dev *hdev;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	spinlock_t lock;		/* For serializing operations */
70*4882a593Smuzhiyun 	struct timer_list timer;	/* For LED control */
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	struct sk_buff_head txq;
73*4882a593Smuzhiyun 	unsigned long tx_state;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	unsigned long rx_state;
76*4882a593Smuzhiyun 	unsigned long rx_count;
77*4882a593Smuzhiyun 	struct sk_buff *rx_skb;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	unsigned char ctrl_reg;
80*4882a593Smuzhiyun 	unsigned long hw_state;		/* Status of the hardware and LED control */
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun static int bluecard_config(struct pcmcia_device *link);
85*4882a593Smuzhiyun static void bluecard_release(struct pcmcia_device *link);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun static void bluecard_detach(struct pcmcia_device *p_dev);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /* Default baud rate: 57600, 115200, 230400 or 460800 */
91*4882a593Smuzhiyun #define DEFAULT_BAUD_RATE  230400
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /* Hardware states */
95*4882a593Smuzhiyun #define CARD_READY             1
96*4882a593Smuzhiyun #define CARD_ACTIVITY	       2
97*4882a593Smuzhiyun #define CARD_HAS_PCCARD_ID     4
98*4882a593Smuzhiyun #define CARD_HAS_POWER_LED     5
99*4882a593Smuzhiyun #define CARD_HAS_ACTIVITY_LED  6
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun /* Transmit states  */
102*4882a593Smuzhiyun #define XMIT_SENDING         1
103*4882a593Smuzhiyun #define XMIT_WAKEUP          2
104*4882a593Smuzhiyun #define XMIT_BUFFER_NUMBER   5	/* unset = buffer one, set = buffer two */
105*4882a593Smuzhiyun #define XMIT_BUF_ONE_READY   6
106*4882a593Smuzhiyun #define XMIT_BUF_TWO_READY   7
107*4882a593Smuzhiyun #define XMIT_SENDING_READY   8
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun /* Receiver states */
110*4882a593Smuzhiyun #define RECV_WAIT_PACKET_TYPE   0
111*4882a593Smuzhiyun #define RECV_WAIT_EVENT_HEADER  1
112*4882a593Smuzhiyun #define RECV_WAIT_ACL_HEADER    2
113*4882a593Smuzhiyun #define RECV_WAIT_SCO_HEADER    3
114*4882a593Smuzhiyun #define RECV_WAIT_DATA          4
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun /* Special packet types */
117*4882a593Smuzhiyun #define PKT_BAUD_RATE_57600   0x80
118*4882a593Smuzhiyun #define PKT_BAUD_RATE_115200  0x81
119*4882a593Smuzhiyun #define PKT_BAUD_RATE_230400  0x82
120*4882a593Smuzhiyun #define PKT_BAUD_RATE_460800  0x83
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun /* These are the register offsets */
124*4882a593Smuzhiyun #define REG_COMMAND     0x20
125*4882a593Smuzhiyun #define REG_INTERRUPT   0x21
126*4882a593Smuzhiyun #define REG_CONTROL     0x22
127*4882a593Smuzhiyun #define REG_RX_CONTROL  0x24
128*4882a593Smuzhiyun #define REG_CARD_RESET  0x30
129*4882a593Smuzhiyun #define REG_LED_CTRL    0x30
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun /* REG_COMMAND */
132*4882a593Smuzhiyun #define REG_COMMAND_TX_BUF_ONE  0x01
133*4882a593Smuzhiyun #define REG_COMMAND_TX_BUF_TWO  0x02
134*4882a593Smuzhiyun #define REG_COMMAND_RX_BUF_ONE  0x04
135*4882a593Smuzhiyun #define REG_COMMAND_RX_BUF_TWO  0x08
136*4882a593Smuzhiyun #define REG_COMMAND_RX_WIN_ONE  0x00
137*4882a593Smuzhiyun #define REG_COMMAND_RX_WIN_TWO  0x10
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun /* REG_CONTROL */
140*4882a593Smuzhiyun #define REG_CONTROL_BAUD_RATE_57600   0x00
141*4882a593Smuzhiyun #define REG_CONTROL_BAUD_RATE_115200  0x01
142*4882a593Smuzhiyun #define REG_CONTROL_BAUD_RATE_230400  0x02
143*4882a593Smuzhiyun #define REG_CONTROL_BAUD_RATE_460800  0x03
144*4882a593Smuzhiyun #define REG_CONTROL_RTS               0x04
145*4882a593Smuzhiyun #define REG_CONTROL_BT_ON             0x08
146*4882a593Smuzhiyun #define REG_CONTROL_BT_RESET          0x10
147*4882a593Smuzhiyun #define REG_CONTROL_BT_RES_PU         0x20
148*4882a593Smuzhiyun #define REG_CONTROL_INTERRUPT         0x40
149*4882a593Smuzhiyun #define REG_CONTROL_CARD_RESET        0x80
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun /* REG_RX_CONTROL */
152*4882a593Smuzhiyun #define RTS_LEVEL_SHIFT_BITS  0x02
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /* ======================== LED handling routines ======================== */
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 
bluecard_activity_led_timeout(struct timer_list * t)159*4882a593Smuzhiyun static void bluecard_activity_led_timeout(struct timer_list *t)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	struct bluecard_info *info = from_timer(info, t, timer);
162*4882a593Smuzhiyun 	unsigned int iobase = info->p_dev->resource[0]->start;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	if (test_bit(CARD_ACTIVITY, &(info->hw_state))) {
165*4882a593Smuzhiyun 		/* leave LED in inactive state for HZ/10 for blink effect */
166*4882a593Smuzhiyun 		clear_bit(CARD_ACTIVITY, &(info->hw_state));
167*4882a593Smuzhiyun 		mod_timer(&(info->timer), jiffies + HZ / 10);
168*4882a593Smuzhiyun 	}
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/* Disable activity LED, enable power LED */
171*4882a593Smuzhiyun 	outb(0x08 | 0x20, iobase + 0x30);
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 
bluecard_enable_activity_led(struct bluecard_info * info)175*4882a593Smuzhiyun static void bluecard_enable_activity_led(struct bluecard_info *info)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	unsigned int iobase = info->p_dev->resource[0]->start;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	/* don't disturb running blink timer */
180*4882a593Smuzhiyun 	if (timer_pending(&(info->timer)))
181*4882a593Smuzhiyun 		return;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	set_bit(CARD_ACTIVITY, &(info->hw_state));
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) {
186*4882a593Smuzhiyun 		/* Enable activity LED, keep power LED enabled */
187*4882a593Smuzhiyun 		outb(0x18 | 0x60, iobase + 0x30);
188*4882a593Smuzhiyun 	} else {
189*4882a593Smuzhiyun 		/* Disable power LED */
190*4882a593Smuzhiyun 		outb(0x00, iobase + 0x30);
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	/* Stop the LED after HZ/10 */
194*4882a593Smuzhiyun 	mod_timer(&(info->timer), jiffies + HZ / 10);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun /* ======================== Interrupt handling ======================== */
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 
bluecard_write(unsigned int iobase,unsigned int offset,__u8 * buf,int len)202*4882a593Smuzhiyun static int bluecard_write(unsigned int iobase, unsigned int offset, __u8 *buf, int len)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	int i, actual;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	actual = (len > 15) ? 15 : len;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	outb_p(actual, iobase + offset);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	for (i = 0; i < actual; i++)
211*4882a593Smuzhiyun 		outb_p(buf[i], iobase + offset + i + 1);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	return actual;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 
bluecard_write_wakeup(struct bluecard_info * info)217*4882a593Smuzhiyun static void bluecard_write_wakeup(struct bluecard_info *info)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	if (!info) {
220*4882a593Smuzhiyun 		BT_ERR("Unknown device");
221*4882a593Smuzhiyun 		return;
222*4882a593Smuzhiyun 	}
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	if (!test_bit(XMIT_SENDING_READY, &(info->tx_state)))
225*4882a593Smuzhiyun 		return;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
228*4882a593Smuzhiyun 		set_bit(XMIT_WAKEUP, &(info->tx_state));
229*4882a593Smuzhiyun 		return;
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	do {
233*4882a593Smuzhiyun 		unsigned int iobase = info->p_dev->resource[0]->start;
234*4882a593Smuzhiyun 		unsigned int offset;
235*4882a593Smuzhiyun 		unsigned char command;
236*4882a593Smuzhiyun 		unsigned long ready_bit;
237*4882a593Smuzhiyun 		register struct sk_buff *skb;
238*4882a593Smuzhiyun 		int len;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 		clear_bit(XMIT_WAKEUP, &(info->tx_state));
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 		if (!pcmcia_dev_present(info->p_dev))
243*4882a593Smuzhiyun 			return;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 		if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
246*4882a593Smuzhiyun 			if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state)))
247*4882a593Smuzhiyun 				break;
248*4882a593Smuzhiyun 			offset = 0x10;
249*4882a593Smuzhiyun 			command = REG_COMMAND_TX_BUF_TWO;
250*4882a593Smuzhiyun 			ready_bit = XMIT_BUF_TWO_READY;
251*4882a593Smuzhiyun 		} else {
252*4882a593Smuzhiyun 			if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state)))
253*4882a593Smuzhiyun 				break;
254*4882a593Smuzhiyun 			offset = 0x00;
255*4882a593Smuzhiyun 			command = REG_COMMAND_TX_BUF_ONE;
256*4882a593Smuzhiyun 			ready_bit = XMIT_BUF_ONE_READY;
257*4882a593Smuzhiyun 		}
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 		skb = skb_dequeue(&(info->txq));
260*4882a593Smuzhiyun 		if (!skb)
261*4882a593Smuzhiyun 			break;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 		if (hci_skb_pkt_type(skb) & 0x80) {
264*4882a593Smuzhiyun 			/* Disable RTS */
265*4882a593Smuzhiyun 			info->ctrl_reg |= REG_CONTROL_RTS;
266*4882a593Smuzhiyun 			outb(info->ctrl_reg, iobase + REG_CONTROL);
267*4882a593Smuzhiyun 		}
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 		/* Activate LED */
270*4882a593Smuzhiyun 		bluecard_enable_activity_led(info);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 		/* Send frame */
273*4882a593Smuzhiyun 		len = bluecard_write(iobase, offset, skb->data, skb->len);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 		/* Tell the FPGA to send the data */
276*4882a593Smuzhiyun 		outb_p(command, iobase + REG_COMMAND);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 		/* Mark the buffer as dirty */
279*4882a593Smuzhiyun 		clear_bit(ready_bit, &(info->tx_state));
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 		if (hci_skb_pkt_type(skb) & 0x80) {
282*4882a593Smuzhiyun 			DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
283*4882a593Smuzhiyun 			DEFINE_WAIT(wait);
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 			unsigned char baud_reg;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 			switch (hci_skb_pkt_type(skb)) {
288*4882a593Smuzhiyun 			case PKT_BAUD_RATE_460800:
289*4882a593Smuzhiyun 				baud_reg = REG_CONTROL_BAUD_RATE_460800;
290*4882a593Smuzhiyun 				break;
291*4882a593Smuzhiyun 			case PKT_BAUD_RATE_230400:
292*4882a593Smuzhiyun 				baud_reg = REG_CONTROL_BAUD_RATE_230400;
293*4882a593Smuzhiyun 				break;
294*4882a593Smuzhiyun 			case PKT_BAUD_RATE_115200:
295*4882a593Smuzhiyun 				baud_reg = REG_CONTROL_BAUD_RATE_115200;
296*4882a593Smuzhiyun 				break;
297*4882a593Smuzhiyun 			case PKT_BAUD_RATE_57600:
298*4882a593Smuzhiyun 			default:
299*4882a593Smuzhiyun 				baud_reg = REG_CONTROL_BAUD_RATE_57600;
300*4882a593Smuzhiyun 				break;
301*4882a593Smuzhiyun 			}
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 			/* Wait until the command reaches the baseband */
304*4882a593Smuzhiyun 			mdelay(100);
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 			/* Set baud on baseband */
307*4882a593Smuzhiyun 			info->ctrl_reg &= ~0x03;
308*4882a593Smuzhiyun 			info->ctrl_reg |= baud_reg;
309*4882a593Smuzhiyun 			outb(info->ctrl_reg, iobase + REG_CONTROL);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 			/* Enable RTS */
312*4882a593Smuzhiyun 			info->ctrl_reg &= ~REG_CONTROL_RTS;
313*4882a593Smuzhiyun 			outb(info->ctrl_reg, iobase + REG_CONTROL);
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 			/* Wait before the next HCI packet can be send */
316*4882a593Smuzhiyun 			mdelay(1000);
317*4882a593Smuzhiyun 		}
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 		if (len == skb->len) {
320*4882a593Smuzhiyun 			kfree_skb(skb);
321*4882a593Smuzhiyun 		} else {
322*4882a593Smuzhiyun 			skb_pull(skb, len);
323*4882a593Smuzhiyun 			skb_queue_head(&(info->txq), skb);
324*4882a593Smuzhiyun 		}
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 		info->hdev->stat.byte_tx += len;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 		/* Change buffer */
329*4882a593Smuzhiyun 		change_bit(XMIT_BUFFER_NUMBER, &(info->tx_state));
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	} while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	clear_bit(XMIT_SENDING, &(info->tx_state));
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 
bluecard_read(unsigned int iobase,unsigned int offset,__u8 * buf,int size)337*4882a593Smuzhiyun static int bluecard_read(unsigned int iobase, unsigned int offset, __u8 *buf, int size)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun 	int i, n, len;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	outb(REG_COMMAND_RX_WIN_ONE, iobase + REG_COMMAND);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	len = inb(iobase + offset);
344*4882a593Smuzhiyun 	n = 0;
345*4882a593Smuzhiyun 	i = 1;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	while (n < len) {
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 		if (i == 16) {
350*4882a593Smuzhiyun 			outb(REG_COMMAND_RX_WIN_TWO, iobase + REG_COMMAND);
351*4882a593Smuzhiyun 			i = 0;
352*4882a593Smuzhiyun 		}
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 		buf[n] = inb(iobase + offset + i);
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 		n++;
357*4882a593Smuzhiyun 		i++;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	return len;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 
bluecard_receive(struct bluecard_info * info,unsigned int offset)365*4882a593Smuzhiyun static void bluecard_receive(struct bluecard_info *info,
366*4882a593Smuzhiyun 			     unsigned int offset)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun 	unsigned int iobase;
369*4882a593Smuzhiyun 	unsigned char buf[31];
370*4882a593Smuzhiyun 	int i, len;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	if (!info) {
373*4882a593Smuzhiyun 		BT_ERR("Unknown device");
374*4882a593Smuzhiyun 		return;
375*4882a593Smuzhiyun 	}
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	iobase = info->p_dev->resource[0]->start;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	if (test_bit(XMIT_SENDING_READY, &(info->tx_state)))
380*4882a593Smuzhiyun 		bluecard_enable_activity_led(info);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	len = bluecard_read(iobase, offset, buf, sizeof(buf));
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	for (i = 0; i < len; i++) {
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 		/* Allocate packet */
387*4882a593Smuzhiyun 		if (!info->rx_skb) {
388*4882a593Smuzhiyun 			info->rx_state = RECV_WAIT_PACKET_TYPE;
389*4882a593Smuzhiyun 			info->rx_count = 0;
390*4882a593Smuzhiyun 			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
391*4882a593Smuzhiyun 			if (!info->rx_skb) {
392*4882a593Smuzhiyun 				BT_ERR("Can't allocate mem for new packet");
393*4882a593Smuzhiyun 				return;
394*4882a593Smuzhiyun 			}
395*4882a593Smuzhiyun 		}
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 			hci_skb_pkt_type(info->rx_skb) = buf[i];
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 			switch (hci_skb_pkt_type(info->rx_skb)) {
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 			case 0x00:
404*4882a593Smuzhiyun 				/* init packet */
405*4882a593Smuzhiyun 				if (offset != 0x00) {
406*4882a593Smuzhiyun 					set_bit(XMIT_BUF_ONE_READY, &(info->tx_state));
407*4882a593Smuzhiyun 					set_bit(XMIT_BUF_TWO_READY, &(info->tx_state));
408*4882a593Smuzhiyun 					set_bit(XMIT_SENDING_READY, &(info->tx_state));
409*4882a593Smuzhiyun 					bluecard_write_wakeup(info);
410*4882a593Smuzhiyun 				}
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 				kfree_skb(info->rx_skb);
413*4882a593Smuzhiyun 				info->rx_skb = NULL;
414*4882a593Smuzhiyun 				break;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 			case HCI_EVENT_PKT:
417*4882a593Smuzhiyun 				info->rx_state = RECV_WAIT_EVENT_HEADER;
418*4882a593Smuzhiyun 				info->rx_count = HCI_EVENT_HDR_SIZE;
419*4882a593Smuzhiyun 				break;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 			case HCI_ACLDATA_PKT:
422*4882a593Smuzhiyun 				info->rx_state = RECV_WAIT_ACL_HEADER;
423*4882a593Smuzhiyun 				info->rx_count = HCI_ACL_HDR_SIZE;
424*4882a593Smuzhiyun 				break;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 			case HCI_SCODATA_PKT:
427*4882a593Smuzhiyun 				info->rx_state = RECV_WAIT_SCO_HEADER;
428*4882a593Smuzhiyun 				info->rx_count = HCI_SCO_HDR_SIZE;
429*4882a593Smuzhiyun 				break;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 			default:
432*4882a593Smuzhiyun 				/* unknown packet */
433*4882a593Smuzhiyun 				BT_ERR("Unknown HCI packet with type 0x%02x received",
434*4882a593Smuzhiyun 				       hci_skb_pkt_type(info->rx_skb));
435*4882a593Smuzhiyun 				info->hdev->stat.err_rx++;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 				kfree_skb(info->rx_skb);
438*4882a593Smuzhiyun 				info->rx_skb = NULL;
439*4882a593Smuzhiyun 				break;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 			}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 		} else {
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 			skb_put_u8(info->rx_skb, buf[i]);
446*4882a593Smuzhiyun 			info->rx_count--;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 			if (info->rx_count == 0) {
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 				int dlen;
451*4882a593Smuzhiyun 				struct hci_event_hdr *eh;
452*4882a593Smuzhiyun 				struct hci_acl_hdr *ah;
453*4882a593Smuzhiyun 				struct hci_sco_hdr *sh;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 				switch (info->rx_state) {
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 				case RECV_WAIT_EVENT_HEADER:
458*4882a593Smuzhiyun 					eh = hci_event_hdr(info->rx_skb);
459*4882a593Smuzhiyun 					info->rx_state = RECV_WAIT_DATA;
460*4882a593Smuzhiyun 					info->rx_count = eh->plen;
461*4882a593Smuzhiyun 					break;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 				case RECV_WAIT_ACL_HEADER:
464*4882a593Smuzhiyun 					ah = hci_acl_hdr(info->rx_skb);
465*4882a593Smuzhiyun 					dlen = __le16_to_cpu(ah->dlen);
466*4882a593Smuzhiyun 					info->rx_state = RECV_WAIT_DATA;
467*4882a593Smuzhiyun 					info->rx_count = dlen;
468*4882a593Smuzhiyun 					break;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 				case RECV_WAIT_SCO_HEADER:
471*4882a593Smuzhiyun 					sh = hci_sco_hdr(info->rx_skb);
472*4882a593Smuzhiyun 					info->rx_state = RECV_WAIT_DATA;
473*4882a593Smuzhiyun 					info->rx_count = sh->dlen;
474*4882a593Smuzhiyun 					break;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 				case RECV_WAIT_DATA:
477*4882a593Smuzhiyun 					hci_recv_frame(info->hdev, info->rx_skb);
478*4882a593Smuzhiyun 					info->rx_skb = NULL;
479*4882a593Smuzhiyun 					break;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 				}
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 			}
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 		}
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	}
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	info->hdev->stat.byte_rx += len;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 
bluecard_interrupt(int irq,void * dev_inst)494*4882a593Smuzhiyun static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun 	struct bluecard_info *info = dev_inst;
497*4882a593Smuzhiyun 	unsigned int iobase;
498*4882a593Smuzhiyun 	unsigned char reg;
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	if (!info || !info->hdev)
501*4882a593Smuzhiyun 		/* our irq handler is shared */
502*4882a593Smuzhiyun 		return IRQ_NONE;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	if (!test_bit(CARD_READY, &(info->hw_state)))
505*4882a593Smuzhiyun 		return IRQ_HANDLED;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	iobase = info->p_dev->resource[0]->start;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	spin_lock(&(info->lock));
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	/* Disable interrupt */
512*4882a593Smuzhiyun 	info->ctrl_reg &= ~REG_CONTROL_INTERRUPT;
513*4882a593Smuzhiyun 	outb(info->ctrl_reg, iobase + REG_CONTROL);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	reg = inb(iobase + REG_INTERRUPT);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	if ((reg != 0x00) && (reg != 0xff)) {
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 		if (reg & 0x04) {
520*4882a593Smuzhiyun 			bluecard_receive(info, 0x00);
521*4882a593Smuzhiyun 			outb(0x04, iobase + REG_INTERRUPT);
522*4882a593Smuzhiyun 			outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND);
523*4882a593Smuzhiyun 		}
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 		if (reg & 0x08) {
526*4882a593Smuzhiyun 			bluecard_receive(info, 0x10);
527*4882a593Smuzhiyun 			outb(0x08, iobase + REG_INTERRUPT);
528*4882a593Smuzhiyun 			outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND);
529*4882a593Smuzhiyun 		}
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 		if (reg & 0x01) {
532*4882a593Smuzhiyun 			set_bit(XMIT_BUF_ONE_READY, &(info->tx_state));
533*4882a593Smuzhiyun 			outb(0x01, iobase + REG_INTERRUPT);
534*4882a593Smuzhiyun 			bluecard_write_wakeup(info);
535*4882a593Smuzhiyun 		}
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 		if (reg & 0x02) {
538*4882a593Smuzhiyun 			set_bit(XMIT_BUF_TWO_READY, &(info->tx_state));
539*4882a593Smuzhiyun 			outb(0x02, iobase + REG_INTERRUPT);
540*4882a593Smuzhiyun 			bluecard_write_wakeup(info);
541*4882a593Smuzhiyun 		}
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	}
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	/* Enable interrupt */
546*4882a593Smuzhiyun 	info->ctrl_reg |= REG_CONTROL_INTERRUPT;
547*4882a593Smuzhiyun 	outb(info->ctrl_reg, iobase + REG_CONTROL);
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	spin_unlock(&(info->lock));
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	return IRQ_HANDLED;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun /* ======================== Device specific HCI commands ======================== */
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 
bluecard_hci_set_baud_rate(struct hci_dev * hdev,int baud)559*4882a593Smuzhiyun static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun 	struct bluecard_info *info = hci_get_drvdata(hdev);
562*4882a593Smuzhiyun 	struct sk_buff *skb;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	/* Ericsson baud rate command */
565*4882a593Smuzhiyun 	unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 };
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_KERNEL);
568*4882a593Smuzhiyun 	if (!skb) {
569*4882a593Smuzhiyun 		BT_ERR("Can't allocate mem for new packet");
570*4882a593Smuzhiyun 		return -1;
571*4882a593Smuzhiyun 	}
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	switch (baud) {
574*4882a593Smuzhiyun 	case 460800:
575*4882a593Smuzhiyun 		cmd[4] = 0x00;
576*4882a593Smuzhiyun 		hci_skb_pkt_type(skb) = PKT_BAUD_RATE_460800;
577*4882a593Smuzhiyun 		break;
578*4882a593Smuzhiyun 	case 230400:
579*4882a593Smuzhiyun 		cmd[4] = 0x01;
580*4882a593Smuzhiyun 		hci_skb_pkt_type(skb) = PKT_BAUD_RATE_230400;
581*4882a593Smuzhiyun 		break;
582*4882a593Smuzhiyun 	case 115200:
583*4882a593Smuzhiyun 		cmd[4] = 0x02;
584*4882a593Smuzhiyun 		hci_skb_pkt_type(skb) = PKT_BAUD_RATE_115200;
585*4882a593Smuzhiyun 		break;
586*4882a593Smuzhiyun 	case 57600:
587*4882a593Smuzhiyun 	default:
588*4882a593Smuzhiyun 		cmd[4] = 0x03;
589*4882a593Smuzhiyun 		hci_skb_pkt_type(skb) = PKT_BAUD_RATE_57600;
590*4882a593Smuzhiyun 		break;
591*4882a593Smuzhiyun 	}
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	skb_put_data(skb, cmd, sizeof(cmd));
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	skb_queue_tail(&(info->txq), skb);
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	bluecard_write_wakeup(info);
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	return 0;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun /* ======================== HCI interface ======================== */
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 
bluecard_hci_flush(struct hci_dev * hdev)607*4882a593Smuzhiyun static int bluecard_hci_flush(struct hci_dev *hdev)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun 	struct bluecard_info *info = hci_get_drvdata(hdev);
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	/* Drop TX queue */
612*4882a593Smuzhiyun 	skb_queue_purge(&(info->txq));
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	return 0;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 
bluecard_hci_open(struct hci_dev * hdev)618*4882a593Smuzhiyun static int bluecard_hci_open(struct hci_dev *hdev)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun 	struct bluecard_info *info = hci_get_drvdata(hdev);
621*4882a593Smuzhiyun 	unsigned int iobase = info->p_dev->resource[0]->start;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
624*4882a593Smuzhiyun 		bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	/* Enable power LED */
627*4882a593Smuzhiyun 	outb(0x08 | 0x20, iobase + 0x30);
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	return 0;
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 
bluecard_hci_close(struct hci_dev * hdev)633*4882a593Smuzhiyun static int bluecard_hci_close(struct hci_dev *hdev)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun 	struct bluecard_info *info = hci_get_drvdata(hdev);
636*4882a593Smuzhiyun 	unsigned int iobase = info->p_dev->resource[0]->start;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	bluecard_hci_flush(hdev);
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	/* Stop LED timer */
641*4882a593Smuzhiyun 	del_timer_sync(&(info->timer));
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	/* Disable power LED */
644*4882a593Smuzhiyun 	outb(0x00, iobase + 0x30);
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	return 0;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 
bluecard_hci_send_frame(struct hci_dev * hdev,struct sk_buff * skb)650*4882a593Smuzhiyun static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
651*4882a593Smuzhiyun {
652*4882a593Smuzhiyun 	struct bluecard_info *info = hci_get_drvdata(hdev);
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	switch (hci_skb_pkt_type(skb)) {
655*4882a593Smuzhiyun 	case HCI_COMMAND_PKT:
656*4882a593Smuzhiyun 		hdev->stat.cmd_tx++;
657*4882a593Smuzhiyun 		break;
658*4882a593Smuzhiyun 	case HCI_ACLDATA_PKT:
659*4882a593Smuzhiyun 		hdev->stat.acl_tx++;
660*4882a593Smuzhiyun 		break;
661*4882a593Smuzhiyun 	case HCI_SCODATA_PKT:
662*4882a593Smuzhiyun 		hdev->stat.sco_tx++;
663*4882a593Smuzhiyun 		break;
664*4882a593Smuzhiyun 	}
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	/* Prepend skb with frame type */
667*4882a593Smuzhiyun 	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
668*4882a593Smuzhiyun 	skb_queue_tail(&(info->txq), skb);
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	bluecard_write_wakeup(info);
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	return 0;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun /* ======================== Card services HCI interaction ======================== */
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 
bluecard_open(struct bluecard_info * info)680*4882a593Smuzhiyun static int bluecard_open(struct bluecard_info *info)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun 	unsigned int iobase = info->p_dev->resource[0]->start;
683*4882a593Smuzhiyun 	struct hci_dev *hdev;
684*4882a593Smuzhiyun 	unsigned char id;
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	spin_lock_init(&(info->lock));
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun 	timer_setup(&info->timer, bluecard_activity_led_timeout, 0);
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	skb_queue_head_init(&(info->txq));
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	info->rx_state = RECV_WAIT_PACKET_TYPE;
693*4882a593Smuzhiyun 	info->rx_count = 0;
694*4882a593Smuzhiyun 	info->rx_skb = NULL;
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	/* Initialize HCI device */
697*4882a593Smuzhiyun 	hdev = hci_alloc_dev();
698*4882a593Smuzhiyun 	if (!hdev) {
699*4882a593Smuzhiyun 		BT_ERR("Can't allocate HCI device");
700*4882a593Smuzhiyun 		return -ENOMEM;
701*4882a593Smuzhiyun 	}
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun 	info->hdev = hdev;
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	hdev->bus = HCI_PCCARD;
706*4882a593Smuzhiyun 	hci_set_drvdata(hdev, info);
707*4882a593Smuzhiyun 	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	hdev->open  = bluecard_hci_open;
710*4882a593Smuzhiyun 	hdev->close = bluecard_hci_close;
711*4882a593Smuzhiyun 	hdev->flush = bluecard_hci_flush;
712*4882a593Smuzhiyun 	hdev->send  = bluecard_hci_send_frame;
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	id = inb(iobase + 0x30);
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	if ((id & 0x0f) == 0x02)
717*4882a593Smuzhiyun 		set_bit(CARD_HAS_PCCARD_ID, &(info->hw_state));
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	if (id & 0x10)
720*4882a593Smuzhiyun 		set_bit(CARD_HAS_POWER_LED, &(info->hw_state));
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	if (id & 0x20)
723*4882a593Smuzhiyun 		set_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state));
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	/* Reset card */
726*4882a593Smuzhiyun 	info->ctrl_reg = REG_CONTROL_BT_RESET | REG_CONTROL_CARD_RESET;
727*4882a593Smuzhiyun 	outb(info->ctrl_reg, iobase + REG_CONTROL);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	/* Turn FPGA off */
730*4882a593Smuzhiyun 	outb(0x80, iobase + 0x30);
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	/* Wait some time */
733*4882a593Smuzhiyun 	msleep(10);
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	/* Turn FPGA on */
736*4882a593Smuzhiyun 	outb(0x00, iobase + 0x30);
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	/* Activate card */
739*4882a593Smuzhiyun 	info->ctrl_reg = REG_CONTROL_BT_ON | REG_CONTROL_BT_RES_PU;
740*4882a593Smuzhiyun 	outb(info->ctrl_reg, iobase + REG_CONTROL);
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	/* Enable interrupt */
743*4882a593Smuzhiyun 	outb(0xff, iobase + REG_INTERRUPT);
744*4882a593Smuzhiyun 	info->ctrl_reg |= REG_CONTROL_INTERRUPT;
745*4882a593Smuzhiyun 	outb(info->ctrl_reg, iobase + REG_CONTROL);
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	if ((id & 0x0f) == 0x03) {
748*4882a593Smuzhiyun 		/* Disable RTS */
749*4882a593Smuzhiyun 		info->ctrl_reg |= REG_CONTROL_RTS;
750*4882a593Smuzhiyun 		outb(info->ctrl_reg, iobase + REG_CONTROL);
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 		/* Set baud rate */
753*4882a593Smuzhiyun 		info->ctrl_reg |= 0x03;
754*4882a593Smuzhiyun 		outb(info->ctrl_reg, iobase + REG_CONTROL);
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 		/* Enable RTS */
757*4882a593Smuzhiyun 		info->ctrl_reg &= ~REG_CONTROL_RTS;
758*4882a593Smuzhiyun 		outb(info->ctrl_reg, iobase + REG_CONTROL);
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 		set_bit(XMIT_BUF_ONE_READY, &(info->tx_state));
761*4882a593Smuzhiyun 		set_bit(XMIT_BUF_TWO_READY, &(info->tx_state));
762*4882a593Smuzhiyun 		set_bit(XMIT_SENDING_READY, &(info->tx_state));
763*4882a593Smuzhiyun 	}
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	/* Start the RX buffers */
766*4882a593Smuzhiyun 	outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND);
767*4882a593Smuzhiyun 	outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND);
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	/* Signal that the hardware is ready */
770*4882a593Smuzhiyun 	set_bit(CARD_READY, &(info->hw_state));
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	/* Drop TX queue */
773*4882a593Smuzhiyun 	skb_queue_purge(&(info->txq));
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	/* Control the point at which RTS is enabled */
776*4882a593Smuzhiyun 	outb((0x0f << RTS_LEVEL_SHIFT_BITS) | 1, iobase + REG_RX_CONTROL);
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun 	/* Timeout before it is safe to send the first HCI packet */
779*4882a593Smuzhiyun 	msleep(1250);
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	/* Register HCI device */
782*4882a593Smuzhiyun 	if (hci_register_dev(hdev) < 0) {
783*4882a593Smuzhiyun 		BT_ERR("Can't register HCI device");
784*4882a593Smuzhiyun 		info->hdev = NULL;
785*4882a593Smuzhiyun 		hci_free_dev(hdev);
786*4882a593Smuzhiyun 		return -ENODEV;
787*4882a593Smuzhiyun 	}
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	return 0;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 
bluecard_close(struct bluecard_info * info)793*4882a593Smuzhiyun static int bluecard_close(struct bluecard_info *info)
794*4882a593Smuzhiyun {
795*4882a593Smuzhiyun 	unsigned int iobase = info->p_dev->resource[0]->start;
796*4882a593Smuzhiyun 	struct hci_dev *hdev = info->hdev;
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	if (!hdev)
799*4882a593Smuzhiyun 		return -ENODEV;
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	bluecard_hci_close(hdev);
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	clear_bit(CARD_READY, &(info->hw_state));
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	/* Reset card */
806*4882a593Smuzhiyun 	info->ctrl_reg = REG_CONTROL_BT_RESET | REG_CONTROL_CARD_RESET;
807*4882a593Smuzhiyun 	outb(info->ctrl_reg, iobase + REG_CONTROL);
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 	/* Turn FPGA off */
810*4882a593Smuzhiyun 	outb(0x80, iobase + 0x30);
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	hci_unregister_dev(hdev);
813*4882a593Smuzhiyun 	hci_free_dev(hdev);
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 	return 0;
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun 
bluecard_probe(struct pcmcia_device * link)818*4882a593Smuzhiyun static int bluecard_probe(struct pcmcia_device *link)
819*4882a593Smuzhiyun {
820*4882a593Smuzhiyun 	struct bluecard_info *info;
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 	/* Create new info device */
823*4882a593Smuzhiyun 	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
824*4882a593Smuzhiyun 	if (!info)
825*4882a593Smuzhiyun 		return -ENOMEM;
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	info->p_dev = link;
828*4882a593Smuzhiyun 	link->priv = info;
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	link->config_flags |= CONF_ENABLE_IRQ;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 	return bluecard_config(link);
833*4882a593Smuzhiyun }
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 
bluecard_detach(struct pcmcia_device * link)836*4882a593Smuzhiyun static void bluecard_detach(struct pcmcia_device *link)
837*4882a593Smuzhiyun {
838*4882a593Smuzhiyun 	bluecard_release(link);
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 
bluecard_config(struct pcmcia_device * link)842*4882a593Smuzhiyun static int bluecard_config(struct pcmcia_device *link)
843*4882a593Smuzhiyun {
844*4882a593Smuzhiyun 	struct bluecard_info *info = link->priv;
845*4882a593Smuzhiyun 	int i, n;
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	link->config_index = 0x20;
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
850*4882a593Smuzhiyun 	link->resource[0]->end = 64;
851*4882a593Smuzhiyun 	link->io_lines = 6;
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	for (n = 0; n < 0x400; n += 0x40) {
854*4882a593Smuzhiyun 		link->resource[0]->start = n ^ 0x300;
855*4882a593Smuzhiyun 		i = pcmcia_request_io(link);
856*4882a593Smuzhiyun 		if (i == 0)
857*4882a593Smuzhiyun 			break;
858*4882a593Smuzhiyun 	}
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	if (i != 0)
861*4882a593Smuzhiyun 		goto failed;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	i = pcmcia_request_irq(link, bluecard_interrupt);
864*4882a593Smuzhiyun 	if (i != 0)
865*4882a593Smuzhiyun 		goto failed;
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	i = pcmcia_enable_device(link);
868*4882a593Smuzhiyun 	if (i != 0)
869*4882a593Smuzhiyun 		goto failed;
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 	if (bluecard_open(info) != 0)
872*4882a593Smuzhiyun 		goto failed;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	return 0;
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun failed:
877*4882a593Smuzhiyun 	bluecard_release(link);
878*4882a593Smuzhiyun 	return -ENODEV;
879*4882a593Smuzhiyun }
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 
bluecard_release(struct pcmcia_device * link)882*4882a593Smuzhiyun static void bluecard_release(struct pcmcia_device *link)
883*4882a593Smuzhiyun {
884*4882a593Smuzhiyun 	struct bluecard_info *info = link->priv;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 	bluecard_close(info);
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 	del_timer_sync(&(info->timer));
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	pcmcia_disable_device(link);
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun static const struct pcmcia_device_id bluecard_ids[] = {
894*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e),
895*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c),
896*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("WSS", "LSE039", 0x0a0736ec, 0x24e6dfab),
897*4882a593Smuzhiyun 	PCMCIA_DEVICE_NULL
898*4882a593Smuzhiyun };
899*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pcmcia, bluecard_ids);
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun static struct pcmcia_driver bluecard_driver = {
902*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
903*4882a593Smuzhiyun 	.name		= "bluecard_cs",
904*4882a593Smuzhiyun 	.probe		= bluecard_probe,
905*4882a593Smuzhiyun 	.remove		= bluecard_detach,
906*4882a593Smuzhiyun 	.id_table	= bluecard_ids,
907*4882a593Smuzhiyun };
908*4882a593Smuzhiyun module_pcmcia_driver(bluecard_driver);
909