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