xref: /netbsd/sys/dev/pcmcia/btbc.c (revision 6550d01e)
1 /*	$NetBSD: btbc.c,v 1.15 2010/02/24 22:38:08 dyoung Exp $	*/
2 /*
3  * Copyright (c) 2007 KIYOHARA Takashi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 /*
28  * This driver is support to the AnyCom BlueCard.  written with reference to
29  * Linux driver: (drivers/bluetooth/bluecard_cs.c)
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: btbc.c,v 1.15 2010/02/24 22:38:08 dyoung Exp $");
34 
35 #include <sys/param.h>
36 #include <sys/callout.h>
37 #include <sys/device.h>
38 #include <sys/errno.h>
39 #include <sys/kernel.h>
40 #include <sys/mbuf.h>
41 #include <sys/proc.h>
42 
43 #include <sys/bus.h>
44 #include <sys/intr.h>
45 
46 #include <dev/pcmcia/pcmciareg.h>
47 #include <dev/pcmcia/pcmciavar.h>
48 #include <dev/pcmcia/pcmciadevs.h>
49 
50 #include <netbt/bluetooth.h>
51 #include <netbt/hci.h>
52 
53 #include <dev/pcmcia/bluecardreg.h>
54 
55 
56 /* sc_state */				/* receiving */
57 #define BTBC_RECV_PKT_TYPE	0		/* packet type */
58 #define BTBC_RECV_ACL_HDR	1		/* acl header */
59 #define BTBC_RECV_SCO_HDR	2		/* sco header */
60 #define BTBC_RECV_EVENT_HDR	3		/* event header */
61 #define BTBC_RECV_ACL_DATA	4		/* acl packet data */
62 #define BTBC_RECV_SCO_DATA	5		/* sco packet data */
63 #define BTBC_RECV_EVENT_DATA	6		/* event packet data */
64 
65 /* sc_flags */
66 #define BTBC_XMIT		(1 << 1)	/* transmit active */
67 #define BTBC_ENABLED		(1 << 2)	/* is enabled */
68 
69 /* Default baud rate: 57600, 115200, 230400 or 460800 */
70 #ifndef BTBC_DEFAULT_BAUDRATE
71 #define BTBC_DEFAULT_BAUDRATE	57600
72 #endif
73 
74 struct btbc_softc {
75 	device_t sc_dev;
76 
77 	struct pcmcia_function *sc_pf;		/* our PCMCIA function */
78 	struct pcmcia_io_handle sc_pcioh;	/* PCMCIA i/o space info */
79 	int sc_flags;				/* flags */
80 
81 	struct hci_unit *sc_unit;		/* Bluetooth HCI Unit */
82 	struct bt_stats sc_stats;		/* HCI stats */
83 
84 	/* hardware interrupt */
85 	void *sc_intr;				/* cookie */
86 	int sc_state;				/* receive state */
87 	int sc_want;				/* how much we want */
88 	struct mbuf *sc_rxp;			/* incoming packet */
89 	struct mbuf *sc_txp;			/* outgoing packet */
90 	int sc_txstate;
91 #define TXBUF1_EMPTY	(1 << 0)
92 #define TXBUF2_EMPTY	(1 << 1)
93 #define TXBUF_MASK	(1 << 2)
94 
95 	/* output queues */
96 	MBUFQ_HEAD()	sc_cmdq;
97 	MBUFQ_HEAD()	sc_aclq;
98 	MBUFQ_HEAD()	sc_scoq;
99 
100 	callout_t sc_ledch;			/* callout handler for LED */
101 	uint8_t sc_ctrlreg;			/* value for control register */
102 };
103 
104 static int btbc_match(device_t, cfdata_t, void *);
105 static void btbc_attach(device_t, device_t, void *);
106 static int btbc_detach(device_t, int);
107 static bool btbc_suspend(device_t, const pmf_qual_t *);
108 static bool btbc_resume(device_t, const pmf_qual_t *);
109 
110 static void btbc_activity_led_timeout(void *);
111 static void btbc_enable_activity_led(struct btbc_softc *);
112 static int btbc_read(struct btbc_softc *, uint32_t, uint8_t *, int);
113 static int btbc_write(struct btbc_softc *, uint32_t, uint8_t *, int);
114 static int btbc_set_baudrate(struct btbc_softc *, int);
115 static void btbc_receive(struct btbc_softc *, uint32_t);
116 static void btbc_transmit(struct btbc_softc *);
117 static int btbc_intr(void *);
118 static void btbc_start(struct btbc_softc *);
119 
120 static int btbc_enable(device_t);
121 static void btbc_disable(device_t);
122 static void btbc_output_cmd(device_t, struct mbuf *);
123 static void btbc_output_acl(device_t, struct mbuf *);
124 static void btbc_output_sco(device_t, struct mbuf *);
125 static void btbc_stats(device_t, struct bt_stats *, int);
126 
127 CFATTACH_DECL_NEW(btbc, sizeof(struct btbc_softc),
128     btbc_match, btbc_attach, btbc_detach, NULL);
129 
130 static const struct hci_if btbc_hci = {
131 	.enable = btbc_enable,
132 	.disable = btbc_disable,
133 	.output_cmd = btbc_output_cmd,
134 	.output_acl = btbc_output_acl,
135 	.output_sco = btbc_output_sco,
136 	.get_stats = btbc_stats,
137 	.ipl = IPL_TTY,
138 };
139 
140 /* ARGSUSED */
141 static int
142 btbc_match(device_t parent, cfdata_t match, void *aux)
143 {
144 	struct pcmcia_attach_args *pa = aux;
145 
146 	if (pa->manufacturer == PCMCIA_VENDOR_ANYCOM)
147 		if ((pa->product == PCMCIA_PRODUCT_ANYCOM_LSE041) ||
148 		    (pa->product == PCMCIA_PRODUCT_ANYCOM_LSE039) ||
149 		    (pa->product == PCMCIA_PRODUCT_ANYCOM_LSE139))
150 			return 1;
151 	return 0;
152 }
153 
154 static int
155 btbc_pcmcia_validate_config(struct pcmcia_config_entry *cfe)
156 {
157 
158 	if (cfe->iftype != PCMCIA_IFTYPE_IO ||
159 	    cfe->num_iospace < 1 || cfe->num_iospace > 2)
160 		return EINVAL;
161 	return 0;
162 }
163 
164 /* ARGSUSED */
165 static void
166 btbc_attach(device_t parent, device_t self, void *aux)
167 {
168 	struct btbc_softc *sc = device_private(self);
169 	struct pcmcia_attach_args *pa = aux;
170 	struct pcmcia_config_entry *cfe;
171 	int error;
172 
173 	sc->sc_dev = self;
174 	sc->sc_pf = pa->pf;
175 
176 	MBUFQ_INIT(&sc->sc_cmdq);
177 	MBUFQ_INIT(&sc->sc_aclq);
178 	MBUFQ_INIT(&sc->sc_scoq);
179 
180 	if ((error = pcmcia_function_configure(pa->pf,
181 	    btbc_pcmcia_validate_config)) != 0) {
182 		aprint_error_dev(self, "configure failed, error=%d\n", error);
183 		return;
184 	}
185 
186 	cfe = pa->pf->cfe;
187 	sc->sc_pcioh = cfe->iospace[0].handle;
188 
189 	/* Attach Bluetooth unit */
190 	sc->sc_unit = hci_attach(&btbc_hci, self, 0);
191 	if (sc->sc_unit == NULL)
192 		aprint_error_dev(self, "HCI attach failed\n");
193 
194 	if (!pmf_device_register(self, btbc_suspend, btbc_resume))
195 		aprint_error_dev(self, "couldn't establish power handler\n");
196 
197 	callout_init(&sc->sc_ledch, 0);
198 	callout_setfunc(&sc->sc_ledch, btbc_activity_led_timeout, sc);
199 
200 	return;
201 }
202 
203 /* ARGSUSED */
204 static int
205 btbc_detach(device_t self, int flags)
206 {
207 	struct btbc_softc *sc = device_private(self);
208 	int err = 0;
209 
210 	pmf_device_deregister(self);
211 	btbc_disable(sc->sc_dev);
212 
213 	callout_stop(&sc->sc_ledch);
214 	callout_destroy(&sc->sc_ledch);
215 
216 	if (sc->sc_unit) {
217 		hci_detach(sc->sc_unit);
218 		sc->sc_unit = NULL;
219 	}
220 
221 	pcmcia_function_unconfigure(sc->sc_pf);
222 
223 	return err;
224 }
225 
226 static bool
227 btbc_suspend(device_t self, const pmf_qual_t *qual)
228 {
229 	struct btbc_softc *sc = device_private(self);
230 
231 	if (sc->sc_unit) {
232 		hci_detach(sc->sc_unit);
233 		sc->sc_unit = NULL;
234 	}
235 
236 	return true;
237 }
238 
239 
240 static bool
241 btbc_resume(device_t self, const pmf_qual_t *qual)
242 {
243 	struct btbc_softc *sc = device_private(self);
244 
245 	KASSERT(sc->sc_unit == NULL);
246 
247 	sc->sc_unit = hci_attach(&btbc_hci, sc->sc_dev, 0);
248 	if (sc->sc_unit == NULL)
249 		return false;
250 
251 	return true;
252 }
253 
254 static void
255 btbc_activity_led_timeout(void *arg)
256 {
257 	struct btbc_softc *sc = arg;
258 	uint8_t id;
259 
260 	id = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
261 	    BLUECARD_LEDCONTROL);
262 	if (id & 0x20)
263 		/* Disable activity LED */
264 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
265 		    BLUECARD_LEDCONTROL, 0x08 | 0x20);
266 	else
267 		/* Disable power LED */
268 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
269 		    BLUECARD_LEDCONTROL, 0x00);
270 }
271 
272 static void
273 btbc_enable_activity_led(struct btbc_softc *sc)
274 {
275 	uint8_t id;
276 
277 	id = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
278 	    BLUECARD_LEDCONTROL);
279 	if (id & 0x20) {
280 		/* Enable activity LED */
281 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
282 		    BLUECARD_LEDCONTROL, 0x10 | 0x40);
283 
284 		/* Stop the LED after hz/4 */
285 		callout_schedule(&sc->sc_ledch, hz / 4);
286 	} else {
287 		/* Enable power LED */
288 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
289 		    BLUECARD_LEDCONTROL, 0x08 | 0x20);
290 
291 		/* Stop the LED after HZ/2 */
292 		callout_schedule(&sc->sc_ledch, hz / 2);
293 	}
294 }
295 
296 static int
297 btbc_read(struct btbc_softc *sc, uint32_t offset, uint8_t *buf, int buflen)
298 {
299 	int i, n, len;
300 
301 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
302 	    BLUECARD_COMMAND, BLUECARD_COMMAND_RXWIN1);
303 	len = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, offset);
304 
305 	n = 0;
306 	i = 1;
307 	while (n < len) {
308 		if (i == 16) {
309 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
310 			    BLUECARD_COMMAND, BLUECARD_COMMAND_RXWIN2);
311 			i = 0;
312 		}
313 
314 		buf[n] = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
315 		    offset + i);
316 		i++;
317 		if (++n > buflen)
318 			break;
319 	}
320 	return len;
321 }
322 
323 static int
324 btbc_write(struct btbc_softc *sc, uint32_t offset, uint8_t *buf, int buflen)
325 {
326         int i, actual;
327 
328 	actual = (buflen > 15) ? 15 : buflen;
329 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, offset, actual);
330 	for (i = 0; i < actual; i++)
331 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
332 		    offset + i + 1, buf[i]);
333 	return actual;
334 }
335 
336 /*
337  * send Ericsson baud rate command
338  */
339 static int
340 btbc_set_baudrate(struct btbc_softc *sc, int baud)
341 {
342 	hci_cmd_hdr_t *p;
343 	struct mbuf *m;
344 	const uint16_t opcode = htole16(HCI_CMD_ERICSSON_SET_UART_BAUD_RATE);
345 	uint8_t param;
346 
347 	m = m_gethdr(M_WAIT, MT_DATA);
348 
349 	switch (baud) {
350 	case 460800:
351 		param = 0x00;
352 		break;
353 
354 	case 230400:
355 		param = 0x01;
356 		break;
357 
358         case 115200:
359 		param = 0x02;
360 		break;
361 
362 	case 57600:
363 	default:
364 		param = 0x03;
365 		break;
366 	}
367 
368 	p = mtod(m, hci_cmd_hdr_t *);
369 	p->type = HCI_CMD_PKT;
370 	p->opcode = opcode;
371 	p->length = sizeof(param);
372 	m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
373 	m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, &param);
374 
375 	btbc_output_cmd(sc->sc_dev, m);
376 	return 0;
377 }
378 
379 static void
380 btbc_receive(struct btbc_softc *sc, uint32_t offset)
381 {
382 	struct mbuf *m = sc->sc_rxp;
383 	int count, space = 0, i;
384 	uint8_t buf[31];
385 
386 	btbc_enable_activity_led(sc);
387 
388 	/*
389 	 * If we already started a packet, find the
390 	 * trailing end of it.
391 	 */
392 	if (m) {
393 		while (m->m_next)
394 			m = m->m_next;
395 
396 		space = M_TRAILINGSPACE(m);
397 	}
398 
399 	count = btbc_read(sc, offset, buf, sizeof(buf));
400 	i = 0;
401 
402 	while (i < count) {
403 		if (space == 0) {
404 			if (m == NULL) {
405 				/* new packet */
406 				MGETHDR(m, M_DONTWAIT, MT_DATA);
407 				if (m == NULL) {
408 					aprint_error_dev(sc->sc_dev,
409 					    "out of memory\n");
410 					sc->sc_stats.err_rx++;
411 					return;		/* (lost sync) */
412 				}
413 
414 				sc->sc_rxp = m;
415 				m->m_pkthdr.len = m->m_len = 0;
416 				space = MHLEN;
417 
418 				sc->sc_state = BTBC_RECV_PKT_TYPE;
419 				sc->sc_want = 1;
420 			} else {
421 				/* extend mbuf */
422 				MGET(m->m_next, M_DONTWAIT, MT_DATA);
423 				if (m->m_next == NULL) {
424 					aprint_error_dev(sc->sc_dev,
425 					    "out of memory\n");
426 					sc->sc_stats.err_rx++;
427 					return;		/* (lost sync) */
428 				}
429 
430 				m = m->m_next;
431 				m->m_len = 0;
432 				space = MLEN;
433 
434 				if (sc->sc_want > MINCLSIZE) {
435 					MCLGET(m, M_DONTWAIT);
436 					if (m->m_flags & M_EXT)
437 						space = MCLBYTES;
438 				}
439 			}
440 		}
441 
442 		mtod(m, uint8_t *)[m->m_len++] = buf[i];
443 		space--;
444 		sc->sc_rxp->m_pkthdr.len++;
445 		sc->sc_stats.byte_rx++;
446 
447 		sc->sc_want--;
448 		if (sc->sc_want > 0) {
449 			i++;
450 			continue; /* want more */
451 		}
452 
453 		switch (sc->sc_state) {
454 		case BTBC_RECV_PKT_TYPE:		/* Got packet type */
455 			switch (buf[i]) {
456 			case 0x00:	/* init packet */
457 				m_freem(sc->sc_rxp);
458 				sc->sc_rxp = NULL;
459 				break;
460 
461 			case HCI_ACL_DATA_PKT:
462 				sc->sc_state = BTBC_RECV_ACL_HDR;
463 				sc->sc_want = sizeof(hci_acldata_hdr_t) - 1;
464 				break;
465 
466 			case HCI_SCO_DATA_PKT:
467 				sc->sc_state = BTBC_RECV_SCO_HDR;
468 				sc->sc_want = sizeof(hci_scodata_hdr_t) - 1;
469 				break;
470 
471 			case HCI_EVENT_PKT:
472 				sc->sc_state = BTBC_RECV_EVENT_HDR;
473 				sc->sc_want = sizeof(hci_event_hdr_t) - 1;
474 				break;
475 
476 			default:
477 				aprint_error_dev(sc->sc_dev,
478 				    "Unknown packet type=%#x!\n", buf[i]);
479 				sc->sc_stats.err_rx++;
480 				m_freem(sc->sc_rxp);
481 				sc->sc_rxp = NULL;
482 				return;		/* (lost sync) */
483 			}
484 
485 			break;
486 
487 		/*
488 		 * we assume (correctly of course :) that the packet headers
489 		 * all fit into a single pkthdr mbuf
490 		 */
491 		case BTBC_RECV_ACL_HDR:		/* Got ACL Header */
492 			sc->sc_state = BTBC_RECV_ACL_DATA;
493 			sc->sc_want = mtod(m, hci_acldata_hdr_t *)->length;
494 			sc->sc_want = le16toh(sc->sc_want);
495 			break;
496 
497 		case BTBC_RECV_SCO_HDR:		/* Got SCO Header */
498 			sc->sc_state = BTBC_RECV_SCO_DATA;
499 			sc->sc_want =  mtod(m, hci_scodata_hdr_t *)->length;
500 			break;
501 
502 		case BTBC_RECV_EVENT_HDR:	/* Got Event Header */
503 			sc->sc_state = BTBC_RECV_EVENT_DATA;
504 			sc->sc_want =  mtod(m, hci_event_hdr_t *)->length;
505 			break;
506 
507 		case BTBC_RECV_ACL_DATA:	/* ACL Packet Complete */
508 			if (!hci_input_acl(sc->sc_unit, sc->sc_rxp))
509 				sc->sc_stats.err_rx++;
510 
511 			sc->sc_stats.acl_rx++;
512 			sc->sc_rxp = m = NULL;
513 			space = 0;
514 			break;
515 
516 		case BTBC_RECV_SCO_DATA:	/* SCO Packet Complete */
517 			if (!hci_input_sco(sc->sc_unit, sc->sc_rxp))
518 				sc->sc_stats.err_rx++;
519 
520 			sc->sc_stats.sco_rx++;
521 			sc->sc_rxp = m = NULL;
522 			space = 0;
523 			break;
524 
525 		case BTBC_RECV_EVENT_DATA:	/* Event Packet Complete */
526 			if (!hci_input_event(sc->sc_unit, sc->sc_rxp))
527 				sc->sc_stats.err_rx++;
528 
529 			sc->sc_stats.evt_rx++;
530 			sc->sc_rxp = m = NULL;
531 			space = 0;
532 			break;
533 
534 		default:
535 			panic("%s: invalid state %d!\n",
536 				device_xname(sc->sc_dev), sc->sc_state);
537 		}
538 		i++;
539 	}
540 }
541 
542 /*
543  * write data from current packet to Transmit FIFO.
544  * restart when done.
545  */
546 static void
547 btbc_transmit(struct btbc_softc *sc)
548 {
549 	hci_cmd_hdr_t *p;
550 	struct mbuf *m;
551 	int count, set_baudrate, n, s;
552 	uint32_t offset, command;
553 	uint8_t *rptr;
554 
555 	m = sc->sc_txp;
556 	if (m == NULL) {
557 		sc->sc_flags &= ~BTBC_XMIT;
558 		btbc_start(sc);
559 		return;
560 	}
561 
562 	set_baudrate = 0;
563 	p = mtod(m, hci_cmd_hdr_t *);
564 	if ((void *)m->m_pktdat == (void *)p) {
565 		const uint16_t opcode =
566 		    htole16(HCI_CMD_ERICSSON_SET_UART_BAUD_RATE);
567 
568 		if (p->type == HCI_CMD_PKT &&
569 		    p->opcode == opcode &&
570 		    p->length == 1) {
571 			set_baudrate = 1;
572 			sc->sc_txp = NULL;	/* safe reentrant */
573 		}
574 	}
575 
576 	count = 0;
577 	rptr = mtod(m, uint8_t *);
578 	for(;;) {
579 		if (m->m_len == 0) {
580 			m = m->m_next;
581 			if (m == NULL) {
582 				m = sc->sc_txp;
583 				sc->sc_txp = NULL;
584 
585 				if (M_GETCTX(m, void *) == NULL)
586 					m_freem(m);
587 				else if (!hci_complete_sco(sc->sc_unit, m))
588 					sc->sc_stats.err_tx++;
589 
590 				break;
591 			}
592 
593 			rptr = mtod(m, uint8_t *);
594 			continue;
595 		}
596 
597 		s = splhigh();
598 		if (sc->sc_txstate & TXBUF_MASK) {
599 			if (sc->sc_txstate & TXBUF2_EMPTY) {
600 				offset = BLUECARD_BUF2;
601 				command = BLUECARD_COMMAND_TXBUF2;
602 				sc->sc_txstate &= ~(TXBUF2_EMPTY | TXBUF_MASK);
603 			} else {
604 				splx(s);
605 				break;
606 			}
607 		} else {
608 			if (sc->sc_txstate & TXBUF1_EMPTY) {
609 				offset = BLUECARD_BUF1;
610 				command = BLUECARD_COMMAND_TXBUF1;
611 				sc->sc_txstate &= ~TXBUF1_EMPTY;
612 				sc->sc_txstate |= TXBUF_MASK;
613 			} else {
614 				splx(s);
615 				break;
616 			}
617 		}
618 		splx(s);
619 
620 		if (set_baudrate) {
621 			/* Disable RTS */
622 			sc->sc_ctrlreg |= BLUECARD_CONTROL_RTS;
623 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
624 			    BLUECARD_CONTROL, sc->sc_ctrlreg);
625 		}
626 
627 		/* Activate LED */
628 		btbc_enable_activity_led(sc);
629 
630 		/* Send frame */
631 		n = btbc_write(sc, offset, rptr, m->m_len);
632 		count += n;
633 		rptr += n;
634 		m_adj(m, n);
635 
636 		/* Tell the FPGA to send the data */
637 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
638 		    BLUECARD_COMMAND, command);
639 
640 		if (set_baudrate) {
641 			unsigned char baud_reg;
642 
643 			switch (*(uint8_t *)(p + 1)) {
644 			case 0x00:	/* baud rate 460800 */
645 				baud_reg = BLUECARD_CONTROL_BAUDRATE_460800;
646 				break;
647 			case 0x01:	/* baud rate 230400 */
648 				baud_reg = BLUECARD_CONTROL_BAUDRATE_230400;
649 				break;
650 			case 0x02:	/* baud rate 115200 */
651 				baud_reg = BLUECARD_CONTROL_BAUDRATE_115200;
652 				break;
653 			case 0x03:	/* baud rate 57600 */
654 			default:
655 				baud_reg = BLUECARD_CONTROL_BAUDRATE_57600;
656 				break;
657 			}
658 
659 			/* Wait until the command reaches the baseband */
660 			tsleep(sc, PCATCH, "btbc_wait", hz / 5);
661 
662 			/* Set baud on baseband */
663 			sc->sc_ctrlreg &= ~BLUECARD_CONTROL_BAUDRATE_MASK;
664 			sc->sc_ctrlreg |= baud_reg;
665 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
666 			    BLUECARD_CONTROL, sc->sc_ctrlreg);
667 
668 			/* Enable RTS */
669 			sc->sc_ctrlreg &= ~BLUECARD_CONTROL_RTS;
670 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
671 			    BLUECARD_CONTROL, sc->sc_ctrlreg);
672 
673 			/* Wait before the next HCI packet can be send */
674 			tsleep(sc, PCATCH, "btbc_wait", hz);
675 
676 			m_freem(m);
677 			break;
678 		}
679 	}
680 	sc->sc_stats.byte_tx += count;
681 }
682 
683 static int
684 btbc_intr(void *arg)
685 {
686 	struct btbc_softc *sc = arg;
687 	int handled = 0;
688 	uint8_t isr;
689 
690 	isr = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
691 	    BLUECARD_INTERRUPT);
692 	if (isr != 0x00 && isr != 0xff) {
693 		if (isr & BLUECARD_INTERRUPT_RXBUF1) {
694 			isr &= ~BLUECARD_INTERRUPT_RXBUF1;
695 			handled = 1;
696 			btbc_receive(sc, BLUECARD_BUF1);
697 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
698 			    BLUECARD_INTERRUPT, BLUECARD_INTERRUPT_RXBUF1);
699 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
700 			    BLUECARD_COMMAND, BLUECARD_COMMAND_RXBUF1);
701 		}
702 		if (isr & BLUECARD_INTERRUPT_RXBUF2) {
703 			isr &= ~BLUECARD_INTERRUPT_RXBUF2;
704 			handled = 1;
705 			btbc_receive(sc, BLUECARD_BUF2);
706 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
707 			    BLUECARD_INTERRUPT, BLUECARD_INTERRUPT_RXBUF2);
708 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
709 			    BLUECARD_COMMAND, BLUECARD_COMMAND_RXBUF2);
710 		}
711 		if (isr & BLUECARD_INTERRUPT_TXBUF1) {
712 			isr &= ~BLUECARD_INTERRUPT_TXBUF1;
713 			handled = 1;
714 			sc->sc_txstate |= TXBUF1_EMPTY;
715 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
716 			    BLUECARD_INTERRUPT, BLUECARD_INTERRUPT_TXBUF1);
717 			btbc_transmit(sc);
718 		}
719 		if (isr & BLUECARD_INTERRUPT_TXBUF2) {
720 			isr &= ~BLUECARD_INTERRUPT_TXBUF2;
721 			handled = 1;
722 			sc->sc_txstate |= TXBUF2_EMPTY;
723 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
724 			    BLUECARD_INTERRUPT, BLUECARD_INTERRUPT_TXBUF2);
725 			btbc_transmit(sc);
726 		}
727 
728 		if (isr & 0x40) {	/* card eject ? */
729 			aprint_normal_dev(sc->sc_dev, "card eject?\n");
730 			isr &= ~0x40;
731 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
732 			    BLUECARD_INTERRUPT, 0x40);
733 		}
734 		if (isr != 0x00) {
735 			aprint_error_dev(sc->sc_dev,
736 			    "unknown interrupt: isr=0x%x\n", isr);
737 			bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
738 			    BLUECARD_INTERRUPT, isr);
739 		}
740 	}
741 
742 	return handled;
743 }
744 
745 /*
746  * start sending on btbc
747  *
748  * should be called at spltty() and when BTBC_XMIT is not set
749  */
750 static void
751 btbc_start(struct btbc_softc *sc)
752 {
753 	struct mbuf *m;
754 
755 	KASSERT((sc->sc_flags & BTBC_XMIT) == 0);
756 	KASSERT(sc->sc_txp == NULL);
757 
758 	if (MBUFQ_FIRST(&sc->sc_cmdq)) {
759 		MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
760 		sc->sc_stats.cmd_tx++;
761 		goto start;
762 	}
763 
764 	if (MBUFQ_FIRST(&sc->sc_scoq)) {
765 		MBUFQ_DEQUEUE(&sc->sc_scoq, m);
766 		sc->sc_stats.sco_tx++;
767 		goto start;
768 	}
769 
770 	if (MBUFQ_FIRST(&sc->sc_aclq)) {
771 		MBUFQ_DEQUEUE(&sc->sc_aclq, m);
772 		sc->sc_stats.acl_tx++;
773 		goto start;
774 	}
775 
776 	/* Nothing to send */
777 	return;
778 
779 start:
780 	sc->sc_txp = m;
781 	sc->sc_flags |= BTBC_XMIT;
782 	btbc_transmit(sc);
783 }
784 
785 static int
786 btbc_enable(device_t self)
787 {
788 	struct btbc_softc *sc = device_private(self);
789 	int err, s;
790 	uint8_t id, ctrl;
791 
792 	if (sc->sc_flags & BTBC_ENABLED)
793 		return 0;
794 
795 	s = spltty();
796 
797 	sc->sc_txstate = TXBUF1_EMPTY | TXBUF2_EMPTY;
798 	sc->sc_intr = pcmcia_intr_establish(sc->sc_pf, IPL_TTY, btbc_intr, sc);
799 	if (sc->sc_intr == NULL) {
800 		err = EIO;
801 		goto fail1;
802 	}
803 
804 	err = pcmcia_function_enable(sc->sc_pf);
805 	if (err)
806 		goto fail2;
807 
808 	sc->sc_flags |= BTBC_ENABLED;
809 	sc->sc_flags &= ~BTBC_XMIT;
810 
811 	/* Reset card */
812 	ctrl = BLUECARD_CONTROL_RESET | BLUECARD_CONTROL_CARDRESET;
813 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, BLUECARD_CONTROL,
814 	    ctrl);
815 
816 	/* Turn FPGA off */
817 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
818 	    BLUECARD_CARDRESET, 0x80);
819 
820 	/* Wait some time */
821 	tsleep(sc, PCATCH, "btbc_reset", 1);
822 
823 	/* Turn FPGA on */
824 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
825 	    BLUECARD_CARDRESET, 0x00);
826 
827 	/* Activate card */
828 	ctrl = BLUECARD_CONTROL_ON | BLUECARD_CONTROL_RESPU;
829 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, BLUECARD_CONTROL,
830 	    ctrl);
831 
832 	tsleep(sc, PCATCH, "btbc_enable", 1);
833 	sc->sc_ctrlreg = ctrl;
834 
835 	/* Enable interrupt */
836 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
837 	    BLUECARD_INTERRUPT, 0xff);
838 	sc->sc_ctrlreg |= BLUECARD_CONTROL_INTERRUPT;
839 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, BLUECARD_CONTROL,
840 	    sc->sc_ctrlreg);
841 
842 	id = bus_space_read_1(sc->sc_pcioh.iot,
843 	    sc->sc_pcioh.ioh, BLUECARD_LEDCONTROL);
844 	switch (id & 0x0f) {
845 	case 0x02:
846 		/* Enable LED */
847 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
848 		    BLUECARD_LEDCONTROL, 0x08 | 0x20);
849 		break;
850 
851 	case 0x03:
852 		/* Disable RTS */
853 		ctrl |= BLUECARD_CONTROL_RTS;
854 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
855 		    BLUECARD_CONTROL, ctrl);
856 
857 		/* Set baud rate */
858 		ctrl |= BLUECARD_CONTROL_BAUDRATE_460800;
859 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
860 		    BLUECARD_CONTROL, ctrl);
861 
862 		/* Enable RTS */
863 		ctrl &= ~BLUECARD_CONTROL_RTS;
864 		bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
865 		    BLUECARD_CONTROL, ctrl);
866 		break;
867 	}
868 
869 	/* Start the RX buffers */
870 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
871 	    BLUECARD_COMMAND, BLUECARD_COMMAND_RXBUF1);
872 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
873 	    BLUECARD_COMMAND, BLUECARD_COMMAND_RXBUF2);
874 
875 	/* XXX: Control the point at which RTS is enabled */
876 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
877 	    BLUECARD_RXCONTROL, BLUECARD_RXCONTROL_RTSLEVEL(0x0f) | 1);
878 
879 	/* Timeout before it is safe to send the first HCI packet */
880 	tsleep(sc, PCATCH, "btbc_enable", hz * 2);
881 
882 	btbc_set_baudrate(sc, BTBC_DEFAULT_BAUDRATE);
883 
884 	splx(s);
885 	return 0;
886 
887 fail2:
888 	pcmcia_intr_disestablish(sc->sc_pf, sc->sc_intr);
889 	sc->sc_intr = NULL;
890 fail1:
891 	splx(s);
892 	return err;
893 }
894 
895 static void
896 btbc_disable(device_t self)
897 {
898 	struct btbc_softc *sc = device_private(self);
899 	int s;
900 
901 	if ((sc->sc_flags & BTBC_ENABLED) == 0)
902 		return;
903 
904 	s = spltty();
905 
906 	pcmcia_function_disable(sc->sc_pf);
907 
908 	if (sc->sc_intr) {
909 		pcmcia_intr_disestablish(sc->sc_pf, sc->sc_intr);
910 		sc->sc_intr = NULL;
911 	}
912 
913 	if (sc->sc_rxp) {
914 		m_freem(sc->sc_rxp);
915 		sc->sc_rxp = NULL;
916 	}
917 
918 	if (sc->sc_txp) {
919 		m_freem(sc->sc_txp);
920 		sc->sc_txp = NULL;
921 	}
922 
923 	MBUFQ_DRAIN(&sc->sc_cmdq);
924 	MBUFQ_DRAIN(&sc->sc_aclq);
925 	MBUFQ_DRAIN(&sc->sc_scoq);
926 
927 	sc->sc_flags &= ~BTBC_ENABLED;
928 
929 	/* Disable LED */
930 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
931 	    BLUECARD_LEDCONTROL, 0x00);
932 
933 	/* Reset card */
934 	sc->sc_ctrlreg = BLUECARD_CONTROL_RESET | BLUECARD_CONTROL_CARDRESET;
935 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, BLUECARD_CONTROL,
936 	    sc->sc_ctrlreg);
937 
938 	/* Turn FPGA off */
939 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
940 	    BLUECARD_CARDRESET, 0x80);
941 
942 	splx(s);
943 }
944 
945 static void
946 btbc_output_cmd(device_t self, struct mbuf *m)
947 {
948 	struct btbc_softc *sc = device_private(self);
949 	int s;
950 
951 	KASSERT(sc->sc_flags & BTBC_ENABLED);
952 
953 	M_SETCTX(m, NULL);
954 
955 	s = spltty();
956 	MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
957 	if ((sc->sc_flags & BTBC_XMIT) == 0)
958 		btbc_start(sc);
959 
960 	splx(s);
961 }
962 
963 static void
964 btbc_output_acl(device_t self, struct mbuf *m)
965 {
966 	struct btbc_softc *sc = device_private(self);
967 	int s;
968 
969 	KASSERT(sc->sc_flags & BTBC_ENABLED);
970 
971 	M_SETCTX(m, NULL);
972 
973 	s = spltty();
974 	MBUFQ_ENQUEUE(&sc->sc_aclq, m);
975 	if ((sc->sc_flags & BTBC_XMIT) == 0)
976 		btbc_start(sc);
977 
978 	splx(s);
979 }
980 
981 static void
982 btbc_output_sco(device_t self, struct mbuf *m)
983 {
984 	struct btbc_softc *sc = device_private(self);
985 	int s;
986 
987 	KASSERT(sc->sc_flags & BTBC_ENABLED);
988 
989 	s = spltty();
990 	MBUFQ_ENQUEUE(&sc->sc_scoq, m);
991 	if ((sc->sc_flags & BTBC_XMIT) == 0)
992 		btbc_start(sc);
993 
994 	splx(s);
995 }
996 
997 static void
998 btbc_stats(device_t self, struct bt_stats *dest, int flush)
999 {
1000 	struct btbc_softc *sc = device_private(self);
1001 	int s;
1002 
1003 	s = spltty();
1004 	memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
1005 
1006 	if (flush)
1007 		memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
1008 
1009 	splx(s);
1010 }
1011