1 /* $NetBSD: sbt.c,v 1.8 2019/11/10 21:16:37 chs Exp $ */ 2 /* $OpenBSD: sbt.c,v 1.9 2007/06/19 07:59:57 uwe Exp $ */ 3 4 /* 5 * Copyright (c) 2007 Uwe Stuehler <uwe@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Driver for Type-A/B SDIO Bluetooth cards */ 21 22 #include <sys/cdefs.h> 23 __KERNEL_RCSID(0, "$NetBSD: sbt.c,v 1.8 2019/11/10 21:16:37 chs Exp $"); 24 25 #include <sys/param.h> 26 #include <sys/device.h> 27 #include <sys/malloc.h> 28 #include <sys/mbuf.h> 29 #include <sys/proc.h> 30 #include <sys/queue.h> 31 #include <sys/socket.h> 32 #include <sys/systm.h> 33 34 #include <netbt/hci.h> 35 36 #include <dev/sdmmc/sdmmcdevs.h> 37 #include <dev/sdmmc/sdmmcvar.h> 38 39 #define CSR_READ_1(sc, reg) sdmmc_io_read_1((sc)->sc_sf, (reg)) 40 #define CSR_WRITE_1(sc, reg, val) sdmmc_io_write_1((sc)->sc_sf, (reg), (val)) 41 42 #define SBT_REG_DAT 0x00 /* receiver/transmitter data */ 43 #define SBT_REG_RPC 0x10 /* read packet control */ 44 #define RPC_PCRRT (1<<0) /* packet read retry */ 45 #define SBT_REG_WPC 0x11 /* write packet control */ 46 #define WPC_PCWRT (1<<0) /* packet write retry */ 47 #define SBT_REG_RC 0x12 /* retry control status/set */ 48 #define SBT_REG_ISTAT 0x13 /* interrupt status */ 49 #define ISTAT_INTRD (1<<0) /* packet available for read */ 50 #define SBT_REG_ICLR 0x13 /* interrupt clear */ 51 #define SBT_REG_IENA 0x14 /* interrupt enable */ 52 #define SBT_REG_BTMODE 0x20 /* SDIO Bluetooth card mode */ 53 #define BTMODE_TYPEB (1<<0) /* 1=Type-B, 0=Type-A */ 54 55 #define SBT_PKT_BUFSIZ 65540 56 #define SBT_RXTRY_MAX 5 57 58 struct sbt_softc { 59 device_t sc_dev; /* base device */ 60 int sc_flags; 61 struct hci_unit *sc_unit; /* Bluetooth HCI Unit */ 62 struct bt_stats sc_stats; 63 struct sdmmc_function *sc_sf; /* SDIO function */ 64 int sc_dying; /* shutdown in progress */ 65 void *sc_ih; 66 u_char *sc_buf; 67 int sc_rxtry; 68 69 /* transmit queues */ 70 MBUFQ_HEAD() sc_cmdq; 71 MBUFQ_HEAD() sc_aclq; 72 MBUFQ_HEAD() sc_scoq; 73 }; 74 75 /* sc_flags */ 76 #define SBT_XMIT (1 << 0) /* transmit is active */ 77 #define SBT_ENABLED (1 << 1) /* device is enabled */ 78 79 static int sbt_match(device_t, cfdata_t, void *); 80 static void sbt_attach(device_t, device_t, void *); 81 static int sbt_detach(device_t, int); 82 83 CFATTACH_DECL_NEW(sbt, sizeof(struct sbt_softc), 84 sbt_match, sbt_attach, sbt_detach, NULL); 85 86 static int sbt_write_packet(struct sbt_softc *, u_char *, size_t); 87 static int sbt_read_packet(struct sbt_softc *, u_char *, size_t *); 88 static void sbt_start(struct sbt_softc *); 89 90 static int sbt_intr(void *); 91 92 static int sbt_enable(device_t); 93 static void sbt_disable(device_t); 94 static void sbt_start_cmd(device_t, struct mbuf *); 95 static void sbt_start_acl(device_t, struct mbuf *); 96 static void sbt_start_sco(device_t, struct mbuf *); 97 static void sbt_stats(device_t, struct bt_stats *, int); 98 99 #undef DPRINTF /* avoid redefine by bluetooth.h */ 100 #ifdef SBT_DEBUG 101 int sbt_debug = 1; 102 #define DPRINTF(s) printf s 103 #define DNPRINTF(n, s) do { if ((n) <= sbt_debug) printf s; } while (0) 104 #else 105 #define DPRINTF(s) do {} while (0) 106 #define DNPRINTF(n, s) do {} while (0) 107 #endif 108 109 #define DEVNAME(sc) device_xname((sc)->sc_dev) 110 111 112 /* 113 * Autoconf glue 114 */ 115 116 static const struct sbt_product { 117 uint16_t sp_vendor; 118 uint16_t sp_product; 119 const char *sp_cisinfo[4]; 120 } sbt_products[] = { 121 { 122 SDMMC_VENDOR_SOCKETCOM, 123 SDMMC_PRODUCT_SOCKETCOM_BTCARD, 124 SDMMC_CIS_SOCKETCOM_BTCARD 125 }, 126 }; 127 128 static const struct hci_if sbt_hci = { 129 .enable = sbt_enable, 130 .disable = sbt_disable, 131 .output_cmd = sbt_start_cmd, 132 .output_acl = sbt_start_acl, 133 .output_sco = sbt_start_sco, 134 .get_stats = sbt_stats, 135 .ipl = IPL_TTY, /* XXX */ 136 }; 137 138 139 static int 140 sbt_match(device_t parent, cfdata_t match, void *aux) 141 { 142 struct sdmmc_attach_args *sa = aux; 143 const struct sbt_product *sp; 144 struct sdmmc_function *sf; 145 int i; 146 147 if (sa->sf == NULL) 148 return 0; /* not SDIO */ 149 150 sf = sa->sf->sc->sc_fn0; 151 sp = &sbt_products[0]; 152 153 for (i = 0; i < sizeof(sbt_products) / sizeof(sbt_products[0]); 154 i++, sp = &sbt_products[i]) 155 if (sp->sp_vendor == sf->cis.manufacturer && 156 sp->sp_product == sf->cis.product) 157 return 1; 158 return 0; 159 } 160 161 static void 162 sbt_attach(device_t parent, device_t self, void *aux) 163 { 164 struct sbt_softc *sc = device_private(self); 165 struct sdmmc_attach_args *sa = aux; 166 167 aprint_normal("\n"); 168 aprint_naive("\n"); 169 170 sc->sc_dev = self; 171 sc->sc_sf = sa->sf; 172 MBUFQ_INIT(&sc->sc_cmdq); 173 MBUFQ_INIT(&sc->sc_aclq); 174 MBUFQ_INIT(&sc->sc_scoq); 175 176 (void)sdmmc_io_function_disable(sc->sc_sf); 177 if (sdmmc_io_function_enable(sc->sc_sf)) { 178 aprint_error("%s: function not ready\n", DEVNAME(sc)); 179 return; 180 } 181 182 /* It may be Type-B, but we use it only in Type-A mode. */ 183 printf("%s: SDIO Bluetooth Type-A\n", DEVNAME(sc)); 184 185 sc->sc_buf = malloc(SBT_PKT_BUFSIZ, M_DEVBUF, M_WAITOK); 186 187 /* Enable the HCI packet transport read interrupt. */ 188 CSR_WRITE_1(sc, SBT_REG_IENA, ISTAT_INTRD); 189 190 /* Enable the card interrupt for this function. */ 191 sc->sc_ih = sdmmc_intr_establish(parent, sbt_intr, sc, DEVNAME(sc)); 192 if (sc->sc_ih == NULL) { 193 aprint_error("%s: can't establish interrupt\n", DEVNAME(sc)); 194 return; 195 } 196 sdmmc_intr_enable(sc->sc_sf); 197 198 /* 199 * Attach Bluetooth unit (machine-independent HCI). 200 */ 201 sc->sc_unit = hci_attach_pcb(&sbt_hci, self, 0); 202 } 203 204 static int 205 sbt_detach(device_t self, int flags) 206 { 207 struct sbt_softc *sc = device_private(self); 208 209 sc->sc_dying = 1; 210 211 if (sc->sc_unit) { 212 hci_detach_pcb(sc->sc_unit); 213 sc->sc_unit = NULL; 214 } 215 216 if (sc->sc_ih != NULL) 217 sdmmc_intr_disestablish(sc->sc_ih); 218 219 return 0; 220 } 221 222 223 /* 224 * Bluetooth HCI packet transport 225 */ 226 227 static int 228 sbt_write_packet(struct sbt_softc *sc, u_char *buf, size_t len) 229 { 230 u_char hdr[3]; 231 size_t pktlen; 232 int error = EIO; 233 int retry = 3; 234 235 again: 236 if (retry-- == 0) { 237 DPRINTF(("%s: sbt_write_cmd: giving up\n", DEVNAME(sc))); 238 return error; 239 } 240 241 /* Restart the current packet. */ 242 sdmmc_io_write_1(sc->sc_sf, SBT_REG_WPC, WPC_PCWRT); 243 244 /* Write the packet length. */ 245 pktlen = len + 3; 246 hdr[0] = pktlen & 0xff; 247 hdr[1] = (pktlen >> 8) & 0xff; 248 hdr[2] = (pktlen >> 16) & 0xff; 249 error = sdmmc_io_write_multi_1(sc->sc_sf, SBT_REG_DAT, hdr, 3); 250 if (error) { 251 DPRINTF(("%s: sbt_write_packet: failed to send length\n", 252 DEVNAME(sc))); 253 goto again; 254 } 255 256 error = sdmmc_io_write_multi_1(sc->sc_sf, SBT_REG_DAT, buf, len); 257 if (error) { 258 DPRINTF(("%s: sbt_write_packet: failed to send packet data\n", 259 DEVNAME(sc))); 260 goto again; 261 } 262 return 0; 263 } 264 265 static int 266 sbt_read_packet(struct sbt_softc *sc, u_char *buf, size_t *lenp) 267 { 268 u_char hdr[3]; 269 size_t len; 270 int error; 271 272 error = sdmmc_io_read_multi_1(sc->sc_sf, SBT_REG_DAT, hdr, 3); 273 if (error) { 274 DPRINTF(("%s: sbt_read_packet: failed to read length\n", 275 DEVNAME(sc))); 276 goto out; 277 } 278 len = (hdr[0] | (hdr[1] << 8) | (hdr[2] << 16)) - 3; 279 if (len > *lenp) { 280 DPRINTF(("%s: sbt_read_packet: len %u > %u\n", 281 DEVNAME(sc), len, *lenp)); 282 error = ENOBUFS; 283 goto out; 284 } 285 286 DNPRINTF(2,("%s: sbt_read_packet: reading len %u bytes\n", 287 DEVNAME(sc), len)); 288 error = sdmmc_io_read_multi_1(sc->sc_sf, SBT_REG_DAT, buf, len); 289 if (error) { 290 DPRINTF(("%s: sbt_read_packet: failed to read packet data\n", 291 DEVNAME(sc))); 292 goto out; 293 } 294 295 out: 296 if (error) { 297 if (sc->sc_rxtry >= SBT_RXTRY_MAX) { 298 /* Drop and request the next packet. */ 299 sc->sc_rxtry = 0; 300 CSR_WRITE_1(sc, SBT_REG_RPC, 0); 301 } else { 302 /* Request the current packet again. */ 303 sc->sc_rxtry++; 304 CSR_WRITE_1(sc, SBT_REG_RPC, RPC_PCRRT); 305 } 306 return error; 307 } 308 309 /* acknowledge read packet */ 310 CSR_WRITE_1(sc, SBT_REG_RPC, 0); 311 312 *lenp = len; 313 return 0; 314 } 315 316 /* 317 * Interrupt handling 318 */ 319 320 static int 321 sbt_intr(void *arg) 322 { 323 struct sbt_softc *sc = arg; 324 struct mbuf *m = NULL; 325 u_int8_t status; 326 size_t len; 327 int s; 328 329 s = splsdmmc(); 330 331 status = CSR_READ_1(sc, SBT_REG_ISTAT); 332 CSR_WRITE_1(sc, SBT_REG_ICLR, status); 333 334 if ((status & ISTAT_INTRD) == 0) 335 return 0; /* shared SDIO card interrupt? */ 336 337 len = SBT_PKT_BUFSIZ; 338 if (sbt_read_packet(sc, sc->sc_buf, &len) != 0 || len == 0) { 339 DPRINTF(("%s: sbt_intr: read failed\n", DEVNAME(sc))); 340 goto eoi; 341 } 342 343 MGETHDR(m, M_DONTWAIT, MT_DATA); 344 if (m == NULL) { 345 DPRINTF(("%s: sbt_intr: MGETHDR failed\n", DEVNAME(sc))); 346 goto eoi; 347 } 348 349 m->m_pkthdr.len = m->m_len = MHLEN; 350 m_copyback(m, 0, len, sc->sc_buf); 351 if (m->m_pkthdr.len == MAX(MHLEN, len)) { 352 m->m_pkthdr.len = len; 353 m->m_len = MIN(MHLEN, m->m_pkthdr.len); 354 } else { 355 DPRINTF(("%s: sbt_intr: m_copyback failed\n", DEVNAME(sc))); 356 m_freem(m); 357 m = NULL; 358 } 359 360 eoi: 361 if (m != NULL) { 362 switch (sc->sc_buf[0]) { 363 case HCI_ACL_DATA_PKT: 364 DNPRINTF(1,("%s: recv ACL packet (%d bytes)\n", 365 DEVNAME(sc), m->m_pkthdr.len)); 366 hci_input_acl(sc->sc_unit, m); 367 break; 368 case HCI_SCO_DATA_PKT: 369 DNPRINTF(1,("%s: recv SCO packet (%d bytes)\n", 370 DEVNAME(sc), m->m_pkthdr.len)); 371 hci_input_sco(sc->sc_unit, m); 372 break; 373 case HCI_EVENT_PKT: 374 DNPRINTF(1,("%s: recv EVENT packet (%d bytes)\n", 375 DEVNAME(sc), m->m_pkthdr.len)); 376 hci_input_event(sc->sc_unit, m); 377 break; 378 default: 379 DPRINTF(("%s: recv 0x%x packet (%d bytes)\n", 380 DEVNAME(sc), sc->sc_buf[0], m->m_pkthdr.len)); 381 sc->sc_stats.err_rx++; 382 m_freem(m); 383 break; 384 } 385 } else 386 sc->sc_stats.err_rx++; 387 388 splx(s); 389 390 /* Claim this interrupt. */ 391 return 1; 392 } 393 394 395 /* 396 * Bluetooth HCI unit functions 397 */ 398 399 static int 400 sbt_enable(device_t self) 401 { 402 struct sbt_softc *sc = device_private(self); 403 int s; 404 405 if (sc->sc_flags & SBT_ENABLED) 406 return 0; 407 408 s = spltty(); 409 410 sc->sc_flags |= SBT_ENABLED; 411 sc->sc_flags &= ~SBT_XMIT; 412 413 splx(s); 414 415 return 0; 416 } 417 418 static void 419 sbt_disable(device_t self) 420 { 421 struct sbt_softc *sc = device_private(self); 422 int s; 423 424 if (!(sc->sc_flags & SBT_ENABLED)) 425 return; 426 427 s = spltty(); 428 429 #ifdef notyet /* XXX */ 430 if (sc->sc_rxp) { 431 m_freem(sc->sc_rxp); 432 sc->sc_rxp = NULL; 433 } 434 435 if (sc->sc_txp) { 436 m_freem(sc->sc_txp); 437 sc->sc_txp = NULL; 438 } 439 #endif 440 441 MBUFQ_DRAIN(&sc->sc_cmdq); 442 MBUFQ_DRAIN(&sc->sc_aclq); 443 MBUFQ_DRAIN(&sc->sc_scoq); 444 445 sc->sc_flags &= ~SBT_ENABLED; 446 447 splx(s); 448 } 449 450 static void 451 sbt_start(struct sbt_softc *sc) 452 { 453 struct mbuf *m; 454 int len; 455 #ifdef SBT_DEBUG 456 const char *what; 457 #endif 458 459 KASSERT((sc->sc_flags & SBT_XMIT) == 0); 460 461 if (sc->sc_dying) 462 return; 463 464 if (MBUFQ_FIRST(&sc->sc_cmdq)) { 465 MBUFQ_DEQUEUE(&sc->sc_cmdq, m); 466 sc->sc_stats.cmd_tx++; 467 #ifdef SBT_DEBUG 468 what = "CMD"; 469 #endif 470 goto start; 471 } 472 473 if (MBUFQ_FIRST(&sc->sc_scoq)) { 474 MBUFQ_DEQUEUE(&sc->sc_scoq, m); 475 sc->sc_stats.sco_tx++; 476 #ifdef SBT_DEBUG 477 what = "SCO"; 478 #endif 479 goto start; 480 } 481 482 if (MBUFQ_FIRST(&sc->sc_aclq)) { 483 MBUFQ_DEQUEUE(&sc->sc_aclq, m); 484 sc->sc_stats.acl_tx++; 485 #ifdef SBT_DEBUG 486 what = "ACL"; 487 #endif 488 goto start; 489 } 490 491 /* Nothing to send */ 492 return; 493 494 start: 495 DNPRINTF(1,("%s: xmit %s packet (%d bytes)\n", DEVNAME(sc), 496 what, m->m_pkthdr.len)); 497 498 sc->sc_flags |= SBT_XMIT; 499 500 len = m->m_pkthdr.len; 501 m_copydata(m, 0, len, sc->sc_buf); 502 m_freem(m); 503 504 if (sbt_write_packet(sc, sc->sc_buf, len)) 505 DPRINTF(("%s: sbt_write_packet failed\n", DEVNAME(sc))); 506 507 sc->sc_flags &= ~SBT_XMIT; 508 } 509 510 static void 511 sbt_start_cmd(device_t self, struct mbuf *m) 512 { 513 struct sbt_softc *sc = device_private(self); 514 int s; 515 516 KASSERT(sc->sc_flags & SBT_ENABLED); 517 518 M_SETCTX(m, NULL); 519 520 s = spltty(); 521 522 MBUFQ_ENQUEUE(&sc->sc_cmdq, m); 523 if ((sc->sc_flags & SBT_XMIT) == 0) 524 sbt_start(sc); 525 526 splx(s); 527 } 528 529 static void 530 sbt_start_acl(device_t self, struct mbuf *m) 531 { 532 struct sbt_softc *sc = device_private(self); 533 int s; 534 535 KASSERT(sc->sc_flags & SBT_ENABLED); 536 537 M_SETCTX(m, NULL); 538 539 s = spltty(); 540 541 MBUFQ_ENQUEUE(&sc->sc_aclq, m); 542 if ((sc->sc_flags & SBT_XMIT) == 0) 543 sbt_start(sc); 544 545 splx(s); 546 } 547 548 static void 549 sbt_start_sco(device_t self, struct mbuf *m) 550 { 551 struct sbt_softc *sc = device_private(self); 552 int s; 553 554 KASSERT(sc->sc_flags & SBT_ENABLED); 555 556 s = spltty(); 557 558 MBUFQ_ENQUEUE(&sc->sc_scoq, m); 559 if ((sc->sc_flags & SBT_XMIT) == 0) 560 sbt_start(sc); 561 562 splx(s); 563 } 564 565 static void 566 sbt_stats(device_t self, struct bt_stats *dest, int flush) 567 { 568 struct sbt_softc *sc = device_private(self); 569 int s; 570 571 s = spltty(); 572 573 memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats)); 574 575 if (flush) 576 memset(&sc->sc_stats, 0, sizeof(struct bt_stats)); 577 578 splx(s); 579 } 580