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, ¶m); 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