Line data Source code
1 : /* $OpenBSD: if_upgt.c,v 1.82 2018/08/25 17:07:20 mestre Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org>
5 : *
6 : * Permission to use, copy, modify, and 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/sockio.h>
23 : #include <sys/mbuf.h>
24 : #include <sys/kernel.h>
25 : #include <sys/socket.h>
26 : #include <sys/systm.h>
27 : #include <sys/timeout.h>
28 : #include <sys/conf.h>
29 : #include <sys/device.h>
30 : #include <sys/endian.h>
31 :
32 : #include <machine/intr.h>
33 :
34 : #if NBPFILTER > 0
35 : #include <net/bpf.h>
36 : #endif
37 : #include <net/if.h>
38 : #include <net/if_dl.h>
39 : #include <net/if_media.h>
40 :
41 : #include <netinet/in.h>
42 : #include <netinet/if_ether.h>
43 :
44 : #include <net80211/ieee80211_var.h>
45 : #include <net80211/ieee80211_radiotap.h>
46 :
47 : #include <dev/usb/usb.h>
48 : #include <dev/usb/usbdi.h>
49 : #include <dev/usb/usbdi_util.h>
50 : #include <dev/usb/usbdevs.h>
51 :
52 : #include <dev/usb/if_upgtvar.h>
53 :
54 : /*
55 : * Driver for the USB PrismGT devices.
56 : *
57 : * For now just USB 2.0 devices with the GW3887 chipset are supported.
58 : * The driver has been written based on the firmware version 2.13.1.0_LM87.
59 : *
60 : * TODO's:
61 : * - Fix MONITOR mode (MAC filter).
62 : * - Add HOSTAP mode.
63 : * - Add IBSS mode.
64 : * - Support the USB 1.0 devices (NET2280, ISL3880, ISL3886 chipsets).
65 : *
66 : * Parts of this driver has been influenced by reading the p54u driver
67 : * written by Jean-Baptiste Note <jean-baptiste.note@m4x.org> and
68 : * Sebastien Bourdeauducq <lekernel@prism54.org>.
69 : */
70 :
71 : #ifdef UPGT_DEBUG
72 : int upgt_debug = 2;
73 : #define DPRINTF(l, x...) do { if ((l) <= upgt_debug) printf(x); } while (0)
74 : #else
75 : #define DPRINTF(l, x...)
76 : #endif
77 :
78 : /*
79 : * Prototypes.
80 : */
81 : int upgt_match(struct device *, void *, void *);
82 : void upgt_attach(struct device *, struct device *, void *);
83 : void upgt_attach_hook(struct device *);
84 : int upgt_detach(struct device *, int);
85 :
86 : int upgt_device_type(struct upgt_softc *, uint16_t, uint16_t);
87 : int upgt_device_init(struct upgt_softc *);
88 : int upgt_mem_init(struct upgt_softc *);
89 : uint32_t upgt_mem_alloc(struct upgt_softc *);
90 : void upgt_mem_free(struct upgt_softc *, uint32_t);
91 : int upgt_fw_alloc(struct upgt_softc *);
92 : void upgt_fw_free(struct upgt_softc *);
93 : int upgt_fw_verify(struct upgt_softc *);
94 : int upgt_fw_load(struct upgt_softc *);
95 : int upgt_fw_copy(char *, char *, int);
96 : int upgt_eeprom_read(struct upgt_softc *);
97 : int upgt_eeprom_parse(struct upgt_softc *);
98 : void upgt_eeprom_parse_hwrx(struct upgt_softc *, uint8_t *);
99 : void upgt_eeprom_parse_freq3(struct upgt_softc *, uint8_t *, int);
100 : void upgt_eeprom_parse_freq4(struct upgt_softc *, uint8_t *, int);
101 : void upgt_eeprom_parse_freq6(struct upgt_softc *, uint8_t *, int);
102 :
103 : int upgt_ioctl(struct ifnet *, u_long, caddr_t);
104 : int upgt_init(struct ifnet *);
105 : void upgt_stop(struct upgt_softc *);
106 : int upgt_media_change(struct ifnet *);
107 : void upgt_newassoc(struct ieee80211com *, struct ieee80211_node *,
108 : int);
109 : int upgt_newstate(struct ieee80211com *, enum ieee80211_state, int);
110 : void upgt_newstate_task(void *);
111 : void upgt_next_scan(void *);
112 : void upgt_start(struct ifnet *);
113 : void upgt_watchdog(struct ifnet *);
114 : void upgt_tx_task(void *);
115 : void upgt_tx_done(struct upgt_softc *, uint8_t *);
116 : void upgt_rx_cb(struct usbd_xfer *, void *, usbd_status);
117 : void upgt_rx(struct upgt_softc *, uint8_t *, int);
118 : void upgt_setup_rates(struct upgt_softc *);
119 : uint8_t upgt_rx_rate(struct upgt_softc *, const int);
120 : int upgt_set_macfilter(struct upgt_softc *, uint8_t state);
121 : int upgt_set_channel(struct upgt_softc *, unsigned);
122 : void upgt_set_led(struct upgt_softc *, int);
123 : void upgt_set_led_blink(void *);
124 : int upgt_get_stats(struct upgt_softc *);
125 :
126 : int upgt_alloc_tx(struct upgt_softc *);
127 : int upgt_alloc_rx(struct upgt_softc *);
128 : int upgt_alloc_cmd(struct upgt_softc *);
129 : void upgt_free_tx(struct upgt_softc *);
130 : void upgt_free_rx(struct upgt_softc *);
131 : void upgt_free_cmd(struct upgt_softc *);
132 : int upgt_bulk_xmit(struct upgt_softc *, struct upgt_data *,
133 : struct usbd_pipe *, uint32_t *, int);
134 :
135 : void upgt_hexdump(void *, int);
136 : uint32_t upgt_crc32_le(const void *, size_t);
137 : uint32_t upgt_chksum_le(const uint32_t *, size_t);
138 :
139 : struct cfdriver upgt_cd = {
140 : NULL, "upgt", DV_IFNET
141 : };
142 :
143 : const struct cfattach upgt_ca = {
144 : sizeof(struct upgt_softc), upgt_match, upgt_attach, upgt_detach
145 : };
146 :
147 : static const struct usb_devno upgt_devs_1[] = {
148 : /* version 1 devices */
149 : { USB_VENDOR_ALCATELT, USB_PRODUCT_ALCATELT_ST120G }
150 : };
151 :
152 : static const struct usb_devno upgt_devs_2[] = {
153 : /* version 2 devices */
154 : { USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_PRISM_GT },
155 : { USB_VENDOR_ALCATELT, USB_PRODUCT_ALCATELT_ST121G },
156 : { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050 },
157 : { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54AG },
158 : { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GV2 },
159 : { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_PRISM_GT },
160 : { USB_VENDOR_DELL, USB_PRODUCT_DELL_PRISM_GT_1 },
161 : { USB_VENDOR_DELL, USB_PRODUCT_DELL_PRISM_GT_2 },
162 : { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG122A2 },
163 : { USB_VENDOR_FSC, USB_PRODUCT_FSC_E5400 },
164 : { USB_VENDOR_GLOBESPAN, USB_PRODUCT_GLOBESPAN_PRISM_GT_1 },
165 : { USB_VENDOR_GLOBESPAN, USB_PRODUCT_GLOBESPAN_PRISM_GT_2 },
166 : { USB_VENDOR_INTERSIL, USB_PRODUCT_INTERSIL_PRISM_GT },
167 : { USB_VENDOR_PHEENET, USB_PRODUCT_PHEENET_GWU513 },
168 : { USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_CPWUA054 },
169 : { USB_VENDOR_SMC, USB_PRODUCT_SMC_2862WG },
170 : { USB_VENDOR_USR, USB_PRODUCT_USR_USR5422 },
171 : { USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_UR045G },
172 : { USB_VENDOR_XYRATEX, USB_PRODUCT_XYRATEX_PRISM_GT_1 },
173 : { USB_VENDOR_XYRATEX, USB_PRODUCT_XYRATEX_PRISM_GT_2 },
174 : { USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_MD40900 },
175 : { USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XG703A }
176 : };
177 :
178 : int
179 0 : upgt_match(struct device *parent, void *match, void *aux)
180 : {
181 0 : struct usb_attach_arg *uaa = aux;
182 :
183 0 : if (uaa->iface == NULL || uaa->configno != UPGT_CONFIG_NO)
184 0 : return (UMATCH_NONE);
185 :
186 0 : if (usb_lookup(upgt_devs_1, uaa->vendor, uaa->product) != NULL)
187 0 : return (UMATCH_VENDOR_PRODUCT);
188 :
189 0 : if (usb_lookup(upgt_devs_2, uaa->vendor, uaa->product) != NULL)
190 0 : return (UMATCH_VENDOR_PRODUCT);
191 :
192 0 : return (UMATCH_NONE);
193 0 : }
194 :
195 : void
196 0 : upgt_attach(struct device *parent, struct device *self, void *aux)
197 : {
198 0 : struct upgt_softc *sc = (struct upgt_softc *)self;
199 0 : struct usb_attach_arg *uaa = aux;
200 : usb_interface_descriptor_t *id;
201 : usb_endpoint_descriptor_t *ed;
202 : usbd_status error;
203 : int i;
204 :
205 : /*
206 : * Attach USB device.
207 : */
208 0 : sc->sc_udev = uaa->device;
209 :
210 : /* check device type */
211 0 : if (upgt_device_type(sc, uaa->vendor, uaa->product) != 0)
212 0 : return;
213 :
214 : /* get the first interface handle */
215 0 : error = usbd_device2interface_handle(sc->sc_udev, UPGT_IFACE_INDEX,
216 0 : &sc->sc_iface);
217 0 : if (error != 0) {
218 0 : printf("%s: could not get interface handle!\n",
219 0 : sc->sc_dev.dv_xname);
220 0 : return;
221 : }
222 :
223 : /* find endpoints */
224 0 : id = usbd_get_interface_descriptor(sc->sc_iface);
225 0 : sc->sc_rx_no = sc->sc_tx_no = -1;
226 0 : for (i = 0; i < id->bNumEndpoints; i++) {
227 0 : ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
228 0 : if (ed == NULL) {
229 0 : printf("%s: no endpoint descriptor for iface %d!\n",
230 0 : sc->sc_dev.dv_xname, i);
231 0 : return;
232 : }
233 :
234 0 : if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
235 0 : UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
236 0 : sc->sc_tx_no = ed->bEndpointAddress;
237 0 : if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
238 0 : UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
239 0 : sc->sc_rx_no = ed->bEndpointAddress;
240 :
241 : /*
242 : * 0x01 TX pipe
243 : * 0x81 RX pipe
244 : *
245 : * Deprecated scheme (not used with fw version >2.5.6.x):
246 : * 0x02 TX MGMT pipe
247 : * 0x82 TX MGMT pipe
248 : */
249 0 : if (sc->sc_tx_no != -1 && sc->sc_rx_no != -1)
250 : break;
251 : }
252 0 : if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) {
253 0 : printf("%s: missing endpoint!\n", sc->sc_dev.dv_xname);
254 0 : return;
255 : }
256 :
257 : /* setup tasks and timeouts */
258 0 : usb_init_task(&sc->sc_task_newstate, upgt_newstate_task, sc,
259 : USB_TASK_TYPE_GENERIC);
260 0 : usb_init_task(&sc->sc_task_tx, upgt_tx_task, sc, USB_TASK_TYPE_GENERIC);
261 0 : timeout_set(&sc->scan_to, upgt_next_scan, sc);
262 0 : timeout_set(&sc->led_to, upgt_set_led_blink, sc);
263 :
264 : /*
265 : * Open TX and RX USB bulk pipes.
266 : */
267 0 : error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE,
268 0 : &sc->sc_tx_pipeh);
269 0 : if (error != 0) {
270 0 : printf("%s: could not open TX pipe: %s!\n",
271 0 : sc->sc_dev.dv_xname, usbd_errstr(error));
272 0 : goto fail;
273 : }
274 0 : error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE,
275 0 : &sc->sc_rx_pipeh);
276 0 : if (error != 0) {
277 0 : printf("%s: could not open RX pipe: %s!\n",
278 0 : sc->sc_dev.dv_xname, usbd_errstr(error));
279 0 : goto fail;
280 : }
281 :
282 : /*
283 : * Allocate TX, RX, and CMD xfers.
284 : */
285 0 : if (upgt_alloc_tx(sc) != 0)
286 : goto fail;
287 0 : if (upgt_alloc_rx(sc) != 0)
288 : goto fail;
289 0 : if (upgt_alloc_cmd(sc) != 0)
290 : goto fail;
291 :
292 : /*
293 : * We need the firmware loaded to complete the attach.
294 : */
295 0 : config_mountroot(self, upgt_attach_hook);
296 :
297 0 : return;
298 : fail:
299 0 : printf("%s: %s failed!\n", sc->sc_dev.dv_xname, __func__);
300 0 : }
301 :
302 : void
303 0 : upgt_attach_hook(struct device *self)
304 : {
305 0 : struct upgt_softc *sc = (struct upgt_softc *)self;
306 0 : struct ieee80211com *ic = &sc->sc_ic;
307 0 : struct ifnet *ifp = &ic->ic_if;
308 : usbd_status error;
309 : int i;
310 :
311 : /*
312 : * Load firmware file into memory.
313 : */
314 0 : if (upgt_fw_alloc(sc) != 0)
315 : goto fail;
316 :
317 : /*
318 : * Initialize the device.
319 : */
320 0 : if (upgt_device_init(sc) != 0)
321 : goto fail;
322 :
323 : /*
324 : * Verify the firmware.
325 : */
326 0 : if (upgt_fw_verify(sc) != 0)
327 : goto fail;
328 :
329 : /*
330 : * Calculate device memory space.
331 : */
332 0 : if (sc->sc_memaddr_frame_start == 0 || sc->sc_memaddr_frame_end == 0) {
333 0 : printf("%s: could not find memory space addresses on FW!\n",
334 0 : sc->sc_dev.dv_xname);
335 0 : goto fail;
336 : }
337 0 : sc->sc_memaddr_frame_end -= UPGT_MEMSIZE_RX + 1;
338 0 : sc->sc_memaddr_rx_start = sc->sc_memaddr_frame_end + 1;
339 :
340 : DPRINTF(1, "%s: memory address frame start=0x%08x\n",
341 : sc->sc_dev.dv_xname, sc->sc_memaddr_frame_start);
342 : DPRINTF(1, "%s: memory address frame end=0x%08x\n",
343 : sc->sc_dev.dv_xname, sc->sc_memaddr_frame_end);
344 : DPRINTF(1, "%s: memory address rx start=0x%08x\n",
345 : sc->sc_dev.dv_xname, sc->sc_memaddr_rx_start);
346 :
347 0 : upgt_mem_init(sc);
348 :
349 : /*
350 : * Load the firmware.
351 : */
352 0 : if (upgt_fw_load(sc) != 0)
353 : goto fail;
354 :
355 : /*
356 : * Startup the RX pipe.
357 : */
358 0 : struct upgt_data *data_rx = &sc->rx_data;
359 :
360 0 : usbd_setup_xfer(data_rx->xfer, sc->sc_rx_pipeh, data_rx, data_rx->buf,
361 : MCLBYTES, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, upgt_rx_cb);
362 0 : error = usbd_transfer(data_rx->xfer);
363 0 : if (error != 0 && error != USBD_IN_PROGRESS) {
364 0 : printf("%s: could not queue RX transfer!\n",
365 0 : sc->sc_dev.dv_xname);
366 0 : goto fail;
367 : }
368 0 : usbd_delay_ms(sc->sc_udev, 100);
369 :
370 : /*
371 : * Read the whole EEPROM content and parse it.
372 : */
373 0 : if (upgt_eeprom_read(sc) != 0)
374 : goto fail;
375 0 : if (upgt_eeprom_parse(sc) != 0)
376 : goto fail;
377 :
378 : /*
379 : * Setup the 802.11 device.
380 : */
381 0 : ic->ic_phytype = IEEE80211_T_OFDM;
382 0 : ic->ic_opmode = IEEE80211_M_STA;
383 0 : ic->ic_state = IEEE80211_S_INIT;
384 0 : ic->ic_caps =
385 : IEEE80211_C_MONITOR |
386 : IEEE80211_C_SHPREAMBLE |
387 : IEEE80211_C_SHSLOT |
388 : IEEE80211_C_WEP |
389 : IEEE80211_C_RSN;
390 :
391 0 : ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
392 0 : ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
393 :
394 0 : for (i = 1; i <= 14; i++) {
395 0 : ic->ic_channels[i].ic_freq =
396 0 : ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
397 0 : ic->ic_channels[i].ic_flags =
398 : IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
399 : IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
400 : }
401 :
402 0 : ifp->if_softc = sc;
403 0 : ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
404 0 : ifp->if_ioctl = upgt_ioctl;
405 0 : ifp->if_start = upgt_start;
406 0 : ifp->if_watchdog = upgt_watchdog;
407 0 : memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
408 :
409 0 : if_attach(ifp);
410 0 : ieee80211_ifattach(ifp);
411 0 : ic->ic_newassoc = upgt_newassoc;
412 :
413 0 : sc->sc_newstate = ic->ic_newstate;
414 0 : ic->ic_newstate = upgt_newstate;
415 0 : ieee80211_media_init(ifp, upgt_media_change, ieee80211_media_status);
416 :
417 : #if NBPFILTER > 0
418 0 : bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
419 : sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
420 :
421 0 : sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
422 0 : sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
423 0 : sc->sc_rxtap.wr_ihdr.it_present = htole32(UPGT_RX_RADIOTAP_PRESENT);
424 :
425 0 : sc->sc_txtap_len = sizeof(sc->sc_txtapu);
426 0 : sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
427 0 : sc->sc_txtap.wt_ihdr.it_present = htole32(UPGT_TX_RADIOTAP_PRESENT);
428 : #endif
429 :
430 0 : printf("%s: address %s\n",
431 0 : sc->sc_dev.dv_xname, ether_sprintf(ic->ic_myaddr));
432 :
433 0 : return;
434 : fail:
435 0 : printf("%s: %s failed!\n", sc->sc_dev.dv_xname, __func__);
436 0 : }
437 :
438 : int
439 0 : upgt_detach(struct device *self, int flags)
440 : {
441 0 : struct upgt_softc *sc = (struct upgt_softc *)self;
442 0 : struct ifnet *ifp = &sc->sc_ic.ic_if;
443 : int s;
444 :
445 : DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
446 :
447 0 : s = splusb();
448 :
449 : /* abort and close TX / RX pipes */
450 0 : if (sc->sc_tx_pipeh != NULL) {
451 0 : usbd_abort_pipe(sc->sc_tx_pipeh);
452 0 : usbd_close_pipe(sc->sc_tx_pipeh);
453 0 : }
454 0 : if (sc->sc_rx_pipeh != NULL) {
455 0 : usbd_abort_pipe(sc->sc_rx_pipeh);
456 0 : usbd_close_pipe(sc->sc_rx_pipeh);
457 0 : }
458 :
459 : /* remove tasks and timeouts */
460 0 : usb_rem_task(sc->sc_udev, &sc->sc_task_newstate);
461 0 : usb_rem_task(sc->sc_udev, &sc->sc_task_tx);
462 0 : if (timeout_initialized(&sc->scan_to))
463 0 : timeout_del(&sc->scan_to);
464 0 : if (timeout_initialized(&sc->led_to))
465 0 : timeout_del(&sc->led_to);
466 :
467 : /* free xfers */
468 0 : upgt_free_tx(sc);
469 0 : upgt_free_rx(sc);
470 0 : upgt_free_cmd(sc);
471 :
472 : /* free firmware */
473 0 : upgt_fw_free(sc);
474 :
475 0 : if (ifp->if_softc != NULL) {
476 : /* detach interface */
477 0 : ieee80211_ifdetach(ifp);
478 0 : if_detach(ifp);
479 0 : }
480 :
481 0 : splx(s);
482 :
483 0 : return (0);
484 : }
485 :
486 : int
487 0 : upgt_device_type(struct upgt_softc *sc, uint16_t vendor, uint16_t product)
488 : {
489 0 : if (usb_lookup(upgt_devs_1, vendor, product) != NULL) {
490 0 : sc->sc_device_type = 1;
491 : /* XXX */
492 0 : printf("%s: version 1 devices not supported yet!\n",
493 0 : sc->sc_dev.dv_xname);
494 0 : return (1);
495 : } else {
496 0 : sc->sc_device_type = 2;
497 : }
498 :
499 0 : return (0);
500 0 : }
501 :
502 : int
503 0 : upgt_device_init(struct upgt_softc *sc)
504 : {
505 0 : struct upgt_data *data_cmd = &sc->cmd_data;
506 0 : char init_cmd[] = { 0x7e, 0x7e, 0x7e, 0x7e };
507 0 : int len;
508 :
509 0 : len = sizeof(init_cmd);
510 0 : bcopy(init_cmd, data_cmd->buf, len);
511 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
512 0 : printf("%s: could not send device init string!\n",
513 0 : sc->sc_dev.dv_xname);
514 0 : return (EIO);
515 : }
516 0 : usbd_delay_ms(sc->sc_udev, 100);
517 :
518 : DPRINTF(1, "%s: device initialized\n", sc->sc_dev.dv_xname);
519 :
520 0 : return (0);
521 0 : }
522 :
523 : int
524 0 : upgt_mem_init(struct upgt_softc *sc)
525 : {
526 : int i;
527 :
528 0 : for (i = 0; i < UPGT_MEMORY_MAX_PAGES; i++) {
529 0 : sc->sc_memory.page[i].used = 0;
530 :
531 0 : if (i == 0) {
532 : /*
533 : * The first memory page is always reserved for
534 : * command data.
535 : */
536 0 : sc->sc_memory.page[i].addr =
537 0 : sc->sc_memaddr_frame_start + MCLBYTES;
538 0 : } else {
539 0 : sc->sc_memory.page[i].addr =
540 0 : sc->sc_memory.page[i - 1].addr + MCLBYTES;
541 : }
542 :
543 0 : if (sc->sc_memory.page[i].addr + MCLBYTES >=
544 0 : sc->sc_memaddr_frame_end)
545 : break;
546 :
547 : DPRINTF(2, "%s: memory address page %d=0x%08x\n",
548 : sc->sc_dev.dv_xname, i, sc->sc_memory.page[i].addr);
549 : }
550 :
551 0 : sc->sc_memory.pages = i;
552 :
553 : DPRINTF(2, "%s: memory pages=%d\n",
554 : sc->sc_dev.dv_xname, sc->sc_memory.pages);
555 :
556 0 : return (0);
557 : }
558 :
559 : uint32_t
560 0 : upgt_mem_alloc(struct upgt_softc *sc)
561 : {
562 : int i;
563 :
564 0 : for (i = 0; i < sc->sc_memory.pages; i++) {
565 0 : if (sc->sc_memory.page[i].used == 0) {
566 0 : sc->sc_memory.page[i].used = 1;
567 0 : return (sc->sc_memory.page[i].addr);
568 : }
569 : }
570 :
571 0 : return (0);
572 0 : }
573 :
574 : void
575 0 : upgt_mem_free(struct upgt_softc *sc, uint32_t addr)
576 : {
577 : int i;
578 :
579 0 : for (i = 0; i < sc->sc_memory.pages; i++) {
580 0 : if (sc->sc_memory.page[i].addr == addr) {
581 0 : sc->sc_memory.page[i].used = 0;
582 0 : return;
583 : }
584 : }
585 :
586 0 : printf("%s: could not free memory address 0x%08x!\n",
587 0 : sc->sc_dev.dv_xname, addr);
588 0 : }
589 :
590 :
591 : int
592 0 : upgt_fw_alloc(struct upgt_softc *sc)
593 : {
594 : const char *name = "upgt-gw3887";
595 : int error;
596 :
597 0 : if (sc->sc_fw == NULL) {
598 0 : error = loadfirmware(name, &sc->sc_fw, &sc->sc_fw_size);
599 0 : if (error != 0) {
600 0 : printf("%s: error %d, could not read firmware %s!\n",
601 0 : sc->sc_dev.dv_xname, error, name);
602 0 : return (EIO);
603 : }
604 : }
605 :
606 : DPRINTF(1, "%s: firmware %s allocated\n", sc->sc_dev.dv_xname, name);
607 :
608 0 : return (0);
609 0 : }
610 :
611 : void
612 0 : upgt_fw_free(struct upgt_softc *sc)
613 : {
614 0 : if (sc->sc_fw != NULL) {
615 0 : free(sc->sc_fw, M_DEVBUF, sc->sc_fw_size);
616 0 : sc->sc_fw = NULL;
617 : DPRINTF(1, "%s: firmware freed\n", sc->sc_dev.dv_xname);
618 0 : }
619 0 : }
620 :
621 : int
622 0 : upgt_fw_verify(struct upgt_softc *sc)
623 : {
624 : struct upgt_fw_bra_option *bra_option;
625 : uint32_t bra_option_type, bra_option_len;
626 : uint32_t *uc;
627 : int offset, bra_end = 0;
628 :
629 : /*
630 : * Seek to beginning of Boot Record Area (BRA).
631 : */
632 0 : for (offset = 0; offset < sc->sc_fw_size; offset += sizeof(*uc)) {
633 0 : uc = (uint32_t *)(sc->sc_fw + offset);
634 0 : if (*uc == 0)
635 : break;
636 : }
637 0 : for (; offset < sc->sc_fw_size; offset += sizeof(*uc)) {
638 0 : uc = (uint32_t *)(sc->sc_fw + offset);
639 0 : if (*uc != 0)
640 : break;
641 : }
642 0 : if (offset == sc->sc_fw_size) {
643 0 : printf("%s: firmware Boot Record Area not found!\n",
644 0 : sc->sc_dev.dv_xname);
645 0 : return (EIO);
646 : }
647 : DPRINTF(1, "%s: firmware Boot Record Area found at offset %d\n",
648 : sc->sc_dev.dv_xname, offset);
649 :
650 : /*
651 : * Parse Boot Record Area (BRA) options.
652 : */
653 0 : while (offset < sc->sc_fw_size && bra_end == 0) {
654 : /* get current BRA option */
655 0 : bra_option = (struct upgt_fw_bra_option *)(sc->sc_fw + offset);
656 0 : bra_option_type = letoh32(bra_option->type);
657 0 : bra_option_len = letoh32(bra_option->len) * sizeof(*uc);
658 :
659 0 : switch (bra_option_type) {
660 : case UPGT_BRA_TYPE_FW:
661 : DPRINTF(1, "%s: UPGT_BRA_TYPE_FW len=%d\n",
662 : sc->sc_dev.dv_xname, bra_option_len);
663 :
664 0 : if (bra_option_len != UPGT_BRA_FWTYPE_SIZE) {
665 0 : printf("%s: wrong UPGT_BRA_TYPE_FW len!\n",
666 0 : sc->sc_dev.dv_xname);
667 0 : return (EIO);
668 : }
669 0 : if (memcmp(UPGT_BRA_FWTYPE_LM86, bra_option->data,
670 0 : bra_option_len) == 0) {
671 0 : sc->sc_fw_type = UPGT_FWTYPE_LM86;
672 0 : break;
673 : }
674 0 : if (memcmp(UPGT_BRA_FWTYPE_LM87, bra_option->data,
675 0 : bra_option_len) == 0) {
676 0 : sc->sc_fw_type = UPGT_FWTYPE_LM87;
677 0 : break;
678 : }
679 0 : if (memcmp(UPGT_BRA_FWTYPE_FMAC, bra_option->data,
680 0 : bra_option_len) == 0) {
681 0 : sc->sc_fw_type = UPGT_FWTYPE_FMAC;
682 0 : break;
683 : }
684 0 : printf("%s: unsupported firmware type!\n",
685 0 : sc->sc_dev.dv_xname);
686 0 : return (EIO);
687 : case UPGT_BRA_TYPE_VERSION:
688 : DPRINTF(1, "%s: UPGT_BRA_TYPE_VERSION len=%d\n",
689 : sc->sc_dev.dv_xname, bra_option_len);
690 : break;
691 : case UPGT_BRA_TYPE_DEPIF:
692 : DPRINTF(1, "%s: UPGT_BRA_TYPE_DEPIF len=%d\n",
693 : sc->sc_dev.dv_xname, bra_option_len);
694 : break;
695 : case UPGT_BRA_TYPE_EXPIF:
696 : DPRINTF(1, "%s: UPGT_BRA_TYPE_EXPIF len=%d\n",
697 : sc->sc_dev.dv_xname, bra_option_len);
698 : break;
699 : case UPGT_BRA_TYPE_DESCR:
700 : DPRINTF(1, "%s: UPGT_BRA_TYPE_DESCR len=%d\n",
701 : sc->sc_dev.dv_xname, bra_option_len);
702 :
703 : struct upgt_fw_bra_descr *descr =
704 0 : (struct upgt_fw_bra_descr *)bra_option->data;
705 :
706 0 : sc->sc_memaddr_frame_start =
707 0 : letoh32(descr->memaddr_space_start);
708 0 : sc->sc_memaddr_frame_end =
709 0 : letoh32(descr->memaddr_space_end);
710 :
711 : DPRINTF(2, "%s: memory address space start=0x%08x\n",
712 : sc->sc_dev.dv_xname, sc->sc_memaddr_frame_start);
713 : DPRINTF(2, "%s: memory address space end=0x%08x\n",
714 : sc->sc_dev.dv_xname, sc->sc_memaddr_frame_end);
715 0 : break;
716 : case UPGT_BRA_TYPE_END:
717 : DPRINTF(1, "%s: UPGT_BRA_TYPE_END len=%d\n",
718 : sc->sc_dev.dv_xname, bra_option_len);
719 : bra_end = 1;
720 0 : break;
721 : default:
722 : DPRINTF(1, "%s: unknown BRA option len=%d\n",
723 : sc->sc_dev.dv_xname, bra_option_len);
724 0 : return (EIO);
725 : }
726 :
727 : /* jump to next BRA option */
728 0 : offset += sizeof(struct upgt_fw_bra_option) + bra_option_len;
729 : }
730 :
731 : DPRINTF(1, "%s: firmware verified\n", sc->sc_dev.dv_xname);
732 :
733 0 : return (0);
734 0 : }
735 :
736 : int
737 0 : upgt_fw_load(struct upgt_softc *sc)
738 : {
739 0 : struct upgt_data *data_cmd = &sc->cmd_data;
740 0 : struct upgt_data *data_rx = &sc->rx_data;
741 0 : char start_fwload_cmd[] = { 0x3c, 0x0d };
742 0 : int offset, bsize, n, i, len;
743 : uint32_t crc32;
744 :
745 : /* send firmware start load command */
746 0 : len = sizeof(start_fwload_cmd);
747 0 : bcopy(start_fwload_cmd, data_cmd->buf, len);
748 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
749 0 : printf("%s: could not send start_firmware_load command!\n",
750 0 : sc->sc_dev.dv_xname);
751 0 : return (EIO);
752 : }
753 :
754 : /* send X2 header */
755 0 : len = sizeof(struct upgt_fw_x2_header);
756 0 : struct upgt_fw_x2_header *x2 = data_cmd->buf;
757 0 : bcopy(UPGT_X2_SIGNATURE, x2->signature, UPGT_X2_SIGNATURE_SIZE);
758 0 : x2->startaddr = htole32(UPGT_MEMADDR_FIRMWARE_START);
759 0 : x2->len = htole32(sc->sc_fw_size);
760 0 : x2->crc = upgt_crc32_le(data_cmd->buf + UPGT_X2_SIGNATURE_SIZE,
761 : sizeof(struct upgt_fw_x2_header) - UPGT_X2_SIGNATURE_SIZE -
762 : sizeof(uint32_t));
763 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
764 0 : printf("%s: could not send firmware X2 header!\n",
765 0 : sc->sc_dev.dv_xname);
766 0 : return (EIO);
767 : }
768 :
769 : /* download firmware */
770 0 : for (offset = 0; offset < sc->sc_fw_size; offset += bsize) {
771 0 : if (sc->sc_fw_size - offset > UPGT_FW_BLOCK_SIZE)
772 0 : bsize = UPGT_FW_BLOCK_SIZE;
773 : else
774 0 : bsize = sc->sc_fw_size - offset;
775 :
776 0 : n = upgt_fw_copy(sc->sc_fw + offset, data_cmd->buf, bsize);
777 :
778 : DPRINTF(1, "%s: FW offset=%d, read=%d, sent=%d\n",
779 : sc->sc_dev.dv_xname, offset, n, bsize);
780 :
781 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &bsize, 0)
782 0 : != 0) {
783 0 : printf("%s: error while downloading firmware block!\n",
784 0 : sc->sc_dev.dv_xname);
785 0 : return (EIO);
786 : }
787 :
788 0 : bsize = n;
789 : }
790 : DPRINTF(1, "%s: firmware downloaded\n", sc->sc_dev.dv_xname);
791 :
792 : /* load firmware */
793 0 : crc32 = upgt_crc32_le(sc->sc_fw, sc->sc_fw_size);
794 0 : *((uint32_t *)(data_cmd->buf) ) = crc32;
795 0 : *((uint8_t *)(data_cmd->buf) + 4) = 'g';
796 0 : *((uint8_t *)(data_cmd->buf) + 5) = '\r';
797 0 : len = 6;
798 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
799 0 : printf("%s: could not send load_firmware command!\n",
800 0 : sc->sc_dev.dv_xname);
801 0 : return (EIO);
802 : }
803 :
804 0 : for (i = 0; i < UPGT_FIRMWARE_TIMEOUT; i++) {
805 0 : len = UPGT_FW_BLOCK_SIZE;
806 0 : bzero(data_rx->buf, MCLBYTES);
807 0 : if (upgt_bulk_xmit(sc, data_rx, sc->sc_rx_pipeh, &len,
808 0 : USBD_SHORT_XFER_OK) != 0) {
809 0 : printf("%s: could not read firmware response!\n",
810 0 : sc->sc_dev.dv_xname);
811 0 : return (EIO);
812 : }
813 :
814 0 : if (memcmp(data_rx->buf, "OK", 2) == 0)
815 : break; /* firmware load was successful */
816 : }
817 0 : if (i == UPGT_FIRMWARE_TIMEOUT) {
818 0 : printf("%s: firmware load failed!\n", sc->sc_dev.dv_xname);
819 0 : return (EIO);
820 : }
821 : DPRINTF(1, "%s: firmware loaded\n", sc->sc_dev.dv_xname);
822 :
823 0 : return (0);
824 0 : }
825 :
826 : /*
827 : * While copying the version 2 firmware, we need to replace two characters:
828 : *
829 : * 0x7e -> 0x7d 0x5e
830 : * 0x7d -> 0x7d 0x5d
831 : */
832 : int
833 0 : upgt_fw_copy(char *src, char *dst, int size)
834 : {
835 : int i, j;
836 :
837 0 : for (i = 0, j = 0; i < size && j < size; i++) {
838 0 : switch (src[i]) {
839 : case 0x7e:
840 0 : dst[j] = 0x7d;
841 0 : j++;
842 0 : dst[j] = 0x5e;
843 0 : j++;
844 0 : break;
845 : case 0x7d:
846 0 : dst[j] = 0x7d;
847 0 : j++;
848 0 : dst[j] = 0x5d;
849 0 : j++;
850 0 : break;
851 : default:
852 0 : dst[j] = src[i];
853 0 : j++;
854 0 : break;
855 : }
856 : }
857 :
858 0 : return (i);
859 : }
860 :
861 : int
862 0 : upgt_eeprom_read(struct upgt_softc *sc)
863 : {
864 0 : struct upgt_data *data_cmd = &sc->cmd_data;
865 : struct upgt_lmac_mem *mem;
866 : struct upgt_lmac_eeprom *eeprom;
867 0 : int offset, block, len;
868 :
869 : offset = 0;
870 : block = UPGT_EEPROM_BLOCK_SIZE;
871 0 : while (offset < UPGT_EEPROM_SIZE) {
872 : DPRINTF(1, "%s: request EEPROM block (offset=%d, len=%d)\n",
873 : sc->sc_dev.dv_xname, offset, block);
874 :
875 : /*
876 : * Transmit the URB containing the CMD data.
877 : */
878 0 : bzero(data_cmd->buf, MCLBYTES);
879 :
880 0 : mem = (struct upgt_lmac_mem *)data_cmd->buf;
881 0 : mem->addr = htole32(sc->sc_memaddr_frame_start +
882 : UPGT_MEMSIZE_FRAME_HEAD);
883 :
884 0 : eeprom = (struct upgt_lmac_eeprom *)(mem + 1);
885 0 : eeprom->header1.flags = 0;
886 0 : eeprom->header1.type = UPGT_H1_TYPE_CTRL;
887 0 : eeprom->header1.len = htole16((
888 : sizeof(struct upgt_lmac_eeprom) -
889 : sizeof(struct upgt_lmac_header)) + block);
890 :
891 0 : eeprom->header2.reqid = htole32(sc->sc_memaddr_frame_start);
892 0 : eeprom->header2.type = htole16(UPGT_H2_TYPE_EEPROM);
893 0 : eeprom->header2.flags = 0;
894 :
895 0 : eeprom->offset = htole16(offset);
896 0 : eeprom->len = htole16(block);
897 :
898 0 : len = sizeof(*mem) + sizeof(*eeprom) + block;
899 :
900 0 : mem->chksum = upgt_chksum_le((uint32_t *)eeprom,
901 0 : len - sizeof(*mem));
902 :
903 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len,
904 0 : USBD_FORCE_SHORT_XFER) != 0) {
905 0 : printf("%s: could not transmit EEPROM data URB!\n",
906 0 : sc->sc_dev.dv_xname);
907 0 : return (EIO);
908 : }
909 0 : if (tsleep(sc, 0, "eeprom_request", UPGT_USB_TIMEOUT)) {
910 0 : printf("%s: timeout while waiting for EEPROM data!\n",
911 0 : sc->sc_dev.dv_xname);
912 0 : return (EIO);
913 : }
914 :
915 0 : offset += block;
916 0 : if (UPGT_EEPROM_SIZE - offset < block)
917 0 : block = UPGT_EEPROM_SIZE - offset;
918 : }
919 :
920 0 : return (0);
921 0 : }
922 :
923 : int
924 0 : upgt_eeprom_parse(struct upgt_softc *sc)
925 : {
926 0 : struct ieee80211com *ic = &sc->sc_ic;
927 : struct upgt_eeprom_header *eeprom_header;
928 : struct upgt_eeprom_option *eeprom_option;
929 : uint16_t option_len;
930 : uint16_t option_type;
931 : uint16_t preamble_len;
932 : int option_end = 0;
933 :
934 : /* calculate eeprom options start offset */
935 0 : eeprom_header = (struct upgt_eeprom_header *)sc->sc_eeprom;
936 0 : preamble_len = letoh16(eeprom_header->preamble_len);
937 0 : eeprom_option = (struct upgt_eeprom_option *)(sc->sc_eeprom +
938 0 : (sizeof(struct upgt_eeprom_header) + preamble_len));
939 :
940 0 : while (!option_end) {
941 : /* the eeprom option length is stored in words */
942 : option_len =
943 0 : (letoh16(eeprom_option->len) - 1) * sizeof(uint16_t);
944 : option_type =
945 0 : letoh16(eeprom_option->type);
946 :
947 0 : switch (option_type) {
948 : case UPGT_EEPROM_TYPE_NAME:
949 : DPRINTF(1, "%s: EEPROM name len=%d\n",
950 : sc->sc_dev.dv_xname, option_len);
951 : break;
952 : case UPGT_EEPROM_TYPE_SERIAL:
953 : DPRINTF(1, "%s: EEPROM serial len=%d\n",
954 : sc->sc_dev.dv_xname, option_len);
955 : break;
956 : case UPGT_EEPROM_TYPE_MAC:
957 : DPRINTF(1, "%s: EEPROM mac len=%d\n",
958 : sc->sc_dev.dv_xname, option_len);
959 :
960 0 : IEEE80211_ADDR_COPY(ic->ic_myaddr, eeprom_option->data);
961 0 : break;
962 : case UPGT_EEPROM_TYPE_HWRX:
963 : DPRINTF(1, "%s: EEPROM hwrx len=%d\n",
964 : sc->sc_dev.dv_xname, option_len);
965 :
966 0 : upgt_eeprom_parse_hwrx(sc, eeprom_option->data);
967 0 : break;
968 : case UPGT_EEPROM_TYPE_CHIP:
969 : DPRINTF(1, "%s: EEPROM chip len=%d\n",
970 : sc->sc_dev.dv_xname, option_len);
971 : break;
972 : case UPGT_EEPROM_TYPE_FREQ3:
973 : DPRINTF(1, "%s: EEPROM freq3 len=%d\n",
974 : sc->sc_dev.dv_xname, option_len);
975 :
976 0 : upgt_eeprom_parse_freq3(sc, eeprom_option->data,
977 0 : option_len);
978 0 : break;
979 : case UPGT_EEPROM_TYPE_FREQ4:
980 : DPRINTF(1, "%s: EEPROM freq4 len=%d\n",
981 : sc->sc_dev.dv_xname, option_len);
982 :
983 0 : upgt_eeprom_parse_freq4(sc, eeprom_option->data,
984 0 : option_len);
985 0 : break;
986 : case UPGT_EEPROM_TYPE_FREQ5:
987 : DPRINTF(1, "%s: EEPROM freq5 len=%d\n",
988 : sc->sc_dev.dv_xname, option_len);
989 : break;
990 : case UPGT_EEPROM_TYPE_FREQ6:
991 : DPRINTF(1, "%s: EEPROM freq6 len=%d\n",
992 : sc->sc_dev.dv_xname, option_len);
993 :
994 0 : upgt_eeprom_parse_freq6(sc, eeprom_option->data,
995 0 : option_len);
996 0 : break;
997 : case UPGT_EEPROM_TYPE_END:
998 : DPRINTF(1, "%s: EEPROM end len=%d\n",
999 : sc->sc_dev.dv_xname, option_len);
1000 : option_end = 1;
1001 0 : break;
1002 : case UPGT_EEPROM_TYPE_OFF:
1003 : DPRINTF(1, "%s: EEPROM off without end option!\n",
1004 : sc->sc_dev.dv_xname);
1005 0 : return (EIO);
1006 : default:
1007 : DPRINTF(1, "%s: EEPROM unknown type 0x%04x len=%d\n",
1008 : sc->sc_dev.dv_xname, option_type, option_len);
1009 : break;
1010 : }
1011 :
1012 : /* jump to next EEPROM option */
1013 0 : eeprom_option = (struct upgt_eeprom_option *)
1014 0 : (eeprom_option->data + option_len);
1015 : }
1016 :
1017 0 : return (0);
1018 0 : }
1019 :
1020 : void
1021 0 : upgt_eeprom_parse_hwrx(struct upgt_softc *sc, uint8_t *data)
1022 : {
1023 : struct upgt_eeprom_option_hwrx *option_hwrx;
1024 :
1025 0 : option_hwrx = (struct upgt_eeprom_option_hwrx *)data;
1026 :
1027 0 : sc->sc_eeprom_hwrx = option_hwrx->rxfilter - UPGT_EEPROM_RX_CONST;
1028 :
1029 : DPRINTF(2, "%s: hwrx option value=0x%04x\n",
1030 : sc->sc_dev.dv_xname, sc->sc_eeprom_hwrx);
1031 0 : }
1032 :
1033 : void
1034 0 : upgt_eeprom_parse_freq3(struct upgt_softc *sc, uint8_t *data, int len)
1035 : {
1036 : struct upgt_eeprom_freq3_header *freq3_header;
1037 : struct upgt_lmac_freq3 *freq3;
1038 : int i, elements, flags;
1039 : unsigned channel;
1040 :
1041 0 : freq3_header = (struct upgt_eeprom_freq3_header *)data;
1042 0 : freq3 = (struct upgt_lmac_freq3 *)(freq3_header + 1);
1043 :
1044 0 : flags = freq3_header->flags;
1045 0 : elements = freq3_header->elements;
1046 :
1047 : DPRINTF(2, "%s: flags=0x%02x\n", sc->sc_dev.dv_xname, flags);
1048 : DPRINTF(2, "%s: elements=%d\n", sc->sc_dev.dv_xname, elements);
1049 :
1050 0 : for (i = 0; i < elements; i++) {
1051 0 : channel = ieee80211_mhz2ieee(letoh16(freq3[i].freq), 0);
1052 :
1053 0 : sc->sc_eeprom_freq3[channel] = freq3[i];
1054 :
1055 : DPRINTF(2, "%s: frequence=%d, channel=%d\n",
1056 : sc->sc_dev.dv_xname,
1057 : letoh16(sc->sc_eeprom_freq3[channel].freq), channel);
1058 : }
1059 0 : }
1060 :
1061 : void
1062 0 : upgt_eeprom_parse_freq4(struct upgt_softc *sc, uint8_t *data, int len)
1063 : {
1064 : struct upgt_eeprom_freq4_header *freq4_header;
1065 : struct upgt_eeprom_freq4_1 *freq4_1;
1066 : struct upgt_eeprom_freq4_2 *freq4_2;
1067 : int i, j, elements, settings, flags;
1068 : unsigned channel;
1069 :
1070 0 : freq4_header = (struct upgt_eeprom_freq4_header *)data;
1071 0 : freq4_1 = (struct upgt_eeprom_freq4_1 *)(freq4_header + 1);
1072 :
1073 0 : flags = freq4_header->flags;
1074 0 : elements = freq4_header->elements;
1075 0 : settings = freq4_header->settings;
1076 :
1077 : /* we need this value later */
1078 0 : sc->sc_eeprom_freq6_settings = freq4_header->settings;
1079 :
1080 : DPRINTF(2, "%s: flags=0x%02x\n", sc->sc_dev.dv_xname, flags);
1081 : DPRINTF(2, "%s: elements=%d\n", sc->sc_dev.dv_xname, elements);
1082 : DPRINTF(2, "%s: settings=%d\n", sc->sc_dev.dv_xname, settings);
1083 :
1084 0 : for (i = 0; i < elements; i++) {
1085 0 : channel = ieee80211_mhz2ieee(letoh16(freq4_1[i].freq), 0);
1086 :
1087 0 : freq4_2 = (struct upgt_eeprom_freq4_2 *)freq4_1[i].data;
1088 :
1089 0 : for (j = 0; j < settings; j++) {
1090 0 : sc->sc_eeprom_freq4[channel][j].cmd = freq4_2[j];
1091 0 : sc->sc_eeprom_freq4[channel][j].pad = 0;
1092 : }
1093 :
1094 : DPRINTF(2, "%s: frequence=%d, channel=%d\n",
1095 : sc->sc_dev.dv_xname,
1096 : letoh16(freq4_1[i].freq), channel);
1097 : }
1098 0 : }
1099 :
1100 : void
1101 0 : upgt_eeprom_parse_freq6(struct upgt_softc *sc, uint8_t *data, int len)
1102 : {
1103 : struct upgt_lmac_freq6 *freq6;
1104 : int i, elements;
1105 : unsigned channel;
1106 :
1107 0 : freq6 = (struct upgt_lmac_freq6 *)data;
1108 :
1109 0 : elements = len / sizeof(struct upgt_lmac_freq6);
1110 :
1111 : DPRINTF(2, "%s: elements=%d\n", sc->sc_dev.dv_xname, elements);
1112 :
1113 0 : for (i = 0; i < elements; i++) {
1114 0 : channel = ieee80211_mhz2ieee(letoh16(freq6[i].freq), 0);
1115 :
1116 0 : sc->sc_eeprom_freq6[channel] = freq6[i];
1117 :
1118 : DPRINTF(2, "%s: frequence=%d, channel=%d\n",
1119 : sc->sc_dev.dv_xname,
1120 : letoh16(sc->sc_eeprom_freq6[channel].freq), channel);
1121 : }
1122 0 : }
1123 :
1124 : int
1125 0 : upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1126 : {
1127 0 : struct upgt_softc *sc = ifp->if_softc;
1128 0 : struct ieee80211com *ic = &sc->sc_ic;
1129 : int s, error = 0;
1130 : uint8_t chan;
1131 :
1132 0 : s = splnet();
1133 :
1134 0 : switch (cmd) {
1135 : case SIOCSIFADDR:
1136 0 : ifp->if_flags |= IFF_UP;
1137 : /* FALLTHROUGH */
1138 : case SIOCSIFFLAGS:
1139 0 : if (ifp->if_flags & IFF_UP) {
1140 0 : if ((ifp->if_flags & IFF_RUNNING) == 0)
1141 0 : upgt_init(ifp);
1142 : } else {
1143 0 : if (ifp->if_flags & IFF_RUNNING)
1144 0 : upgt_stop(sc);
1145 : }
1146 : break;
1147 : case SIOCS80211CHANNEL:
1148 : /* allow fast channel switching in monitor mode */
1149 0 : error = ieee80211_ioctl(ifp, cmd, data);
1150 0 : if (error == ENETRESET &&
1151 0 : ic->ic_opmode == IEEE80211_M_MONITOR) {
1152 0 : if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
1153 : (IFF_UP | IFF_RUNNING)) {
1154 0 : ic->ic_bss->ni_chan = ic->ic_ibss_chan;
1155 0 : chan = ieee80211_chan2ieee(ic,
1156 0 : ic->ic_bss->ni_chan);
1157 0 : upgt_set_channel(sc, chan);
1158 0 : }
1159 : error = 0;
1160 0 : }
1161 : break;
1162 : default:
1163 0 : error = ieee80211_ioctl(ifp, cmd, data);
1164 0 : break;
1165 : }
1166 :
1167 0 : if (error == ENETRESET) {
1168 0 : if (ifp->if_flags & (IFF_UP | IFF_RUNNING))
1169 0 : upgt_init(ifp);
1170 : error = 0;
1171 0 : }
1172 :
1173 0 : splx(s);
1174 :
1175 0 : return (error);
1176 : }
1177 :
1178 : int
1179 0 : upgt_init(struct ifnet *ifp)
1180 : {
1181 0 : struct upgt_softc *sc = ifp->if_softc;
1182 0 : struct ieee80211com *ic = &sc->sc_ic;
1183 :
1184 : DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
1185 :
1186 0 : IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
1187 :
1188 : /* select default channel */
1189 0 : ic->ic_bss->ni_chan = ic->ic_ibss_chan;
1190 0 : sc->sc_cur_chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
1191 :
1192 : /* setup device rates */
1193 0 : upgt_setup_rates(sc);
1194 :
1195 0 : ifp->if_flags |= IFF_RUNNING;
1196 0 : ifq_clr_oactive(&ifp->if_snd);
1197 :
1198 0 : upgt_set_macfilter(sc, IEEE80211_S_SCAN);
1199 :
1200 0 : if (ic->ic_opmode == IEEE80211_M_MONITOR) {
1201 0 : upgt_set_channel(sc, sc->sc_cur_chan);
1202 0 : ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1203 0 : } else
1204 0 : ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1205 :
1206 0 : return (0);
1207 : }
1208 :
1209 : void
1210 0 : upgt_stop(struct upgt_softc *sc)
1211 : {
1212 0 : struct ieee80211com *ic = &sc->sc_ic;
1213 0 : struct ifnet *ifp = &ic->ic_if;
1214 :
1215 : DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
1216 :
1217 : /* device down */
1218 0 : ifp->if_timer = 0;
1219 0 : ifp->if_flags &= ~IFF_RUNNING;
1220 0 : ifq_clr_oactive(&ifp->if_snd);
1221 :
1222 0 : upgt_set_led(sc, UPGT_LED_OFF);
1223 :
1224 : /* change device back to initial state */
1225 0 : ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1226 0 : }
1227 :
1228 : int
1229 0 : upgt_media_change(struct ifnet *ifp)
1230 : {
1231 0 : struct upgt_softc *sc = ifp->if_softc;
1232 : int error;
1233 :
1234 : DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
1235 :
1236 0 : if ((error = ieee80211_media_change(ifp)) != ENETRESET)
1237 0 : return (error);
1238 :
1239 0 : if (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1240 : /* give pending USB transfers a chance to finish */
1241 0 : usbd_delay_ms(sc->sc_udev, 100);
1242 0 : upgt_init(ifp);
1243 0 : }
1244 :
1245 0 : return (0);
1246 0 : }
1247 :
1248 : void
1249 0 : upgt_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
1250 : {
1251 0 : ni->ni_txrate = 0;
1252 0 : }
1253 :
1254 : int
1255 0 : upgt_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1256 : {
1257 0 : struct upgt_softc *sc = ic->ic_if.if_softc;
1258 :
1259 0 : usb_rem_task(sc->sc_udev, &sc->sc_task_newstate);
1260 0 : timeout_del(&sc->scan_to);
1261 :
1262 : /* do it in a process context */
1263 0 : sc->sc_state = nstate;
1264 0 : sc->sc_arg = arg;
1265 0 : usb_add_task(sc->sc_udev, &sc->sc_task_newstate);
1266 :
1267 0 : return (0);
1268 : }
1269 :
1270 : void
1271 0 : upgt_newstate_task(void *arg)
1272 : {
1273 0 : struct upgt_softc *sc = arg;
1274 0 : struct ieee80211com *ic = &sc->sc_ic;
1275 : struct ieee80211_node *ni;
1276 : unsigned channel;
1277 :
1278 0 : switch (sc->sc_state) {
1279 : case IEEE80211_S_INIT:
1280 : DPRINTF(1, "%s: newstate is IEEE80211_S_INIT\n",
1281 : sc->sc_dev.dv_xname);
1282 :
1283 : /* do not accept any frames if the device is down */
1284 0 : upgt_set_macfilter(sc, IEEE80211_S_INIT);
1285 0 : upgt_set_led(sc, UPGT_LED_OFF);
1286 0 : break;
1287 : case IEEE80211_S_SCAN:
1288 : DPRINTF(1, "%s: newstate is IEEE80211_S_SCAN\n",
1289 : sc->sc_dev.dv_xname);
1290 :
1291 0 : channel = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
1292 0 : upgt_set_channel(sc, channel);
1293 0 : timeout_add_msec(&sc->scan_to, 200);
1294 0 : break;
1295 : case IEEE80211_S_AUTH:
1296 : DPRINTF(1, "%s: newstate is IEEE80211_S_AUTH\n",
1297 : sc->sc_dev.dv_xname);
1298 :
1299 0 : channel = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
1300 0 : upgt_set_channel(sc, channel);
1301 0 : break;
1302 : case IEEE80211_S_ASSOC:
1303 : DPRINTF(1, "%s: newstate is IEEE80211_S_ASSOC\n",
1304 : sc->sc_dev.dv_xname);
1305 : break;
1306 : case IEEE80211_S_RUN:
1307 : DPRINTF(1, "%s: newstate is IEEE80211_S_RUN\n",
1308 : sc->sc_dev.dv_xname);
1309 :
1310 0 : ni = ic->ic_bss;
1311 :
1312 : /*
1313 : * TX rate control is done by the firmware.
1314 : * Report the maximum rate which is available therefore.
1315 : */
1316 0 : ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
1317 :
1318 0 : if (ic->ic_opmode != IEEE80211_M_MONITOR)
1319 0 : upgt_set_macfilter(sc, IEEE80211_S_RUN);
1320 0 : upgt_set_led(sc, UPGT_LED_ON);
1321 0 : break;
1322 : }
1323 :
1324 0 : sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
1325 0 : }
1326 :
1327 : void
1328 0 : upgt_next_scan(void *arg)
1329 : {
1330 0 : struct upgt_softc *sc = arg;
1331 0 : struct ieee80211com *ic = &sc->sc_ic;
1332 0 : struct ifnet *ifp = &ic->ic_if;
1333 :
1334 : DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
1335 :
1336 0 : if (ic->ic_state == IEEE80211_S_SCAN)
1337 0 : ieee80211_next_scan(ifp);
1338 0 : }
1339 :
1340 : void
1341 0 : upgt_start(struct ifnet *ifp)
1342 : {
1343 0 : struct upgt_softc *sc = ifp->if_softc;
1344 0 : struct ieee80211com *ic = &sc->sc_ic;
1345 0 : struct ieee80211_node *ni;
1346 : struct mbuf *m;
1347 : int i;
1348 :
1349 : /* don't transmit packets if interface is busy or down */
1350 0 : if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
1351 0 : return;
1352 :
1353 : DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
1354 :
1355 0 : for (i = 0; i < UPGT_TX_COUNT; i++) {
1356 0 : struct upgt_data *data_tx = &sc->tx_data[i];
1357 :
1358 0 : m = mq_dequeue(&ic->ic_mgtq);
1359 0 : if (m != NULL) {
1360 : /* management frame */
1361 0 : ni = m->m_pkthdr.ph_cookie;
1362 : #if NBPFILTER > 0
1363 0 : if (ic->ic_rawbpf != NULL)
1364 0 : bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
1365 : #endif
1366 0 : if ((data_tx->addr = upgt_mem_alloc(sc)) == 0) {
1367 0 : printf("%s: no free prism memory!\n",
1368 0 : sc->sc_dev.dv_xname);
1369 0 : return;
1370 : }
1371 0 : data_tx->ni = ni;
1372 0 : data_tx->m = m;
1373 0 : sc->tx_queued++;
1374 0 : } else {
1375 : /* data frame */
1376 0 : if (ic->ic_state != IEEE80211_S_RUN)
1377 0 : break;
1378 :
1379 0 : IFQ_DEQUEUE(&ifp->if_snd, m);
1380 0 : if (m == NULL)
1381 0 : break;
1382 :
1383 : #if NBPFILTER > 0
1384 0 : if (ifp->if_bpf != NULL)
1385 0 : bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1386 : #endif
1387 0 : m = ieee80211_encap(ifp, m, &ni);
1388 0 : if (m == NULL)
1389 0 : continue;
1390 : #if NBPFILTER > 0
1391 0 : if (ic->ic_rawbpf != NULL)
1392 0 : bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
1393 : #endif
1394 0 : if ((data_tx->addr = upgt_mem_alloc(sc)) == 0) {
1395 0 : printf("%s: no free prism memory!\n",
1396 0 : sc->sc_dev.dv_xname);
1397 0 : return;
1398 : }
1399 0 : data_tx->ni = ni;
1400 0 : data_tx->m = m;
1401 0 : sc->tx_queued++;
1402 : }
1403 0 : }
1404 :
1405 0 : if (sc->tx_queued > 0) {
1406 : DPRINTF(2, "%s: tx_queued=%d\n",
1407 : sc->sc_dev.dv_xname, sc->tx_queued);
1408 : /* process the TX queue in process context */
1409 0 : ifp->if_timer = 5;
1410 0 : ifq_set_oactive(&ifp->if_snd);
1411 0 : usb_rem_task(sc->sc_udev, &sc->sc_task_tx);
1412 0 : usb_add_task(sc->sc_udev, &sc->sc_task_tx);
1413 0 : }
1414 0 : }
1415 :
1416 : void
1417 0 : upgt_watchdog(struct ifnet *ifp)
1418 : {
1419 0 : struct upgt_softc *sc = ifp->if_softc;
1420 0 : struct ieee80211com *ic = &sc->sc_ic;
1421 :
1422 0 : if (ic->ic_state == IEEE80211_S_INIT)
1423 0 : return;
1424 :
1425 0 : printf("%s: watchdog timeout!\n", sc->sc_dev.dv_xname);
1426 :
1427 : /* TODO: what shall we do on TX timeout? */
1428 :
1429 0 : ieee80211_watchdog(ifp);
1430 0 : }
1431 :
1432 : void
1433 0 : upgt_tx_task(void *arg)
1434 : {
1435 0 : struct upgt_softc *sc = arg;
1436 0 : struct ieee80211com *ic = &sc->sc_ic;
1437 : struct ieee80211_frame *wh;
1438 : struct ieee80211_key *k;
1439 : struct upgt_lmac_mem *mem;
1440 : struct upgt_lmac_tx_desc *txdesc;
1441 : struct mbuf *m;
1442 : uint32_t addr;
1443 : int len, i, s;
1444 : usbd_status error;
1445 :
1446 0 : s = splusb();
1447 :
1448 0 : upgt_set_led(sc, UPGT_LED_BLINK);
1449 :
1450 0 : for (i = 0; i < UPGT_TX_COUNT; i++) {
1451 0 : struct upgt_data *data_tx = &sc->tx_data[i];
1452 :
1453 0 : if (data_tx->m == NULL) {
1454 : DPRINTF(2, "%s: %d: m is NULL\n",
1455 : sc->sc_dev.dv_xname, i);
1456 0 : continue;
1457 : }
1458 :
1459 : m = data_tx->m;
1460 0 : addr = data_tx->addr + UPGT_MEMSIZE_FRAME_HEAD;
1461 :
1462 : /*
1463 : * Software crypto.
1464 : */
1465 0 : wh = mtod(m, struct ieee80211_frame *);
1466 :
1467 0 : if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1468 0 : k = ieee80211_get_txkey(ic, wh, ic->ic_bss);
1469 :
1470 0 : if ((m = ieee80211_encrypt(ic, m, k)) == NULL) {
1471 0 : splx(s);
1472 0 : return;
1473 : }
1474 :
1475 : /* in case packet header moved, reset pointer */
1476 0 : wh = mtod(m, struct ieee80211_frame *);
1477 0 : }
1478 :
1479 : /*
1480 : * Transmit the URB containing the TX data.
1481 : */
1482 0 : bzero(data_tx->buf, MCLBYTES);
1483 :
1484 0 : mem = (struct upgt_lmac_mem *)data_tx->buf;
1485 0 : mem->addr = htole32(addr);
1486 :
1487 0 : txdesc = (struct upgt_lmac_tx_desc *)(mem + 1);
1488 :
1489 : /* XXX differ between data and mgmt frames? */
1490 0 : txdesc->header1.flags = UPGT_H1_FLAGS_TX_DATA;
1491 0 : txdesc->header1.type = UPGT_H1_TYPE_TX_DATA;
1492 0 : txdesc->header1.len = htole16(m->m_pkthdr.len);
1493 :
1494 0 : txdesc->header2.reqid = htole32(data_tx->addr);
1495 0 : txdesc->header2.type = htole16(UPGT_H2_TYPE_TX_ACK_YES);
1496 0 : txdesc->header2.flags = htole16(UPGT_H2_FLAGS_TX_ACK_YES);
1497 :
1498 0 : if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
1499 : IEEE80211_FC0_TYPE_MGT) {
1500 : /* always send mgmt frames at lowest rate (DS1) */
1501 0 : memset(txdesc->rates, 0x10, sizeof(txdesc->rates));
1502 0 : } else {
1503 0 : bcopy(sc->sc_cur_rateset, txdesc->rates,
1504 : sizeof(txdesc->rates));
1505 : }
1506 0 : txdesc->type = htole32(UPGT_TX_DESC_TYPE_DATA);
1507 0 : txdesc->pad3[0] = UPGT_TX_DESC_PAD3_SIZE;
1508 :
1509 : #if NBPFILTER > 0
1510 0 : if (sc->sc_drvbpf != NULL) {
1511 0 : struct mbuf mb;
1512 0 : struct upgt_tx_radiotap_header *tap = &sc->sc_txtap;
1513 :
1514 0 : tap->wt_flags = 0;
1515 0 : tap->wt_rate = 0; /* TODO: where to get from? */
1516 0 : tap->wt_chan_freq =
1517 0 : htole16(ic->ic_bss->ni_chan->ic_freq);
1518 0 : tap->wt_chan_flags =
1519 0 : htole16(ic->ic_bss->ni_chan->ic_flags);
1520 :
1521 0 : mb.m_data = (caddr_t)tap;
1522 0 : mb.m_len = sc->sc_txtap_len;
1523 0 : mb.m_next = m;
1524 0 : mb.m_nextpkt = NULL;
1525 0 : mb.m_type = 0;
1526 0 : mb.m_flags = 0;
1527 0 : bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
1528 0 : }
1529 : #endif
1530 : /* copy frame below our TX descriptor header */
1531 0 : m_copydata(m, 0, m->m_pkthdr.len,
1532 0 : data_tx->buf + (sizeof(*mem) + sizeof(*txdesc)));
1533 :
1534 : /* calculate frame size */
1535 0 : len = sizeof(*mem) + sizeof(*txdesc) + m->m_pkthdr.len;
1536 :
1537 : /* we need to align the frame to a 4 byte boundary */
1538 0 : len = (len + 3) & ~3;
1539 :
1540 : /* calculate frame checksum */
1541 0 : mem->chksum = upgt_chksum_le((uint32_t *)txdesc,
1542 0 : len - sizeof(*mem));
1543 :
1544 : /* we do not need the mbuf anymore */
1545 0 : m_freem(m);
1546 0 : data_tx->m = NULL;
1547 :
1548 : DPRINTF(2, "%s: TX start data sending\n", sc->sc_dev.dv_xname);
1549 :
1550 0 : usbd_setup_xfer(data_tx->xfer, sc->sc_tx_pipeh, data_tx,
1551 0 : data_tx->buf, len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
1552 : UPGT_USB_TIMEOUT, NULL);
1553 0 : error = usbd_transfer(data_tx->xfer);
1554 0 : if (error != 0 && error != USBD_IN_PROGRESS) {
1555 0 : printf("%s: could not transmit TX data URB!\n",
1556 0 : sc->sc_dev.dv_xname);
1557 0 : splx(s);
1558 0 : return;
1559 : }
1560 :
1561 : DPRINTF(2, "%s: TX sent (%d bytes)\n",
1562 : sc->sc_dev.dv_xname, len);
1563 0 : }
1564 :
1565 : /*
1566 : * If we don't regulary read the device statistics, the RX queue
1567 : * will stall. It's strange, but it works, so we keep reading
1568 : * the statistics here. *shrug*
1569 : */
1570 0 : upgt_get_stats(sc);
1571 :
1572 0 : splx(s);
1573 0 : }
1574 :
1575 : void
1576 0 : upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
1577 : {
1578 0 : struct ieee80211com *ic = &sc->sc_ic;
1579 0 : struct ifnet *ifp = &ic->ic_if;
1580 : struct upgt_lmac_tx_done_desc *desc;
1581 : int i, s;
1582 :
1583 0 : s = splnet();
1584 :
1585 0 : desc = (struct upgt_lmac_tx_done_desc *)data;
1586 :
1587 0 : for (i = 0; i < UPGT_TX_COUNT; i++) {
1588 0 : struct upgt_data *data_tx = &sc->tx_data[i];
1589 :
1590 0 : if (data_tx->addr == letoh32(desc->header2.reqid)) {
1591 0 : upgt_mem_free(sc, data_tx->addr);
1592 0 : ieee80211_release_node(ic, data_tx->ni);
1593 0 : data_tx->ni = NULL;
1594 0 : data_tx->addr = 0;
1595 :
1596 0 : sc->tx_queued--;
1597 :
1598 : DPRINTF(2, "%s: TX done: ", sc->sc_dev.dv_xname);
1599 : DPRINTF(2, "memaddr=0x%08x, status=0x%04x, rssi=%d, ",
1600 : letoh32(desc->header2.reqid),
1601 : letoh16(desc->status),
1602 : letoh16(desc->rssi));
1603 : DPRINTF(2, "seq=%d\n", letoh16(desc->seq));
1604 0 : break;
1605 : }
1606 0 : }
1607 :
1608 0 : if (sc->tx_queued == 0) {
1609 : /* TX queued was processed, continue */
1610 0 : ifp->if_timer = 0;
1611 0 : ifq_clr_oactive(&ifp->if_snd);
1612 0 : upgt_start(ifp);
1613 0 : }
1614 :
1615 0 : splx(s);
1616 0 : }
1617 :
1618 : void
1619 0 : upgt_rx_cb(struct usbd_xfer *xfer, void *priv, usbd_status status)
1620 : {
1621 0 : struct upgt_data *data_rx = priv;
1622 0 : struct upgt_softc *sc = data_rx->sc;
1623 0 : int len;
1624 : struct upgt_lmac_header *header;
1625 : struct upgt_lmac_eeprom *eeprom;
1626 : uint8_t h1_type;
1627 : uint16_t h2_type;
1628 :
1629 : DPRINTF(3, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
1630 :
1631 0 : if (status != USBD_NORMAL_COMPLETION) {
1632 0 : if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1633 0 : return;
1634 0 : if (status == USBD_STALLED)
1635 0 : usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh);
1636 : goto skip;
1637 : }
1638 0 : usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1639 :
1640 : /*
1641 : * Check what type of frame came in.
1642 : */
1643 0 : header = (struct upgt_lmac_header *)(data_rx->buf + 4);
1644 :
1645 0 : h1_type = header->header1.type;
1646 0 : h2_type = letoh16(header->header2.type);
1647 :
1648 0 : if (h1_type == UPGT_H1_TYPE_CTRL &&
1649 0 : h2_type == UPGT_H2_TYPE_EEPROM) {
1650 0 : eeprom = (struct upgt_lmac_eeprom *)(data_rx->buf + 4);
1651 0 : uint16_t eeprom_offset = letoh16(eeprom->offset);
1652 0 : uint16_t eeprom_len = letoh16(eeprom->len);
1653 :
1654 : DPRINTF(2, "%s: received EEPROM block (offset=%d, len=%d)\n",
1655 : sc->sc_dev.dv_xname, eeprom_offset, eeprom_len);
1656 :
1657 0 : bcopy(data_rx->buf + sizeof(struct upgt_lmac_eeprom) + 4,
1658 0 : sc->sc_eeprom + eeprom_offset, eeprom_len);
1659 :
1660 : /* EEPROM data has arrived in time, wakeup tsleep() */
1661 0 : wakeup(sc);
1662 0 : } else
1663 0 : if (h1_type == UPGT_H1_TYPE_CTRL &&
1664 0 : h2_type == UPGT_H2_TYPE_TX_DONE) {
1665 : DPRINTF(2, "%s: received 802.11 TX done\n",
1666 : sc->sc_dev.dv_xname);
1667 :
1668 0 : upgt_tx_done(sc, data_rx->buf + 4);
1669 0 : } else
1670 0 : if (h1_type == UPGT_H1_TYPE_RX_DATA ||
1671 0 : h1_type == UPGT_H1_TYPE_RX_DATA_MGMT) {
1672 : DPRINTF(3, "%s: received 802.11 RX data\n",
1673 : sc->sc_dev.dv_xname);
1674 :
1675 0 : upgt_rx(sc, data_rx->buf + 4, letoh16(header->header1.len));
1676 0 : } else
1677 : if (h1_type == UPGT_H1_TYPE_CTRL &&
1678 : h2_type == UPGT_H2_TYPE_STATS) {
1679 : DPRINTF(2, "%s: received statistic data\n",
1680 : sc->sc_dev.dv_xname);
1681 :
1682 : /* TODO: what could we do with the statistic data? */
1683 : } else {
1684 : /* ignore unknown frame types */
1685 : DPRINTF(1, "%s: received unknown frame type 0x%02x\n",
1686 : sc->sc_dev.dv_xname, header->header1.type);
1687 : }
1688 :
1689 : skip: /* setup new transfer */
1690 0 : usbd_setup_xfer(xfer, sc->sc_rx_pipeh, data_rx, data_rx->buf, MCLBYTES,
1691 : USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, upgt_rx_cb);
1692 0 : (void)usbd_transfer(xfer);
1693 0 : }
1694 :
1695 : void
1696 0 : upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen)
1697 : {
1698 0 : struct ieee80211com *ic = &sc->sc_ic;
1699 0 : struct ifnet *ifp = &ic->ic_if;
1700 : struct upgt_lmac_rx_desc *rxdesc;
1701 : struct ieee80211_frame *wh;
1702 0 : struct ieee80211_rxinfo rxi;
1703 : struct ieee80211_node *ni;
1704 : struct mbuf *m;
1705 : int s;
1706 :
1707 : /* access RX packet descriptor */
1708 0 : rxdesc = (struct upgt_lmac_rx_desc *)data;
1709 :
1710 : /* create mbuf which is suitable for strict alignment archs */
1711 0 : m = m_devget(rxdesc->data, pkglen, ETHER_ALIGN);
1712 0 : if (m == NULL) {
1713 : DPRINTF(1, "%s: could not create RX mbuf!\n", sc->sc_dev.dv_xname);
1714 0 : ifp->if_ierrors++;
1715 0 : return;
1716 : }
1717 :
1718 0 : s = splnet();
1719 :
1720 : #if NBPFILTER > 0
1721 0 : if (sc->sc_drvbpf != NULL) {
1722 0 : struct mbuf mb;
1723 0 : struct upgt_rx_radiotap_header *tap = &sc->sc_rxtap;
1724 :
1725 0 : tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
1726 0 : tap->wr_rate = upgt_rx_rate(sc, rxdesc->rate);
1727 0 : tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
1728 0 : tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
1729 0 : tap->wr_antsignal = rxdesc->rssi;
1730 :
1731 0 : mb.m_data = (caddr_t)tap;
1732 0 : mb.m_len = sc->sc_rxtap_len;
1733 0 : mb.m_next = m;
1734 0 : mb.m_nextpkt = NULL;
1735 0 : mb.m_type = 0;
1736 0 : mb.m_flags = 0;
1737 0 : bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
1738 0 : }
1739 : #endif
1740 : /* trim FCS */
1741 0 : m_adj(m, -IEEE80211_CRC_LEN);
1742 :
1743 0 : wh = mtod(m, struct ieee80211_frame *);
1744 0 : ni = ieee80211_find_rxnode(ic, wh);
1745 :
1746 : /* push the frame up to the 802.11 stack */
1747 0 : rxi.rxi_flags = 0;
1748 0 : rxi.rxi_rssi = rxdesc->rssi;
1749 0 : rxi.rxi_tstamp = 0; /* unused */
1750 0 : ieee80211_input(ifp, m, ni, &rxi);
1751 :
1752 : /* node is no longer needed */
1753 0 : ieee80211_release_node(ic, ni);
1754 :
1755 0 : splx(s);
1756 :
1757 : DPRINTF(3, "%s: RX done\n", sc->sc_dev.dv_xname);
1758 0 : }
1759 :
1760 : void
1761 0 : upgt_setup_rates(struct upgt_softc *sc)
1762 : {
1763 0 : struct ieee80211com *ic = &sc->sc_ic;
1764 :
1765 : /*
1766 : * 0x01 = OFMD6 0x10 = DS1
1767 : * 0x04 = OFDM9 0x11 = DS2
1768 : * 0x06 = OFDM12 0x12 = DS5
1769 : * 0x07 = OFDM18 0x13 = DS11
1770 : * 0x08 = OFDM24
1771 : * 0x09 = OFDM36
1772 : * 0x0a = OFDM48
1773 : * 0x0b = OFDM54
1774 : */
1775 : const uint8_t rateset_auto_11b[] =
1776 : { 0x13, 0x13, 0x12, 0x11, 0x11, 0x10, 0x10, 0x10 };
1777 : const uint8_t rateset_auto_11g[] =
1778 : { 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x04, 0x01 };
1779 : const uint8_t rateset_fix_11bg[] =
1780 : { 0x10, 0x11, 0x12, 0x13, 0x01, 0x04, 0x06, 0x07,
1781 : 0x08, 0x09, 0x0a, 0x0b };
1782 :
1783 0 : if (ic->ic_fixed_rate == -1) {
1784 : /*
1785 : * Automatic rate control is done by the device.
1786 : * We just pass the rateset from which the device
1787 : * will pickup a rate.
1788 : */
1789 0 : if (ic->ic_curmode == IEEE80211_MODE_11B)
1790 0 : bcopy(rateset_auto_11b, sc->sc_cur_rateset,
1791 : sizeof(sc->sc_cur_rateset));
1792 0 : if (ic->ic_curmode == IEEE80211_MODE_11G ||
1793 0 : ic->ic_curmode == IEEE80211_MODE_AUTO)
1794 0 : bcopy(rateset_auto_11g, sc->sc_cur_rateset,
1795 : sizeof(sc->sc_cur_rateset));
1796 : } else {
1797 : /* set a fixed rate */
1798 0 : memset(sc->sc_cur_rateset, rateset_fix_11bg[ic->ic_fixed_rate],
1799 : sizeof(sc->sc_cur_rateset));
1800 : }
1801 0 : }
1802 :
1803 : uint8_t
1804 0 : upgt_rx_rate(struct upgt_softc *sc, const int rate)
1805 : {
1806 0 : struct ieee80211com *ic = &sc->sc_ic;
1807 :
1808 0 : if (ic->ic_curmode == IEEE80211_MODE_11B) {
1809 0 : if (rate < 0 || rate > 3)
1810 : /* invalid rate */
1811 0 : return (0);
1812 :
1813 0 : switch (rate) {
1814 : case 0:
1815 0 : return (2);
1816 : case 1:
1817 0 : return (4);
1818 : case 2:
1819 0 : return (11);
1820 : case 3:
1821 0 : return (22);
1822 : default:
1823 0 : return (0);
1824 : }
1825 : }
1826 :
1827 0 : if (ic->ic_curmode == IEEE80211_MODE_11G) {
1828 0 : if (rate < 0 || rate > 11)
1829 : /* invalid rate */
1830 0 : return (0);
1831 :
1832 0 : switch (rate) {
1833 : case 0:
1834 0 : return (2);
1835 : case 1:
1836 0 : return (4);
1837 : case 2:
1838 0 : return (11);
1839 : case 3:
1840 0 : return (22);
1841 : case 4:
1842 0 : return (12);
1843 : case 5:
1844 0 : return (18);
1845 : case 6:
1846 0 : return (24);
1847 : case 7:
1848 0 : return (36);
1849 : case 8:
1850 0 : return (48);
1851 : case 9:
1852 0 : return (72);
1853 : case 10:
1854 0 : return (96);
1855 : case 11:
1856 0 : return (108);
1857 : default:
1858 0 : return (0);
1859 : }
1860 : }
1861 :
1862 0 : return (0);
1863 0 : }
1864 :
1865 : int
1866 0 : upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
1867 : {
1868 0 : struct ieee80211com *ic = &sc->sc_ic;
1869 0 : struct ieee80211_node *ni = ic->ic_bss;
1870 0 : struct upgt_data *data_cmd = &sc->cmd_data;
1871 : struct upgt_lmac_mem *mem;
1872 : struct upgt_lmac_filter *filter;
1873 0 : int len;
1874 0 : uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1875 :
1876 : /*
1877 : * Transmit the URB containing the CMD data.
1878 : */
1879 0 : bzero(data_cmd->buf, MCLBYTES);
1880 :
1881 0 : mem = (struct upgt_lmac_mem *)data_cmd->buf;
1882 0 : mem->addr = htole32(sc->sc_memaddr_frame_start +
1883 : UPGT_MEMSIZE_FRAME_HEAD);
1884 :
1885 0 : filter = (struct upgt_lmac_filter *)(mem + 1);
1886 :
1887 0 : filter->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK;
1888 0 : filter->header1.type = UPGT_H1_TYPE_CTRL;
1889 0 : filter->header1.len = htole16(
1890 : sizeof(struct upgt_lmac_filter) -
1891 : sizeof(struct upgt_lmac_header));
1892 :
1893 0 : filter->header2.reqid = htole32(sc->sc_memaddr_frame_start);
1894 0 : filter->header2.type = htole16(UPGT_H2_TYPE_MACFILTER);
1895 0 : filter->header2.flags = 0;
1896 :
1897 0 : switch (state) {
1898 : case IEEE80211_S_INIT:
1899 : DPRINTF(1, "%s: set MAC filter to INIT\n",
1900 : sc->sc_dev.dv_xname);
1901 :
1902 0 : filter->type = htole16(UPGT_FILTER_TYPE_RESET);
1903 0 : break;
1904 : case IEEE80211_S_SCAN:
1905 : DPRINTF(1, "%s: set MAC filter to SCAN (bssid %s)\n",
1906 : sc->sc_dev.dv_xname, ether_sprintf(broadcast));
1907 :
1908 0 : filter->type = htole16(UPGT_FILTER_TYPE_NONE);
1909 0 : IEEE80211_ADDR_COPY(filter->dst, ic->ic_myaddr);
1910 0 : IEEE80211_ADDR_COPY(filter->src, broadcast);
1911 0 : filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
1912 0 : filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
1913 0 : filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2);
1914 0 : filter->rxhw = htole32(sc->sc_eeprom_hwrx);
1915 0 : filter->unknown3 = htole16(UPGT_FILTER_UNKNOWN3);
1916 0 : break;
1917 : case IEEE80211_S_RUN:
1918 : DPRINTF(1, "%s: set MAC filter to RUN (bssid %s)\n",
1919 : sc->sc_dev.dv_xname, ether_sprintf(ni->ni_bssid));
1920 :
1921 0 : filter->type = htole16(UPGT_FILTER_TYPE_STA);
1922 0 : IEEE80211_ADDR_COPY(filter->dst, ic->ic_myaddr);
1923 0 : IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
1924 0 : filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
1925 0 : filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
1926 0 : filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2);
1927 0 : filter->rxhw = htole32(sc->sc_eeprom_hwrx);
1928 0 : filter->unknown3 = htole16(UPGT_FILTER_UNKNOWN3);
1929 0 : break;
1930 : default:
1931 0 : printf("%s: MAC filter does not know that state!\n",
1932 0 : sc->sc_dev.dv_xname);
1933 0 : break;
1934 : }
1935 :
1936 0 : len = sizeof(*mem) + sizeof(*filter);
1937 :
1938 0 : mem->chksum = upgt_chksum_le((uint32_t *)filter,
1939 : len - sizeof(*mem));
1940 :
1941 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
1942 0 : printf("%s: could not transmit macfilter CMD data URB!\n",
1943 0 : sc->sc_dev.dv_xname);
1944 0 : return (EIO);
1945 : }
1946 :
1947 0 : return (0);
1948 0 : }
1949 :
1950 : int
1951 0 : upgt_set_channel(struct upgt_softc *sc, unsigned channel)
1952 : {
1953 0 : struct upgt_data *data_cmd = &sc->cmd_data;
1954 : struct upgt_lmac_mem *mem;
1955 : struct upgt_lmac_channel *chan;
1956 0 : int len;
1957 :
1958 : DPRINTF(1, "%s: %s: %d\n", sc->sc_dev.dv_xname, __func__, channel);
1959 :
1960 : /*
1961 : * Transmit the URB containing the CMD data.
1962 : */
1963 0 : bzero(data_cmd->buf, MCLBYTES);
1964 :
1965 0 : mem = (struct upgt_lmac_mem *)data_cmd->buf;
1966 0 : mem->addr = htole32(sc->sc_memaddr_frame_start +
1967 : UPGT_MEMSIZE_FRAME_HEAD);
1968 :
1969 0 : chan = (struct upgt_lmac_channel *)(mem + 1);
1970 :
1971 0 : chan->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK;
1972 0 : chan->header1.type = UPGT_H1_TYPE_CTRL;
1973 0 : chan->header1.len = htole16(
1974 : sizeof(struct upgt_lmac_channel) -
1975 : sizeof(struct upgt_lmac_header));
1976 :
1977 0 : chan->header2.reqid = htole32(sc->sc_memaddr_frame_start);
1978 0 : chan->header2.type = htole16(UPGT_H2_TYPE_CHANNEL);
1979 0 : chan->header2.flags = 0;
1980 :
1981 0 : chan->unknown1 = htole16(UPGT_CHANNEL_UNKNOWN1);
1982 0 : chan->unknown2 = htole16(UPGT_CHANNEL_UNKNOWN2);
1983 0 : chan->freq6 = sc->sc_eeprom_freq6[channel];
1984 0 : chan->settings = sc->sc_eeprom_freq6_settings;
1985 0 : chan->unknown3 = UPGT_CHANNEL_UNKNOWN3;
1986 :
1987 0 : bcopy(&sc->sc_eeprom_freq3[channel].data, chan->freq3_1,
1988 : sizeof(chan->freq3_1));
1989 :
1990 0 : bcopy(&sc->sc_eeprom_freq4[channel], chan->freq4,
1991 : sizeof(sc->sc_eeprom_freq4[channel]));
1992 :
1993 0 : bcopy(&sc->sc_eeprom_freq3[channel].data, chan->freq3_2,
1994 : sizeof(chan->freq3_2));
1995 :
1996 0 : len = sizeof(*mem) + sizeof(*chan);
1997 :
1998 0 : mem->chksum = upgt_chksum_le((uint32_t *)chan,
1999 : len - sizeof(*mem));
2000 :
2001 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
2002 0 : printf("%s: could not transmit channel CMD data URB!\n",
2003 0 : sc->sc_dev.dv_xname);
2004 0 : return (EIO);
2005 : }
2006 :
2007 0 : return (0);
2008 0 : }
2009 :
2010 : void
2011 0 : upgt_set_led(struct upgt_softc *sc, int action)
2012 : {
2013 0 : struct ieee80211com *ic = &sc->sc_ic;
2014 0 : struct upgt_data *data_cmd = &sc->cmd_data;
2015 : struct upgt_lmac_mem *mem;
2016 : struct upgt_lmac_led *led;
2017 0 : struct timeval t;
2018 0 : int len;
2019 :
2020 : /*
2021 : * Transmit the URB containing the CMD data.
2022 : */
2023 0 : bzero(data_cmd->buf, MCLBYTES);
2024 :
2025 0 : mem = (struct upgt_lmac_mem *)data_cmd->buf;
2026 0 : mem->addr = htole32(sc->sc_memaddr_frame_start +
2027 : UPGT_MEMSIZE_FRAME_HEAD);
2028 :
2029 0 : led = (struct upgt_lmac_led *)(mem + 1);
2030 :
2031 0 : led->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK;
2032 0 : led->header1.type = UPGT_H1_TYPE_CTRL;
2033 0 : led->header1.len = htole16(
2034 : sizeof(struct upgt_lmac_led) -
2035 : sizeof(struct upgt_lmac_header));
2036 :
2037 0 : led->header2.reqid = htole32(sc->sc_memaddr_frame_start);
2038 0 : led->header2.type = htole16(UPGT_H2_TYPE_LED);
2039 0 : led->header2.flags = 0;
2040 :
2041 0 : switch (action) {
2042 : case UPGT_LED_OFF:
2043 0 : led->mode = htole16(UPGT_LED_MODE_SET);
2044 0 : led->action_fix = 0;
2045 0 : led->action_tmp = htole16(UPGT_LED_ACTION_OFF);
2046 0 : led->action_tmp_dur = 0;
2047 0 : break;
2048 : case UPGT_LED_ON:
2049 0 : led->mode = htole16(UPGT_LED_MODE_SET);
2050 0 : led->action_fix = 0;
2051 0 : led->action_tmp = htole16(UPGT_LED_ACTION_ON);
2052 0 : led->action_tmp_dur = 0;
2053 0 : break;
2054 : case UPGT_LED_BLINK:
2055 0 : if (ic->ic_state != IEEE80211_S_RUN)
2056 0 : return;
2057 0 : if (sc->sc_led_blink)
2058 : /* previous blink was not finished */
2059 0 : return;
2060 0 : led->mode = htole16(UPGT_LED_MODE_SET);
2061 0 : led->action_fix = htole16(UPGT_LED_ACTION_OFF);
2062 0 : led->action_tmp = htole16(UPGT_LED_ACTION_ON);
2063 0 : led->action_tmp_dur = htole16(UPGT_LED_ACTION_TMP_DUR);
2064 : /* lock blink */
2065 0 : sc->sc_led_blink = 1;
2066 0 : t.tv_sec = 0;
2067 0 : t.tv_usec = UPGT_LED_ACTION_TMP_DUR * 1000L;
2068 0 : timeout_add(&sc->led_to, tvtohz(&t));
2069 0 : break;
2070 : default:
2071 0 : return;
2072 : }
2073 :
2074 0 : len = sizeof(*mem) + sizeof(*led);
2075 :
2076 0 : mem->chksum = upgt_chksum_le((uint32_t *)led,
2077 : len - sizeof(*mem));
2078 :
2079 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
2080 0 : printf("%s: could not transmit led CMD URB!\n",
2081 0 : sc->sc_dev.dv_xname);
2082 0 : }
2083 0 : }
2084 :
2085 : void
2086 0 : upgt_set_led_blink(void *arg)
2087 : {
2088 0 : struct upgt_softc *sc = arg;
2089 :
2090 : /* blink finished, we are ready for a next one */
2091 0 : sc->sc_led_blink = 0;
2092 0 : timeout_del(&sc->led_to);
2093 0 : }
2094 :
2095 : int
2096 0 : upgt_get_stats(struct upgt_softc *sc)
2097 : {
2098 0 : struct upgt_data *data_cmd = &sc->cmd_data;
2099 : struct upgt_lmac_mem *mem;
2100 : struct upgt_lmac_stats *stats;
2101 0 : int len;
2102 :
2103 : /*
2104 : * Transmit the URB containing the CMD data.
2105 : */
2106 0 : bzero(data_cmd->buf, MCLBYTES);
2107 :
2108 0 : mem = (struct upgt_lmac_mem *)data_cmd->buf;
2109 0 : mem->addr = htole32(sc->sc_memaddr_frame_start +
2110 : UPGT_MEMSIZE_FRAME_HEAD);
2111 :
2112 0 : stats = (struct upgt_lmac_stats *)(mem + 1);
2113 :
2114 0 : stats->header1.flags = 0;
2115 0 : stats->header1.type = UPGT_H1_TYPE_CTRL;
2116 0 : stats->header1.len = htole16(
2117 : sizeof(struct upgt_lmac_stats) -
2118 : sizeof(struct upgt_lmac_header));
2119 :
2120 0 : stats->header2.reqid = htole32(sc->sc_memaddr_frame_start);
2121 0 : stats->header2.type = htole16(UPGT_H2_TYPE_STATS);
2122 0 : stats->header2.flags = 0;
2123 :
2124 0 : len = sizeof(*mem) + sizeof(*stats);
2125 :
2126 0 : mem->chksum = upgt_chksum_le((uint32_t *)stats,
2127 : len - sizeof(*mem));
2128 :
2129 0 : if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
2130 0 : printf("%s: could not transmit statistics CMD data URB!\n",
2131 0 : sc->sc_dev.dv_xname);
2132 0 : return (EIO);
2133 : }
2134 :
2135 0 : return (0);
2136 :
2137 0 : }
2138 :
2139 : int
2140 0 : upgt_alloc_tx(struct upgt_softc *sc)
2141 : {
2142 : int i;
2143 :
2144 0 : sc->tx_queued = 0;
2145 :
2146 0 : for (i = 0; i < UPGT_TX_COUNT; i++) {
2147 0 : struct upgt_data *data_tx = &sc->tx_data[i];
2148 :
2149 0 : data_tx->sc = sc;
2150 :
2151 0 : data_tx->xfer = usbd_alloc_xfer(sc->sc_udev);
2152 0 : if (data_tx->xfer == NULL) {
2153 0 : printf("%s: could not allocate TX xfer!\n",
2154 0 : sc->sc_dev.dv_xname);
2155 0 : return (ENOMEM);
2156 : }
2157 :
2158 0 : data_tx->buf = usbd_alloc_buffer(data_tx->xfer, MCLBYTES);
2159 0 : if (data_tx->buf == NULL) {
2160 0 : printf("%s: could not allocate TX buffer!\n",
2161 0 : sc->sc_dev.dv_xname);
2162 0 : return (ENOMEM);
2163 : }
2164 :
2165 0 : bzero(data_tx->buf, MCLBYTES);
2166 0 : }
2167 :
2168 0 : return (0);
2169 0 : }
2170 :
2171 : int
2172 0 : upgt_alloc_rx(struct upgt_softc *sc)
2173 : {
2174 0 : struct upgt_data *data_rx = &sc->rx_data;
2175 :
2176 0 : data_rx->sc = sc;
2177 :
2178 0 : data_rx->xfer = usbd_alloc_xfer(sc->sc_udev);
2179 0 : if (data_rx->xfer == NULL) {
2180 0 : printf("%s: could not allocate RX xfer!\n",
2181 0 : sc->sc_dev.dv_xname);
2182 0 : return (ENOMEM);
2183 : }
2184 :
2185 0 : data_rx->buf = usbd_alloc_buffer(data_rx->xfer, MCLBYTES);
2186 0 : if (data_rx->buf == NULL) {
2187 0 : printf("%s: could not allocate RX buffer!\n",
2188 0 : sc->sc_dev.dv_xname);
2189 0 : return (ENOMEM);
2190 : }
2191 :
2192 0 : bzero(data_rx->buf, MCLBYTES);
2193 :
2194 0 : return (0);
2195 0 : }
2196 :
2197 : int
2198 0 : upgt_alloc_cmd(struct upgt_softc *sc)
2199 : {
2200 0 : struct upgt_data *data_cmd = &sc->cmd_data;
2201 :
2202 0 : data_cmd->sc = sc;
2203 :
2204 0 : data_cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
2205 0 : if (data_cmd->xfer == NULL) {
2206 0 : printf("%s: could not allocate RX xfer!\n",
2207 0 : sc->sc_dev.dv_xname);
2208 0 : return (ENOMEM);
2209 : }
2210 :
2211 0 : data_cmd->buf = usbd_alloc_buffer(data_cmd->xfer, MCLBYTES);
2212 0 : if (data_cmd->buf == NULL) {
2213 0 : printf("%s: could not allocate RX buffer!\n",
2214 0 : sc->sc_dev.dv_xname);
2215 0 : return (ENOMEM);
2216 : }
2217 :
2218 0 : bzero(data_cmd->buf, MCLBYTES);
2219 :
2220 0 : return (0);
2221 0 : }
2222 :
2223 : void
2224 0 : upgt_free_tx(struct upgt_softc *sc)
2225 : {
2226 : int i;
2227 :
2228 0 : for (i = 0; i < UPGT_TX_COUNT; i++) {
2229 0 : struct upgt_data *data_tx = &sc->tx_data[i];
2230 :
2231 0 : if (data_tx->xfer != NULL) {
2232 0 : usbd_free_xfer(data_tx->xfer);
2233 0 : data_tx->xfer = NULL;
2234 0 : }
2235 :
2236 0 : data_tx->ni = NULL;
2237 : }
2238 0 : }
2239 :
2240 : void
2241 0 : upgt_free_rx(struct upgt_softc *sc)
2242 : {
2243 0 : struct upgt_data *data_rx = &sc->rx_data;
2244 :
2245 0 : if (data_rx->xfer != NULL) {
2246 0 : usbd_free_xfer(data_rx->xfer);
2247 0 : data_rx->xfer = NULL;
2248 0 : }
2249 :
2250 0 : data_rx->ni = NULL;
2251 0 : }
2252 :
2253 : void
2254 0 : upgt_free_cmd(struct upgt_softc *sc)
2255 : {
2256 0 : struct upgt_data *data_cmd = &sc->cmd_data;
2257 :
2258 0 : if (data_cmd->xfer != NULL) {
2259 0 : usbd_free_xfer(data_cmd->xfer);
2260 0 : data_cmd->xfer = NULL;
2261 0 : }
2262 0 : }
2263 :
2264 : int
2265 0 : upgt_bulk_xmit(struct upgt_softc *sc, struct upgt_data *data,
2266 : struct usbd_pipe *pipeh, uint32_t *size, int flags)
2267 : {
2268 : usbd_status status;
2269 :
2270 0 : usbd_setup_xfer(data->xfer, pipeh, 0, data->buf, *size,
2271 0 : USBD_NO_COPY | USBD_SYNCHRONOUS | flags, UPGT_USB_TIMEOUT, NULL);
2272 0 : status = usbd_transfer(data->xfer);
2273 0 : if (status != USBD_NORMAL_COMPLETION) {
2274 0 : printf("%s: %s: error %s!\n",
2275 0 : sc->sc_dev.dv_xname, __func__, usbd_errstr(status));
2276 0 : return (EIO);
2277 : }
2278 :
2279 0 : return (0);
2280 0 : }
2281 :
2282 : void
2283 0 : upgt_hexdump(void *buf, int len)
2284 : {
2285 : int i;
2286 :
2287 0 : for (i = 0; i < len; i++) {
2288 0 : if (i % 16 == 0)
2289 0 : printf("%s%5i:", i ? "\n" : "", i);
2290 0 : if (i % 4 == 0)
2291 0 : printf(" ");
2292 0 : printf("%02x", (int)*((u_char *)buf + i));
2293 : }
2294 0 : printf("\n");
2295 0 : }
2296 :
2297 : uint32_t
2298 0 : upgt_crc32_le(const void *buf, size_t size)
2299 : {
2300 : uint32_t crc;
2301 :
2302 0 : crc = ether_crc32_le(buf, size);
2303 :
2304 : /* apply final XOR value as common for CRC-32 */
2305 0 : crc = htole32(crc ^ 0xffffffffU);
2306 :
2307 0 : return (crc);
2308 : }
2309 :
2310 : /*
2311 : * The firmware awaits a checksum for each frame we send to it.
2312 : * The algorithm used therefor is uncommon but somehow similar to CRC32.
2313 : */
2314 : uint32_t
2315 0 : upgt_chksum_le(const uint32_t *buf, size_t size)
2316 : {
2317 : int i;
2318 : uint32_t crc = 0;
2319 :
2320 0 : for (i = 0; i < size; i += sizeof(uint32_t)) {
2321 0 : crc = htole32(crc ^ *buf++);
2322 0 : crc = htole32((crc >> 5) ^ (crc << 3));
2323 : }
2324 :
2325 0 : return (crc);
2326 : }
|