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