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