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