if_bwfm_usb.c revision 1.5 1 /* $NetBSD: if_bwfm_usb.c,v 1.5 2018/05/11 07:41:11 maya 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 (at) 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