1 /* $NetBSD: btbc.c,v 1.9 2007/11/11 12:59:03 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.9 2007/11/11 12:59:03 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(device_t); 111 static int btbc_enable(device_t); 112 static void btbc_disable(device_t); 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 = device_private(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_dev(self, "configure failed, error=%d\n", error); 157 return; 158 } 159 160 cfe = pa->pf->cfe; 161 sc->sc_pcioh = cfe->iospace[0].handle; 162 163 /* Attach Bluetooth unit */ 164 sc->sc_unit.hci_dev = self; 165 sc->sc_unit.hci_enable = btbc_enable; 166 sc->sc_unit.hci_disable = btbc_disable; 167 sc->sc_unit.hci_start_cmd = btbc_start; 168 sc->sc_unit.hci_start_acl = btbc_start; 169 sc->sc_unit.hci_start_sco = btbc_start; 170 sc->sc_unit.hci_ipl = makeiplcookie(IPL_TTY); 171 hci_attach(&sc->sc_unit); 172 173 /* establish a power change hook */ 174 sc->sc_powerhook = powerhook_establish(device_xname(sc->sc_dev), 175 btbc_power, sc); 176 177 callout_init(&sc->sc_ledch, 0); 178 callout_setfunc(&sc->sc_ledch, btbc_activity_led_timeout, sc); 179 180 return; 181 } 182 183 /* ARGSUSED */ 184 static int 185 btbc_detach(device_t self, int flags) 186 { 187 struct btbc_softc *sc = device_private(self); 188 int err = 0; 189 190 btbc_disable(sc->sc_dev); 191 192 if (sc->sc_powerhook) { 193 powerhook_disestablish(sc->sc_powerhook); 194 sc->sc_powerhook = NULL; 195 } 196 197 callout_stop(&sc->sc_ledch); 198 callout_destroy(&sc->sc_ledch); 199 200 hci_detach(&sc->sc_unit); 201 202 pcmcia_function_unconfigure(sc->sc_pf); 203 204 return err; 205 } 206 207 static void 208 btbc_power(int why, void *arg) 209 { 210 struct btbc_softc *sc = arg; 211 212 switch(why) { 213 case PWR_SUSPEND: 214 case PWR_STANDBY: 215 if (sc->sc_unit.hci_flags & BTF_RUNNING) { 216 hci_detach(&sc->sc_unit); 217 218 sc->sc_flags |= BTBC_SLEEPING; 219 aprint_verbose_dev(sc->sc_dev, "sleeping\n"); 220 } 221 break; 222 223 case PWR_RESUME: 224 if (sc->sc_flags & BTBC_SLEEPING) { 225 aprint_verbose_dev(sc->sc_dev, "waking up\n"); 226 sc->sc_flags &= ~BTBC_SLEEPING; 227 228 memset(&sc->sc_unit, 0, sizeof(sc->sc_unit)); 229 sc->sc_unit.hci_dev = sc->sc_dev; 230 sc->sc_unit.hci_enable = btbc_enable; 231 sc->sc_unit.hci_disable = btbc_disable; 232 sc->sc_unit.hci_start_cmd = btbc_start; 233 sc->sc_unit.hci_start_acl = btbc_start; 234 sc->sc_unit.hci_start_sco = btbc_start; 235 sc->sc_unit.hci_ipl = makeiplcookie(IPL_TTY); 236 hci_attach(&sc->sc_unit); 237 } 238 break; 239 240 case PWR_SOFTSUSPEND: 241 case PWR_SOFTSTANDBY: 242 case PWR_SOFTRESUME: 243 break; 244 } 245 } 246 247 static void 248 btbc_activity_led_timeout(void *arg) 249 { 250 struct btbc_softc *sc = arg; 251 uint8_t id; 252 253 id = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 254 BLUECARD_LEDCONTROL); 255 if (id & 0x20) 256 /* Disable activity LED */ 257 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 258 BLUECARD_LEDCONTROL, 0x08 | 0x20); 259 else 260 /* Disable power LED */ 261 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 262 BLUECARD_LEDCONTROL, 0x00); 263 } 264 265 static void 266 btbc_enable_activity_led(struct btbc_softc *sc) 267 { 268 uint8_t id; 269 270 id = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 271 BLUECARD_LEDCONTROL); 272 if (id & 0x20) { 273 /* Enable activity LED */ 274 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 275 BLUECARD_LEDCONTROL, 0x10 | 0x40); 276 277 /* Stop the LED after hz/4 */ 278 callout_schedule(&sc->sc_ledch, hz / 4); 279 } else { 280 /* Enable power LED */ 281 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 282 BLUECARD_LEDCONTROL, 0x08 | 0x20); 283 284 /* Stop the LED after HZ/2 */ 285 callout_schedule(&sc->sc_ledch, hz / 2); 286 } 287 } 288 289 static int 290 btbc_read(struct btbc_softc *sc, uint32_t offset, uint8_t *buf, int buflen) 291 { 292 int i, n, len; 293 294 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 295 BLUECARD_COMMAND, BLUECARD_COMMAND_RXWIN1); 296 len = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, offset); 297 298 n = 0; 299 i = 1; 300 while (n < len) { 301 if (i == 16) { 302 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 303 BLUECARD_COMMAND, BLUECARD_COMMAND_RXWIN2); 304 i = 0; 305 } 306 307 buf[n] = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 308 offset + i); 309 i++; 310 if (++n > buflen) 311 break; 312 } 313 return len; 314 } 315 316 static int 317 btbc_write(struct btbc_softc *sc, uint32_t offset, uint8_t *buf, int buflen) 318 { 319 int i, actual; 320 321 actual = (buflen > 15) ? 15 : buflen; 322 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, offset, actual); 323 for (i = 0; i < actual; i++) 324 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 325 offset + i + 1, buf[i]); 326 return actual; 327 } 328 329 /* 330 * send Ericsson baud rate command 331 */ 332 static int 333 btbc_set_baudrate(struct btbc_softc *sc, int baud) 334 { 335 struct hci_unit *unit = &sc->sc_unit; 336 hci_cmd_hdr_t *p; 337 struct mbuf *m; 338 const uint16_t opcode = htole16(HCI_CMD_ERICSSON_SET_UART_BAUD_RATE); 339 uint8_t param; 340 341 m = m_gethdr(M_WAIT, MT_DATA); 342 343 switch (baud) { 344 case 460800: 345 param = 0x00; 346 break; 347 348 case 230400: 349 param = 0x01; 350 break; 351 352 case 115200: 353 param = 0x02; 354 break; 355 356 case 57600: 357 default: 358 param = 0x03; 359 break; 360 } 361 362 p = mtod(m, hci_cmd_hdr_t *); 363 p->type = HCI_CMD_PKT; 364 p->opcode = opcode; 365 p->length = sizeof(param); 366 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t); 367 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, ¶m); 368 369 MBUFQ_ENQUEUE(&unit->hci_cmdq, m); 370 btbc_start(sc->sc_dev); 371 372 return 0; 373 } 374 375 static void 376 btbc_receive(struct btbc_softc *sc, uint32_t offset) 377 { 378 struct mbuf *m = sc->sc_rxp; 379 int count, space = 0, i; 380 uint8_t buf[31]; 381 382 btbc_enable_activity_led(sc); 383 384 /* 385 * If we already started a packet, find the 386 * trailing end of it. 387 */ 388 if (m) { 389 while (m->m_next) 390 m = m->m_next; 391 392 space = M_TRAILINGSPACE(m); 393 } 394 395 count = btbc_read(sc, offset, buf, sizeof(buf)); 396 i = 0; 397 398 while (i < count) { 399 if (space == 0) { 400 if (m == NULL) { 401 /* new packet */ 402 MGETHDR(m, M_DONTWAIT, MT_DATA); 403 if (m == NULL) { 404 aprint_error_dev(sc->sc_dev, 405 "out of memory\n"); 406 ++sc->sc_unit.hci_stats.err_rx; 407 return; /* (lost sync) */ 408 } 409 410 sc->sc_rxp = m; 411 m->m_pkthdr.len = m->m_len = 0; 412 space = MHLEN; 413 414 sc->sc_state = BTBC_RECV_PKT_TYPE; 415 sc->sc_want = 1; 416 } else { 417 /* extend mbuf */ 418 MGET(m->m_next, M_DONTWAIT, MT_DATA); 419 if (m->m_next == NULL) { 420 aprint_error_dev(sc->sc_dev, 421 "out of memory\n"); 422 ++sc->sc_unit.hci_stats.err_rx; 423 return; /* (lost sync) */ 424 } 425 426 m = m->m_next; 427 m->m_len = 0; 428 space = MLEN; 429 430 if (sc->sc_want > MINCLSIZE) { 431 MCLGET(m, M_DONTWAIT); 432 if (m->m_flags & M_EXT) 433 space = MCLBYTES; 434 } 435 } 436 } 437 438 mtod(m, uint8_t *)[m->m_len++] = buf[i]; 439 space--; 440 sc->sc_rxp->m_pkthdr.len++; 441 sc->sc_unit.hci_stats.byte_rx++; 442 443 sc->sc_want--; 444 if (sc->sc_want > 0) { 445 i++; 446 continue; /* want more */ 447 } 448 449 switch (sc->sc_state) { 450 case BTBC_RECV_PKT_TYPE: /* Got packet type */ 451 switch (buf[i]) { 452 case 0x00: /* init packet */ 453 m_freem(sc->sc_rxp); 454 sc->sc_rxp = NULL; 455 break; 456 457 case HCI_ACL_DATA_PKT: 458 sc->sc_state = BTBC_RECV_ACL_HDR; 459 sc->sc_want = sizeof(hci_acldata_hdr_t) - 1; 460 break; 461 462 case HCI_SCO_DATA_PKT: 463 sc->sc_state = BTBC_RECV_SCO_HDR; 464 sc->sc_want = sizeof(hci_scodata_hdr_t) - 1; 465 break; 466 467 case HCI_EVENT_PKT: 468 sc->sc_state = BTBC_RECV_EVENT_HDR; 469 sc->sc_want = sizeof(hci_event_hdr_t) - 1; 470 break; 471 472 default: 473 aprint_error_dev(sc->sc_dev, 474 "Unknown packet type=%#x!\n", buf[i]); 475 ++sc->sc_unit.hci_stats.err_rx; 476 m_freem(sc->sc_rxp); 477 sc->sc_rxp = NULL; 478 return; /* (lost sync) */ 479 } 480 481 break; 482 483 /* 484 * we assume (correctly of course :) that the packet headers 485 * all fit into a single pkthdr mbuf 486 */ 487 case BTBC_RECV_ACL_HDR: /* Got ACL Header */ 488 sc->sc_state = BTBC_RECV_ACL_DATA; 489 sc->sc_want = mtod(m, hci_acldata_hdr_t *)->length; 490 sc->sc_want = le16toh(sc->sc_want); 491 break; 492 493 case BTBC_RECV_SCO_HDR: /* Got SCO Header */ 494 sc->sc_state = BTBC_RECV_SCO_DATA; 495 sc->sc_want = mtod(m, hci_scodata_hdr_t *)->length; 496 break; 497 498 case BTBC_RECV_EVENT_HDR: /* Got Event Header */ 499 sc->sc_state = BTBC_RECV_EVENT_DATA; 500 sc->sc_want = mtod(m, hci_event_hdr_t *)->length; 501 break; 502 503 case BTBC_RECV_ACL_DATA: /* ACL Packet Complete */ 504 hci_input_acl(&sc->sc_unit, sc->sc_rxp); 505 sc->sc_unit.hci_stats.acl_rx++; 506 sc->sc_rxp = m = NULL; 507 space = 0; 508 break; 509 510 case BTBC_RECV_SCO_DATA: /* SCO Packet Complete */ 511 hci_input_sco(&sc->sc_unit, sc->sc_rxp); 512 sc->sc_unit.hci_stats.sco_rx++; 513 sc->sc_rxp = m = NULL; 514 space = 0; 515 break; 516 517 case BTBC_RECV_EVENT_DATA: /* Event Packet Complete */ 518 sc->sc_unit.hci_stats.evt_rx++; 519 hci_input_event(&sc->sc_unit, sc->sc_rxp); 520 sc->sc_rxp = m = NULL; 521 space = 0; 522 break; 523 524 default: 525 panic("%s: invalid state %d!\n", 526 device_xname(sc->sc_dev), sc->sc_state); 527 } 528 i++; 529 } 530 } 531 532 /* 533 * write data from current packet to Transmit FIFO. 534 * restart when done. 535 */ 536 static void 537 btbc_transmit(struct btbc_softc *sc) 538 { 539 hci_cmd_hdr_t *p; 540 struct mbuf *m; 541 int count, set_baudrate, n, s; 542 uint32_t offset, command; 543 uint8_t *rptr; 544 545 m = sc->sc_txp; 546 if (m == NULL) { 547 sc->sc_unit.hci_flags &= ~BTF_XMIT; 548 btbc_start(sc->sc_dev); 549 return; 550 } 551 552 set_baudrate = 0; 553 p = mtod(m, hci_cmd_hdr_t *); 554 if ((void *)m->m_pktdat == (void *)p) { 555 const uint16_t opcode = 556 htole16(HCI_CMD_ERICSSON_SET_UART_BAUD_RATE); 557 558 if (p->type == HCI_CMD_PKT && 559 p->opcode == opcode && 560 p->length == 1) { 561 set_baudrate = 1; 562 sc->sc_txp = NULL; /* safe reentrant */ 563 } 564 } 565 566 count = 0; 567 rptr = mtod(m, uint8_t *); 568 for(;;) { 569 if (m->m_len == 0) { 570 m = m->m_next; 571 if (m == NULL) { 572 m = sc->sc_txp; 573 sc->sc_txp = NULL; 574 575 if (M_GETCTX(m, void *) == NULL) 576 m_freem(m); 577 else 578 hci_complete_sco(&sc->sc_unit, m); 579 580 break; 581 } 582 583 rptr = mtod(m, uint8_t *); 584 continue; 585 } 586 587 s = splhigh(); 588 if (sc->sc_txstate & TXBUF_MASK) { 589 if (sc->sc_txstate & TXBUF2_EMPTY) { 590 offset = BLUECARD_BUF2; 591 command = BLUECARD_COMMAND_TXBUF2; 592 sc->sc_txstate &= ~(TXBUF2_EMPTY | TXBUF_MASK); 593 } else { 594 splx(s); 595 break; 596 } 597 } else { 598 if (sc->sc_txstate & TXBUF1_EMPTY) { 599 offset = BLUECARD_BUF1; 600 command = BLUECARD_COMMAND_TXBUF1; 601 sc->sc_txstate &= ~TXBUF1_EMPTY; 602 sc->sc_txstate |= TXBUF_MASK; 603 } else { 604 splx(s); 605 break; 606 } 607 } 608 splx(s); 609 610 if (set_baudrate) { 611 /* Disable RTS */ 612 sc->sc_ctrlreg |= BLUECARD_CONTROL_RTS; 613 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 614 BLUECARD_CONTROL, sc->sc_ctrlreg); 615 } 616 617 /* Activate LED */ 618 btbc_enable_activity_led(sc); 619 620 /* Send frame */ 621 n = btbc_write(sc, offset, rptr, m->m_len); 622 count += n; 623 rptr += n; 624 m_adj(m, n); 625 626 /* Tell the FPGA to send the data */ 627 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 628 BLUECARD_COMMAND, command); 629 630 if (set_baudrate) { 631 unsigned char baud_reg; 632 633 switch (*(uint8_t *)(p + 1)) { 634 case 0x00: /* baud rate 460800 */ 635 baud_reg = BLUECARD_CONTROL_BAUDRATE_460800; 636 break; 637 case 0x01: /* baud rate 230400 */ 638 baud_reg = BLUECARD_CONTROL_BAUDRATE_230400; 639 break; 640 case 0x02: /* baud rate 115200 */ 641 baud_reg = BLUECARD_CONTROL_BAUDRATE_115200; 642 break; 643 case 0x03: /* baud rate 57600 */ 644 default: 645 baud_reg = BLUECARD_CONTROL_BAUDRATE_57600; 646 break; 647 } 648 649 /* Wait until the command reaches the baseband */ 650 tsleep(sc, PCATCH, "btbc_wait", hz / 5); 651 652 /* Set baud on baseband */ 653 sc->sc_ctrlreg &= ~BLUECARD_CONTROL_BAUDRATE_MASK; 654 sc->sc_ctrlreg |= baud_reg; 655 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 656 BLUECARD_CONTROL, sc->sc_ctrlreg); 657 658 /* Enable RTS */ 659 sc->sc_ctrlreg &= ~BLUECARD_CONTROL_RTS; 660 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 661 BLUECARD_CONTROL, sc->sc_ctrlreg); 662 663 /* Wait before the next HCI packet can be send */ 664 tsleep(sc, PCATCH, "btbc_wait", hz); 665 666 m_freem(m); 667 break; 668 } 669 } 670 sc->sc_unit.hci_stats.byte_tx += count; 671 } 672 673 static int 674 btbc_intr(void *arg) 675 { 676 struct btbc_softc *sc = arg; 677 int handled = 0; 678 uint8_t isr; 679 680 isr = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 681 BLUECARD_INTERRUPT); 682 if (isr != 0x00 && isr != 0xff) { 683 if (isr & BLUECARD_INTERRUPT_RXBUF1) { 684 isr &= ~BLUECARD_INTERRUPT_RXBUF1; 685 handled = 1; 686 btbc_receive(sc, BLUECARD_BUF1); 687 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 688 BLUECARD_INTERRUPT, BLUECARD_INTERRUPT_RXBUF1); 689 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 690 BLUECARD_COMMAND, BLUECARD_COMMAND_RXBUF1); 691 } 692 if (isr & BLUECARD_INTERRUPT_RXBUF2) { 693 isr &= ~BLUECARD_INTERRUPT_RXBUF2; 694 handled = 1; 695 btbc_receive(sc, BLUECARD_BUF2); 696 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 697 BLUECARD_INTERRUPT, BLUECARD_INTERRUPT_RXBUF2); 698 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 699 BLUECARD_COMMAND, BLUECARD_COMMAND_RXBUF2); 700 } 701 if (isr & BLUECARD_INTERRUPT_TXBUF1) { 702 isr &= ~BLUECARD_INTERRUPT_TXBUF1; 703 handled = 1; 704 sc->sc_txstate |= TXBUF1_EMPTY; 705 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 706 BLUECARD_INTERRUPT, BLUECARD_INTERRUPT_TXBUF1); 707 btbc_transmit(sc); 708 } 709 if (isr & BLUECARD_INTERRUPT_TXBUF2) { 710 isr &= ~BLUECARD_INTERRUPT_TXBUF2; 711 handled = 1; 712 sc->sc_txstate |= TXBUF2_EMPTY; 713 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 714 BLUECARD_INTERRUPT, BLUECARD_INTERRUPT_TXBUF2); 715 btbc_transmit(sc); 716 } 717 718 if (isr & 0x40) { /* card eject ? */ 719 aprint_normal_dev(sc->sc_dev, "card eject?\n"); 720 isr &= ~0x40; 721 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 722 BLUECARD_INTERRUPT, 0x40); 723 } 724 if (isr != 0x00) { 725 aprint_error_dev(sc->sc_dev, 726 "unknown interrupt: isr=0x%x\n", isr); 727 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 728 BLUECARD_INTERRUPT, isr); 729 } 730 } 731 732 return handled; 733 } 734 735 /* 736 * start sending on btbc 737 * this should be called only when BTF_XMIT is not set, and 738 * we only send cmd packets that are clear to send 739 */ 740 static void 741 btbc_start(device_t self) 742 { 743 struct btbc_softc *sc = device_private(self); 744 struct hci_unit *unit = &sc->sc_unit; 745 struct mbuf *m; 746 747 KASSERT((unit->hci_flags & BTF_XMIT) == 0); 748 KASSERT(sc->sc_txp == NULL); 749 750 if (MBUFQ_FIRST(&unit->hci_cmdq)) { 751 MBUFQ_DEQUEUE(&unit->hci_cmdq, m); 752 unit->hci_stats.cmd_tx++; 753 M_SETCTX(m, NULL); 754 goto start; 755 } 756 757 if (MBUFQ_FIRST(&unit->hci_scotxq)) { 758 MBUFQ_DEQUEUE(&unit->hci_scotxq, m); 759 unit->hci_stats.sco_tx++; 760 goto start; 761 } 762 763 if (MBUFQ_FIRST(&unit->hci_acltxq)) { 764 MBUFQ_DEQUEUE(&unit->hci_acltxq, m); 765 unit->hci_stats.acl_tx++; 766 M_SETCTX(m, NULL); 767 goto start; 768 } 769 770 /* Nothing to send */ 771 return; 772 773 start: 774 sc->sc_txp = m; 775 unit->hci_flags |= BTF_XMIT; 776 btbc_transmit(sc); 777 } 778 779 static int 780 btbc_enable(device_t self) 781 { 782 struct btbc_softc *sc = device_private(self); 783 struct hci_unit *unit = &sc->sc_unit; 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(device_t self) 888 { 889 struct btbc_softc *sc = device_private(self); 890 struct hci_unit *unit = &sc->sc_unit; 891 892 if ((unit->hci_flags & BTF_RUNNING) == 0) 893 return; 894 895 pcmcia_function_disable(sc->sc_pf); 896 897 if (sc->sc_intr) { 898 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_intr); 899 sc->sc_intr = NULL; 900 } 901 902 if (sc->sc_rxp) { 903 m_freem(sc->sc_rxp); 904 sc->sc_rxp = NULL; 905 } 906 907 if (sc->sc_txp) { 908 m_freem(sc->sc_txp); 909 sc->sc_txp = NULL; 910 } 911 912 unit->hci_flags &= ~BTF_RUNNING; 913 914 /* Disable LED */ 915 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 916 BLUECARD_LEDCONTROL, 0x00); 917 918 /* Reset card */ 919 sc->sc_ctrlreg = BLUECARD_CONTROL_RESET | BLUECARD_CONTROL_CARDRESET; 920 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, BLUECARD_CONTROL, 921 sc->sc_ctrlreg); 922 923 /* Turn FPGA off */ 924 bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh, 925 BLUECARD_CARDRESET, 0x80); 926 } 927