1 /* $OpenBSD: if_bwfm_usb.c,v 1.20 2021/11/05 11:38:51 mpi Exp $ */ 2 /* 3 * Copyright (c) 2010-2016 Broadcom Corporation 4 * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "bpfilter.h" 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/buf.h> 24 #include <sys/kernel.h> 25 #include <sys/malloc.h> 26 #include <sys/device.h> 27 #include <sys/queue.h> 28 #include <sys/socket.h> 29 30 #if NBPFILTER > 0 31 #include <net/bpf.h> 32 #endif 33 #include <net/if.h> 34 #include <net/if_dl.h> 35 #include <net/if_media.h> 36 37 #include <netinet/in.h> 38 #include <netinet/if_ether.h> 39 40 #include <net80211/ieee80211_var.h> 41 42 #include <machine/bus.h> 43 44 #include <dev/usb/usb.h> 45 #include <dev/usb/usbdi.h> 46 #include <dev/usb/usbdi_util.h> 47 #include <dev/usb/usbdivar.h> 48 #include <dev/usb/usb_mem.h> 49 #include <dev/usb/usbdevs.h> 50 51 #include <dev/ic/bwfmvar.h> 52 #include <dev/ic/bwfmreg.h> 53 54 /* 55 * Various supported device vendors/products. 56 */ 57 static const struct usb_devno bwfm_usbdevs[] = { 58 { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM43143 }, 59 { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM43236 }, 60 { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM43242 }, 61 { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM43569 }, 62 { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCMFW }, 63 }; 64 65 #ifdef BWFM_DEBUG 66 #define DPRINTF(x) do { if (bwfm_debug > 0) printf x; } while (0) 67 #define DPRINTFN(n, x) do { if (bwfm_debug >= (n)) printf x; } while (0) 68 static int bwfm_debug = 2; 69 #else 70 #define DPRINTF(x) do { ; } while (0) 71 #define DPRINTFN(n, x) do { ; } while (0) 72 #endif 73 74 #define DEVNAME(sc) ((sc)->sc_sc.sc_dev.dv_xname) 75 76 #define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle 77 * has boot up 78 */ 79 80 #define TRX_MAGIC 0x30524448 /* "HDR0" */ 81 #define TRX_MAX_OFFSET 3 /* Max number of file offsets */ 82 #define TRX_UNCOMP_IMAGE 0x20 /* Trx holds uncompressed img */ 83 #define TRX_RDL_CHUNK 1500 /* size of each dl transfer */ 84 #define TRX_OFFSETS_DLFWLEN_IDX 0 85 86 /* Control messages: bRequest values */ 87 #define DL_GETSTATE 0 /* returns the rdl_state_t struct */ 88 #define DL_CHECK_CRC 1 /* currently unused */ 89 #define DL_GO 2 /* execute downloaded image */ 90 #define DL_START 3 /* initialize dl state */ 91 #define DL_REBOOT 4 /* reboot the device in 2 seconds */ 92 #define DL_GETVER 5 /* returns the bootrom_id_t struct */ 93 #define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset 94 * event to occur in 2 seconds. It is the 95 * responsibility of the downloaded code to 96 * clear this event 97 */ 98 #define DL_EXEC 7 /* jump to a supplied address */ 99 #define DL_RESETCFG 8 /* To support single enum on dongle 100 * - Not used by bootloader 101 */ 102 #define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup 103 * if resp unavailable 104 */ 105 106 /* states */ 107 #define DL_WAITING 0 /* waiting to rx first pkt */ 108 #define DL_READY 1 /* hdr was good, waiting for more of the 109 * compressed image 110 */ 111 #define DL_BAD_HDR 2 /* hdr was corrupted */ 112 #define DL_BAD_CRC 3 /* compressed image was corrupted */ 113 #define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ 114 #define DL_START_FAIL 5 /* failed to initialize correctly */ 115 #define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM 116 * value 117 */ 118 #define DL_IMAGE_TOOBIG 7 /* firmware image too big */ 119 120 121 struct trx_header { 122 uint32_t magic; /* "HDR0" */ 123 uint32_t len; /* Length of file including header */ 124 uint32_t crc32; /* CRC from flag_version to end of file */ 125 uint32_t flag_version; /* 0:15 flags, 16:31 version */ 126 uint32_t offsets[TRX_MAX_OFFSET];/* Offsets of partitions from start of 127 * header 128 */ 129 }; 130 131 struct rdl_state { 132 uint32_t state; 133 uint32_t bytes; 134 }; 135 136 struct bootrom_id { 137 uint32_t chip; /* Chip id */ 138 uint32_t chiprev; /* Chip rev */ 139 uint32_t ramsize; /* Size of RAM */ 140 uint32_t remapbase; /* Current remap base address */ 141 uint32_t boardtype; /* Type of board */ 142 uint32_t boardrev; /* Board revision */ 143 }; 144 145 struct bwfm_usb_rx_data { 146 struct bwfm_usb_softc *sc; 147 struct usbd_xfer *xfer; 148 uint8_t *buf; 149 }; 150 151 struct bwfm_usb_tx_data { 152 struct bwfm_usb_softc *sc; 153 struct usbd_xfer *xfer; 154 uint8_t *buf; 155 struct mbuf *mbuf; 156 TAILQ_ENTRY(bwfm_usb_tx_data) next; 157 }; 158 159 #define BWFM_RX_LIST_COUNT 50 160 #define BWFM_TX_LIST_COUNT 50 161 #define BWFM_RXBUFSZ 1600 162 #define BWFM_TXBUFSZ 1600 163 struct bwfm_usb_softc { 164 struct bwfm_softc sc_sc; 165 struct usbd_device *sc_udev; 166 struct usbd_interface *sc_iface; 167 uint8_t sc_ifaceno; 168 169 int sc_initialized; 170 171 uint16_t sc_vendor; 172 uint16_t sc_product; 173 174 uint32_t sc_chip; 175 uint32_t sc_chiprev; 176 177 int sc_rx_no; 178 int sc_tx_no; 179 180 struct usbd_pipe *sc_rx_pipeh; 181 struct usbd_pipe *sc_tx_pipeh; 182 183 struct bwfm_usb_rx_data sc_rx_data[BWFM_RX_LIST_COUNT]; 184 struct bwfm_usb_tx_data sc_tx_data[BWFM_TX_LIST_COUNT]; 185 TAILQ_HEAD(, bwfm_usb_tx_data) sc_tx_free_list; 186 }; 187 188 int bwfm_usb_match(struct device *, void *, void *); 189 void bwfm_usb_attach(struct device *, struct device *, void *); 190 int bwfm_usb_detach(struct device *, int); 191 192 int bwfm_usb_dl_cmd(struct bwfm_usb_softc *, uint8_t, void *, int); 193 int bwfm_usb_load_microcode(struct bwfm_usb_softc *, const u_char *, 194 size_t); 195 196 int bwfm_usb_alloc_rx_list(struct bwfm_usb_softc *); 197 void bwfm_usb_free_rx_list(struct bwfm_usb_softc *); 198 int bwfm_usb_alloc_tx_list(struct bwfm_usb_softc *); 199 void bwfm_usb_free_tx_list(struct bwfm_usb_softc *); 200 201 int bwfm_usb_preinit(struct bwfm_softc *); 202 int bwfm_usb_txcheck(struct bwfm_softc *); 203 int bwfm_usb_txdata(struct bwfm_softc *, struct mbuf *); 204 int bwfm_usb_txctl(struct bwfm_softc *, void *); 205 void bwfm_usb_txctl_cb(struct usbd_xfer *, void *, usbd_status); 206 207 struct mbuf * bwfm_usb_newbuf(void); 208 void bwfm_usb_rxeof(struct usbd_xfer *, void *, usbd_status); 209 void bwfm_usb_txeof(struct usbd_xfer *, void *, usbd_status); 210 211 struct bwfm_bus_ops bwfm_usb_bus_ops = { 212 .bs_preinit = bwfm_usb_preinit, 213 .bs_stop = NULL, 214 .bs_txcheck = bwfm_usb_txcheck, 215 .bs_txdata = bwfm_usb_txdata, 216 .bs_txctl = bwfm_usb_txctl, 217 }; 218 219 const struct cfattach bwfm_usb_ca = { 220 sizeof(struct bwfm_usb_softc), 221 bwfm_usb_match, 222 bwfm_usb_attach, 223 bwfm_usb_detach, 224 }; 225 226 int 227 bwfm_usb_match(struct device *parent, void *match, void *aux) 228 { 229 struct usb_attach_arg *uaa = aux; 230 231 if (uaa->iface == NULL || uaa->configno != 1) 232 return UMATCH_NONE; 233 234 return (usb_lookup(bwfm_usbdevs, uaa->vendor, uaa->product) != NULL) ? 235 UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE; 236 } 237 238 void 239 bwfm_usb_attach(struct device *parent, struct device *self, void *aux) 240 { 241 struct bwfm_usb_softc *sc = (struct bwfm_usb_softc *)self; 242 struct usb_attach_arg *uaa = aux; 243 usb_device_descriptor_t *dd; 244 usb_interface_descriptor_t *id; 245 usb_endpoint_descriptor_t *ed; 246 int i; 247 248 sc->sc_udev = uaa->device; 249 sc->sc_iface = uaa->iface; 250 sc->sc_ifaceno = uaa->ifaceno; 251 sc->sc_vendor = uaa->vendor; 252 sc->sc_product = uaa->product; 253 sc->sc_sc.sc_bus_ops = &bwfm_usb_bus_ops; 254 sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops; 255 256 /* Check number of configurations. */ 257 dd = usbd_get_device_descriptor(sc->sc_udev); 258 if (dd->bNumConfigurations != 1) { 259 printf("%s: number of configurations not supported\n", 260 DEVNAME(sc)); 261 return; 262 } 263 264 /* Get endpoints. */ 265 id = usbd_get_interface_descriptor(sc->sc_iface); 266 267 sc->sc_rx_no = sc->sc_tx_no = -1; 268 for (i = 0; i < id->bNumEndpoints; i++) { 269 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); 270 if (ed == NULL) { 271 printf("%s: no endpoint descriptor for iface %d\n", 272 DEVNAME(sc), i); 273 return; 274 } 275 276 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 277 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK && 278 sc->sc_rx_no == -1) 279 sc->sc_rx_no = ed->bEndpointAddress; 280 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 281 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK && 282 sc->sc_tx_no == -1) 283 sc->sc_tx_no = ed->bEndpointAddress; 284 } 285 if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) { 286 printf("%s: missing endpoint\n", DEVNAME(sc)); 287 return; 288 } 289 290 bwfm_attach(&sc->sc_sc); 291 config_mountroot(self, bwfm_attachhook); 292 } 293 294 int 295 bwfm_usb_preinit(struct bwfm_softc *bwfm) 296 { 297 struct bwfm_usb_softc *sc = (void *)bwfm; 298 struct bwfm_usb_rx_data *data; 299 const char *name = NULL; 300 struct bootrom_id brom; 301 usbd_status error; 302 u_char *ucode; 303 size_t size; 304 int i; 305 306 if (sc->sc_initialized) 307 return 0; 308 309 /* Read chip id and chip rev to check the firmware. */ 310 memset(&brom, 0, sizeof(brom)); 311 bwfm_usb_dl_cmd(sc, DL_GETVER, &brom, sizeof(brom)); 312 sc->sc_chip = letoh32(brom.chip); 313 sc->sc_chiprev = letoh32(brom.chiprev); 314 315 /* Setup data pipes */ 316 error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE, 317 &sc->sc_rx_pipeh); 318 if (error != 0) { 319 printf("%s: could not open rx pipe: %s\n", 320 DEVNAME(sc), usbd_errstr(error)); 321 return 1; 322 } 323 error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, 324 &sc->sc_tx_pipeh); 325 if (error != 0) { 326 printf("%s: could not open tx pipe: %s\n", 327 DEVNAME(sc), usbd_errstr(error)); 328 goto cleanup; 329 } 330 331 /* Firmware not yet loaded? */ 332 if (sc->sc_chip != BRCMF_POSTBOOT_ID) { 333 switch (sc->sc_chip) 334 { 335 case BRCM_CC_43143_CHIP_ID: 336 name = "brcmfmac43143.bin"; 337 break; 338 case BRCM_CC_43235_CHIP_ID: 339 case BRCM_CC_43236_CHIP_ID: 340 case BRCM_CC_43238_CHIP_ID: 341 if (sc->sc_chiprev == 3) 342 name = "brcmfmac43236b.bin"; 343 break; 344 case BRCM_CC_43242_CHIP_ID: 345 name = "brcmfmac43242a.bin"; 346 break; 347 case BRCM_CC_43566_CHIP_ID: 348 case BRCM_CC_43569_CHIP_ID: 349 name = "brcmfmac43569.bin"; 350 break; 351 default: 352 break; 353 } 354 355 if (name == NULL) { 356 printf("%s: unknown firmware\n", DEVNAME(sc)); 357 goto cleanup; 358 } 359 360 if (loadfirmware(name, &ucode, &size) != 0) { 361 printf("%s: failed loadfirmware of file %s\n", 362 DEVNAME(sc), name); 363 goto cleanup; 364 } 365 366 if (bwfm_usb_load_microcode(sc, ucode, size) != 0) { 367 printf("%s: could not load microcode\n", 368 DEVNAME(sc)); 369 free(ucode, M_DEVBUF, size); 370 goto cleanup; 371 } 372 373 free(ucode, M_DEVBUF, size); 374 375 for (i = 0; i < 10; i++) { 376 delay(100 * 1000); 377 memset(&brom, 0, sizeof(brom)); 378 bwfm_usb_dl_cmd(sc, DL_GETVER, &brom, sizeof(brom)); 379 if (letoh32(brom.chip) == BRCMF_POSTBOOT_ID) 380 break; 381 } 382 383 if (letoh32(brom.chip) != BRCMF_POSTBOOT_ID) { 384 printf("%s: firmware did not start up\n", 385 DEVNAME(sc)); 386 goto cleanup; 387 } 388 389 sc->sc_chip = letoh32(brom.chip); 390 sc->sc_chiprev = letoh32(brom.chiprev); 391 } 392 393 bwfm_usb_dl_cmd(sc, DL_RESETCFG, &brom, sizeof(brom)); 394 395 if (bwfm_usb_alloc_rx_list(sc) || bwfm_usb_alloc_tx_list(sc)) { 396 printf("%s: cannot allocate rx/tx lists\n", DEVNAME(sc)); 397 goto cleanup; 398 } 399 400 for (i = 0; i < BWFM_RX_LIST_COUNT; i++) { 401 data = &sc->sc_rx_data[i]; 402 403 usbd_setup_xfer(data->xfer, sc->sc_rx_pipeh, data, data->buf, 404 BWFM_RXBUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 405 bwfm_usb_rxeof); 406 error = usbd_transfer(data->xfer); 407 if (error != 0 && error != USBD_IN_PROGRESS) 408 printf("%s: could not set up new transfer: %s\n", 409 DEVNAME(sc), usbd_errstr(error)); 410 } 411 412 sc->sc_initialized = 1; 413 return 0; 414 415 cleanup: 416 if (sc->sc_rx_pipeh) { 417 usbd_close_pipe(sc->sc_rx_pipeh); 418 sc->sc_rx_pipeh = NULL; 419 } 420 if (sc->sc_tx_pipeh) { 421 usbd_close_pipe(sc->sc_tx_pipeh); 422 sc->sc_tx_pipeh = NULL; 423 } 424 bwfm_usb_free_rx_list(sc); 425 bwfm_usb_free_tx_list(sc); 426 return 1; 427 } 428 429 struct mbuf * 430 bwfm_usb_newbuf(void) 431 { 432 struct mbuf *m; 433 434 MGETHDR(m, M_DONTWAIT, MT_DATA); 435 if (m == NULL) 436 return (NULL); 437 438 MCLGET(m, M_DONTWAIT); 439 if (!(m->m_flags & M_EXT)) { 440 m_freem(m); 441 return (NULL); 442 } 443 444 m->m_len = m->m_pkthdr.len = MCLBYTES; 445 446 return (m); 447 } 448 449 void 450 bwfm_usb_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 451 { 452 struct bwfm_usb_rx_data *data = priv; 453 struct bwfm_usb_softc *sc = data->sc; 454 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 455 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if; 456 usbd_status error; 457 struct mbuf *m; 458 uint32_t len; 459 460 DPRINTFN(2, ("%s: %s status %s\n", DEVNAME(sc), __func__, 461 usbd_errstr(status))); 462 463 if (usbd_is_dying(sc->sc_udev)) 464 return; 465 466 if (__predict_false(status != USBD_NORMAL_COMPLETION)) { 467 usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); 468 if (status != USBD_CANCELLED) 469 goto resubmit; 470 return; 471 } 472 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); 473 474 m = bwfm_usb_newbuf(); 475 if (m == NULL) 476 goto resubmit; 477 478 memcpy(mtod(m, char *), data->buf, len); 479 m->m_len = m->m_pkthdr.len = len; 480 sc->sc_sc.sc_proto_ops->proto_rx(&sc->sc_sc, m, &ml); 481 if_input(ifp, &ml); 482 483 resubmit: 484 usbd_setup_xfer(data->xfer, sc->sc_rx_pipeh, data, data->buf, 485 BWFM_RXBUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 486 bwfm_usb_rxeof); 487 error = usbd_transfer(data->xfer); 488 if (error != 0 && error != USBD_IN_PROGRESS) 489 printf("%s: could not set up new transfer: %s\n", 490 DEVNAME(sc), usbd_errstr(error)); 491 } 492 493 int 494 bwfm_usb_alloc_rx_list(struct bwfm_usb_softc *sc) 495 { 496 struct bwfm_usb_rx_data *data; 497 int i, error = 0; 498 499 for (i = 0; i < BWFM_RX_LIST_COUNT; i++) { 500 data = &sc->sc_rx_data[i]; 501 502 data->sc = sc; /* Backpointer for callbacks. */ 503 504 data->xfer = usbd_alloc_xfer(sc->sc_udev); 505 if (data->xfer == NULL) { 506 printf("%s: could not allocate xfer\n", 507 DEVNAME(sc)); 508 error = ENOMEM; 509 break; 510 } 511 data->buf = usbd_alloc_buffer(data->xfer, BWFM_RXBUFSZ); 512 if (data->buf == NULL) { 513 printf("%s: could not allocate xfer buffer\n", 514 DEVNAME(sc)); 515 error = ENOMEM; 516 break; 517 } 518 } 519 if (error != 0) 520 bwfm_usb_free_rx_list(sc); 521 return (error); 522 } 523 524 void 525 bwfm_usb_free_rx_list(struct bwfm_usb_softc *sc) 526 { 527 int i; 528 529 /* NB: Caller must abort pipe first. */ 530 for (i = 0; i < BWFM_RX_LIST_COUNT; i++) { 531 if (sc->sc_rx_data[i].xfer != NULL) 532 usbd_free_xfer(sc->sc_rx_data[i].xfer); 533 sc->sc_rx_data[i].xfer = NULL; 534 } 535 } 536 537 int 538 bwfm_usb_alloc_tx_list(struct bwfm_usb_softc *sc) 539 { 540 struct bwfm_usb_tx_data *data; 541 int i, error = 0; 542 543 TAILQ_INIT(&sc->sc_tx_free_list); 544 for (i = 0; i < BWFM_TX_LIST_COUNT; i++) { 545 data = &sc->sc_tx_data[i]; 546 547 data->sc = sc; /* Backpointer for callbacks. */ 548 549 data->xfer = usbd_alloc_xfer(sc->sc_udev); 550 if (data->xfer == NULL) { 551 printf("%s: could not allocate xfer\n", 552 DEVNAME(sc)); 553 error = ENOMEM; 554 break; 555 } 556 data->buf = usbd_alloc_buffer(data->xfer, BWFM_TXBUFSZ); 557 if (data->buf == NULL) { 558 printf("%s: could not allocate xfer buffer\n", 559 DEVNAME(sc)); 560 error = ENOMEM; 561 break; 562 } 563 /* Append this Tx buffer to our free list. */ 564 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next); 565 } 566 if (error != 0) 567 bwfm_usb_free_tx_list(sc); 568 return (error); 569 } 570 571 void 572 bwfm_usb_free_tx_list(struct bwfm_usb_softc *sc) 573 { 574 int i; 575 576 /* NB: Caller must abort pipe first. */ 577 for (i = 0; i < BWFM_TX_LIST_COUNT; i++) { 578 if (sc->sc_tx_data[i].xfer != NULL) 579 usbd_free_xfer(sc->sc_tx_data[i].xfer); 580 sc->sc_tx_data[i].xfer = NULL; 581 } 582 } 583 584 void 585 bwfm_usb_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 586 { 587 struct bwfm_usb_tx_data *data = priv; 588 struct bwfm_usb_softc *sc = data->sc; 589 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if; 590 int s; 591 592 DPRINTFN(2, ("%s: %s status %s\n", DEVNAME(sc), __func__, 593 usbd_errstr(status))); 594 595 if (usbd_is_dying(sc->sc_udev)) 596 return; 597 598 s = splnet(); 599 /* Put this Tx buffer back to our free list. */ 600 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next); 601 602 if (__predict_false(status != USBD_NORMAL_COMPLETION)) { 603 if (status == USBD_CANCELLED) 604 usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh); 605 ifp->if_oerrors++; 606 splx(s); 607 return; 608 } 609 610 m_freem(data->mbuf); 611 data->mbuf = NULL; 612 613 /* We just released a Tx buffer, notify Tx. */ 614 if (ifq_is_oactive(&ifp->if_snd)) { 615 ifq_restart(&ifp->if_snd); 616 } 617 splx(s); 618 } 619 620 int 621 bwfm_usb_detach(struct device *self, int flags) 622 { 623 struct bwfm_usb_softc *sc = (struct bwfm_usb_softc *)self; 624 625 bwfm_detach(&sc->sc_sc, flags); 626 627 if (sc->sc_rx_pipeh != NULL) 628 usbd_close_pipe(sc->sc_rx_pipeh); 629 if (sc->sc_tx_pipeh != NULL) 630 usbd_close_pipe(sc->sc_tx_pipeh); 631 632 bwfm_usb_free_rx_list(sc); 633 bwfm_usb_free_tx_list(sc); 634 635 return 0; 636 } 637 638 int 639 bwfm_usb_dl_cmd(struct bwfm_usb_softc *sc, uByte cmd, void *buf, int len) 640 { 641 usb_device_request_t req; 642 usbd_status error; 643 644 req.bmRequestType = UT_READ_VENDOR_INTERFACE; 645 req.bRequest = cmd; 646 647 USETW(req.wValue, 0); 648 USETW(req.wIndex, sc->sc_ifaceno); 649 USETW(req.wLength, len); 650 651 error = usbd_do_request(sc->sc_udev, &req, buf); 652 if (error != 0) { 653 printf("%s: could not read register: %s\n", 654 DEVNAME(sc), usbd_errstr(error)); 655 } 656 return error; 657 } 658 659 int 660 bwfm_usb_load_microcode(struct bwfm_usb_softc *sc, const u_char *ucode, size_t size) 661 { 662 struct trx_header *trx = (struct trx_header *)ucode; 663 struct rdl_state state; 664 uint32_t rdlstate, rdlbytes, sent = 0, sendlen = 0; 665 struct usbd_xfer *xfer; 666 usbd_status error; 667 char *buf; 668 669 if (letoh32(trx->magic) != TRX_MAGIC || 670 (letoh32(trx->flag_version) & TRX_UNCOMP_IMAGE) == 0) { 671 printf("%s: invalid firmware\n", DEVNAME(sc)); 672 return 1; 673 } 674 675 bwfm_usb_dl_cmd(sc, DL_START, &state, sizeof(state)); 676 rdlstate = letoh32(state.state); 677 rdlbytes = letoh32(state.bytes); 678 679 if (rdlstate != DL_WAITING) { 680 printf("%s: cannot start fw download\n", DEVNAME(sc)); 681 return 1; 682 } 683 684 xfer = usbd_alloc_xfer(sc->sc_udev); 685 if (xfer == NULL) { 686 printf("%s: cannot alloc xfer\n", DEVNAME(sc)); 687 goto err; 688 } 689 690 buf = usbd_alloc_buffer(xfer, TRX_RDL_CHUNK); 691 if (buf == NULL) { 692 printf("%s: cannot alloc buf\n", DEVNAME(sc)); 693 goto err; 694 } 695 696 while (rdlbytes != size) { 697 sendlen = MIN(size - sent, TRX_RDL_CHUNK); 698 memcpy(buf, ucode + sent, sendlen); 699 700 usbd_setup_xfer(xfer, sc->sc_tx_pipeh, NULL, buf, sendlen, 701 USBD_SYNCHRONOUS | USBD_NO_COPY, USBD_NO_TIMEOUT, NULL); 702 error = usbd_transfer(xfer); 703 if (error != 0 && error != USBD_IN_PROGRESS) { 704 printf("%s: transfer error\n", DEVNAME(sc)); 705 goto err; 706 } 707 sent += sendlen; 708 709 bwfm_usb_dl_cmd(sc, DL_GETSTATE, &state, sizeof(state)); 710 rdlstate = letoh32(state.state); 711 rdlbytes = letoh32(state.bytes); 712 713 if (rdlbytes != sent) { 714 printf("%s: device reported different size\n", 715 DEVNAME(sc)); 716 goto err; 717 } 718 719 if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) { 720 printf("%s: device reported bad hdr/crc\n", 721 DEVNAME(sc)); 722 goto err; 723 } 724 } 725 726 bwfm_usb_dl_cmd(sc, DL_GETSTATE, &state, sizeof(state)); 727 rdlstate = letoh32(state.state); 728 rdlbytes = letoh32(state.bytes); 729 730 if (rdlstate != DL_RUNNABLE) { 731 printf("%s: dongle not runnable\n", DEVNAME(sc)); 732 goto err; 733 } 734 735 bwfm_usb_dl_cmd(sc, DL_GO, &state, sizeof(state)); 736 737 return 0; 738 err: 739 if (sc->sc_tx_pipeh != NULL) { 740 usbd_close_pipe(sc->sc_tx_pipeh); 741 sc->sc_tx_pipeh = NULL; 742 } 743 if (xfer != NULL) 744 usbd_free_xfer(xfer); 745 return 1; 746 } 747 748 int 749 bwfm_usb_txcheck(struct bwfm_softc *bwfm) 750 { 751 struct bwfm_usb_softc *sc = (void *)bwfm; 752 753 if (TAILQ_EMPTY(&sc->sc_tx_free_list)) 754 return ENOBUFS; 755 756 return 0; 757 } 758 759 int 760 bwfm_usb_txdata(struct bwfm_softc *bwfm, struct mbuf *m) 761 { 762 struct bwfm_usb_softc *sc = (void *)bwfm; 763 struct bwfm_proto_bcdc_hdr *hdr; 764 struct bwfm_usb_tx_data *data; 765 uint32_t len = 0; 766 int error; 767 768 DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__)); 769 770 if (TAILQ_EMPTY(&sc->sc_tx_free_list)) 771 return ENOBUFS; 772 773 /* Grab a Tx buffer from our free list. */ 774 data = TAILQ_FIRST(&sc->sc_tx_free_list); 775 TAILQ_REMOVE(&sc->sc_tx_free_list, data, next); 776 777 hdr = (void *)&data->buf[len]; 778 hdr->data_offset = 0; 779 hdr->priority = ieee80211_classify(&sc->sc_sc.sc_ic, m); 780 hdr->flags = BWFM_BCDC_FLAG_VER(BWFM_BCDC_FLAG_PROTO_VER); 781 hdr->flags2 = 0; 782 len += sizeof(*hdr); 783 784 m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&data->buf[len]); 785 len += m->m_pkthdr.len; 786 787 data->mbuf = m; 788 789 usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, 790 len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, USBD_NO_TIMEOUT, 791 bwfm_usb_txeof); 792 error = usbd_transfer(data->xfer); 793 if (error != 0 && error != USBD_IN_PROGRESS) 794 printf("%s: could not set up new transfer: %s\n", 795 DEVNAME(sc), usbd_errstr(error)); 796 return 0; 797 } 798 799 int 800 bwfm_usb_txctl(struct bwfm_softc *bwfm, void *arg) 801 { 802 struct bwfm_usb_softc *sc = (void *)bwfm; 803 struct bwfm_proto_bcdc_ctl *ctl = arg; 804 usb_device_request_t req; 805 struct usbd_xfer *xfer; 806 usbd_status error; 807 char *buf; 808 809 DPRINTFN(2, ("%s: %s\n", DEVNAME(sc), __func__)); 810 811 /* Send out control packet. */ 812 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 813 req.bRequest = 0; 814 USETW(req.wValue, 0); 815 USETW(req.wIndex, sc->sc_ifaceno); 816 USETW(req.wLength, ctl->len); 817 818 error = usbd_do_request(sc->sc_udev, &req, ctl->buf); 819 if (error != 0) { 820 printf("%s: could not write ctl packet: %s\n", 821 DEVNAME(sc), usbd_errstr(error)); 822 free(ctl->buf, M_TEMP, ctl->len); 823 free(ctl, M_TEMP, sizeof(*ctl)); 824 return 1; 825 } 826 827 /* Setup asynchronous receive. */ 828 if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) { 829 free(ctl->buf, M_TEMP, ctl->len); 830 free(ctl, M_TEMP, sizeof(*ctl)); 831 return 1; 832 } 833 if ((buf = usbd_alloc_buffer(xfer, ctl->len)) == NULL) { 834 free(ctl->buf, M_TEMP, ctl->len); 835 free(ctl, M_TEMP, sizeof(*ctl)); 836 usbd_free_xfer(xfer); 837 return 1; 838 } 839 840 memset(buf, 0, ctl->len); 841 req.bmRequestType = UT_READ_CLASS_INTERFACE; 842 req.bRequest = 1; 843 USETW(req.wValue, 0); 844 USETW(req.wIndex, sc->sc_ifaceno); 845 USETW(req.wLength, ctl->len); 846 847 error = usbd_request_async(xfer, &req, sc, bwfm_usb_txctl_cb); 848 if (error != 0) { 849 printf("%s: could not read ctl packet: %s\n", 850 DEVNAME(sc), usbd_errstr(error)); 851 free(ctl->buf, M_TEMP, ctl->len); 852 free(ctl, M_TEMP, sizeof(*ctl)); 853 return 1; 854 } 855 856 TAILQ_INSERT_TAIL(&sc->sc_sc.sc_bcdc_rxctlq, ctl, next); 857 858 return 0; 859 } 860 861 void 862 bwfm_usb_txctl_cb(struct usbd_xfer *xfer, void *priv, usbd_status err) 863 { 864 struct bwfm_usb_softc *sc = priv; 865 866 if (usbd_is_dying(xfer->pipe->device)) 867 goto err; 868 869 if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) { 870 sc->sc_sc.sc_proto_ops->proto_rxctl(&sc->sc_sc, 871 KERNADDR(&xfer->dmabuf, 0), xfer->actlen); 872 } 873 874 err: 875 usbd_free_xfer(xfer); 876 } 877