Annotation of sys/dev/usb/if_atu.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_atu.c,v 1.86 2007/07/18 18:10:31 damien Exp $ */
2: /*
3: * Copyright (c) 2003, 2004
4: * Daan Vreeken <Danovitsch@Vitsch.net>. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by Daan Vreeken.
17: * 4. Neither the name of the author nor the names of any co-contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY Daan Vreeken AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL Daan Vreeken OR THE VOICES IN HIS HEAD
25: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31: * THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * Atmel AT76c503 / AT76c503a / AT76c505 / AT76c505a USB WLAN driver
36: * version 0.5 - 2004-08-03
37: *
38: * Originally written by Daan Vreeken <Danovitsch @ Vitsch . net>
39: * http://vitsch.net/bsd/atuwi
40: *
41: * Contributed to by :
42: * Chris Whitehouse, Alistair Phillips, Peter Pilka, Martijn van Buul,
43: * Suihong Liang, Arjan van Leeuwen, Stuart Walsh
44: *
45: * Ported to OpenBSD by Theo de Raadt and David Gwynne.
46: */
47:
48: #include "bpfilter.h"
49:
50: #include <sys/param.h>
51: #include <sys/sockio.h>
52: #include <sys/mbuf.h>
53: #include <sys/kernel.h>
54: #include <sys/socket.h>
55: #include <sys/systm.h>
56: #include <sys/malloc.h>
57: #include <sys/kthread.h>
58: #include <sys/queue.h>
59: #include <sys/device.h>
60:
61: #include <machine/bus.h>
62:
63: #include <dev/usb/usb.h>
64: #include <dev/usb/usbdi.h>
65: #include <dev/usb/usbdi_util.h>
66: #include <dev/usb/usbdivar.h>
67:
68: #include <dev/usb/usbdevs.h>
69:
70: #if NBPFILTER > 0
71: #include <net/bpf.h>
72: #endif
73:
74: #include <net/if.h>
75: #include <net/if_dl.h>
76: #include <net/if_media.h>
77:
78: #ifdef INET
79: #include <netinet/in.h>
80: #include <netinet/if_ether.h>
81: #endif
82:
83: #include <net80211/ieee80211_var.h>
84: #include <net80211/ieee80211_radiotap.h>
85:
86: #ifdef USB_DEBUG
87: #define ATU_DEBUG
88: #endif
89:
90: #include <dev/usb/if_atureg.h>
91:
92: #ifdef ATU_DEBUG
93: #define DPRINTF(x) do { if (atudebug) printf x; } while (0)
94: #define DPRINTFN(n,x) do { if (atudebug>(n)) printf x; } while (0)
95: int atudebug = 1;
96: #else
97: #define DPRINTF(x)
98: #define DPRINTFN(n,x)
99: #endif
100:
101: int atu_match(struct device *, void *, void *);
102: void atu_attach(struct device *, struct device *, void *);
103: int atu_detach(struct device *, int);
104: int atu_activate(struct device *, enum devact);
105:
106: struct cfdriver atu_cd = {
107: NULL, "atu", DV_IFNET
108: };
109:
110: const struct cfattach atu_ca = {
111: sizeof(struct atu_softc),
112: atu_match,
113: atu_attach,
114: atu_detach,
115: atu_activate,
116: };
117:
118: /*
119: * Various supported device vendors/products/radio type.
120: */
121: struct atu_type atu_devs[] = {
122: { USB_VENDOR_3COM, USB_PRODUCT_3COM_3CRSHEW696,
123: RadioRFMD, ATU_NO_QUIRK },
124: { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_BWU613,
125: RadioRFMD, ATU_NO_QUIRK },
126: { USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_2664W,
127: AT76C503_rfmd_acc, ATU_NO_QUIRK },
128: { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_AWL300,
129: RadioIntersil, ATU_NO_QUIRK },
130: { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_AWL400,
131: RadioRFMD, ATU_NO_QUIRK },
132: { USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_802UAT1,
133: RadioRFMD, ATU_NO_QUIRK },
134: { USB_VENDOR_ADDTRON, USB_PRODUCT_ADDTRON_AWU120,
135: RadioIntersil, ATU_NO_QUIRK },
136: { USB_VENDOR_AINCOMM, USB_PRODUCT_AINCOMM_AWU2000B,
137: RadioRFMD2958, ATU_NO_QUIRK },
138: { USB_VENDOR_ASKEY, USB_PRODUCT_ASKEY_VOYAGER1010,
139: RadioIntersil, ATU_NO_QUIRK },
140: { USB_VENDOR_ASKEY, USB_PRODUCT_ASKEY_WLL013I,
141: RadioIntersil, ATU_NO_QUIRK },
142: { USB_VENDOR_ASKEY, USB_PRODUCT_ASKEY_WLL013,
143: RadioRFMD, ATU_NO_QUIRK },
144: { USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_AT76C503I1,
145: RadioIntersil, ATU_NO_QUIRK },
146: { USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_AT76C503I2,
147: AT76C503_i3863, ATU_NO_QUIRK },
148: { USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_AT76C503RFMD,
149: RadioRFMD, ATU_NO_QUIRK },
150: { USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_AT76C505RFMD,
151: AT76C505_rfmd, ATU_NO_QUIRK },
152: { USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_AT76C505RFMD2958,
153: RadioRFMD2958, ATU_NO_QUIRK },
154: { USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_AT76C505A, /* SMC2662 V.4 */
155: RadioRFMD2958_SMC, ATU_QUIRK_NO_REMAP | ATU_QUIRK_FW_DELAY },
156: { USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_AT76C505AS, /* quirk? */
157: RadioRFMD2958_SMC, ATU_QUIRK_NO_REMAP | ATU_QUIRK_FW_DELAY },
158: { USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_WN210,
159: RadioRFMD, ATU_NO_QUIRK },
160: { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D6050,
161: RadioRFMD, ATU_NO_QUIRK },
162: { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_C11U,
163: RadioIntersil, ATU_NO_QUIRK },
164: { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_WL210,
165: RadioIntersil, ATU_NO_QUIRK },
166: { USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQWLAN,
167: RadioRFMD, ATU_NO_QUIRK },
168: { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLUSB_11_STICK,
169: RadioRFMD2958, ATU_NO_QUIRK },
170: { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CHUSB611G,
171: RadioRFMD2958, ATU_NO_QUIRK },
172: { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_WL200U,
173: RadioRFMD, ATU_NO_QUIRK },
174: { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_WL240U,
175: RadioRFMD2958, ATU_NO_QUIRK },
176: { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_XH1153,
177: RadioRFMD, ATU_NO_QUIRK },
178: { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWL120E,
179: RadioRFMD, ATU_NO_QUIRK },
180: { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWLBM101,
181: RadioRFMD, ATU_NO_QUIRK },
182: { USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_WLAN, /* quirk? */
183: RadioRFMD2958_SMC, ATU_QUIRK_NO_REMAP | ATU_QUIRK_FW_DELAY },
184: { USB_VENDOR_HP, USB_PRODUCT_HP_HN210W,
185: RadioIntersil, ATU_NO_QUIRK },
186: { USB_VENDOR_INTEL, USB_PRODUCT_INTEL_AP310,
187: RadioIntersil, ATU_NO_QUIRK },
188: { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBWNB11A,
189: RadioIntersil, ATU_NO_QUIRK },
190: { USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_2662WAR,
191: RadioRFMD, ATU_NO_QUIRK },
192: { USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_WUSB11,
193: RadioIntersil, ATU_NO_QUIRK },
194: { USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_WUSB11,
195: RadioRFMD, ATU_NO_QUIRK },
196: { USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_NWU11B,
197: RadioRFMD, ATU_NO_QUIRK },
198: { USB_VENDOR_LINKSYS3, USB_PRODUCT_LINKSYS3_WUSB11V28,
199: RadioRFMD2958, ATU_NO_QUIRK },
200: { USB_VENDOR_MSI, USB_PRODUCT_MSI_WLAN,
201: RadioRFMD2958, ATU_NO_QUIRK },
202: { USB_VENDOR_NETGEAR2, USB_PRODUCT_NETGEAR2_MA101,
203: RadioIntersil, ATU_NO_QUIRK },
204: { USB_VENDOR_NETGEAR2, USB_PRODUCT_NETGEAR2_MA101B,
205: RadioRFMD, ATU_NO_QUIRK },
206: { USB_VENDOR_OQO, USB_PRODUCT_OQO_WIFI01,
207: RadioRFMD2958_SMC, ATU_QUIRK_NO_REMAP | ATU_QUIRK_FW_DELAY },
208: { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GW_US11S,
209: RadioRFMD, ATU_NO_QUIRK },
210: { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_SWL2100W,
211: AT76C503_i3863, ATU_NO_QUIRK },
212: { USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_WLL013,
213: RadioRFMD, ATU_NO_QUIRK },
214: { USB_VENDOR_SMC3, USB_PRODUCT_SMC3_2662WV1,
215: RadioIntersil, ATU_NO_QUIRK },
216: { USB_VENDOR_SMC3, USB_PRODUCT_SMC3_2662WV2,
217: AT76C503_rfmd_acc, ATU_NO_QUIRK },
218: { USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_U300C,
219: RadioIntersil, ATU_NO_QUIRK },
220: { USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_M4Y750,
221: RadioIntersil, ATU_NO_QUIRK },
222: };
223:
224: struct atu_radfirm {
225: enum atu_radio_type atur_type;
226: char *atur_internal;
227: char *atur_external;
228: u_int8_t max_rssi;
229: } atu_radfirm[] = {
230: { RadioRFMD, "atu-rfmd-int", "atu-rfmd-ext", 0 },
231: { RadioRFMD2958, "atu-rfmd2958-int", "atu-rfmd2958-ext", 81 },
232: { RadioRFMD2958_SMC, "atu-rfmd2958smc-int", "atu-rfmd2958smc-ext", 0 },
233: { RadioIntersil, "atu-intersil-int", "atu-intersil-ext", 0 },
234: {
235: AT76C503_i3863,
236: "atu-at76c503-i3863-int",
237: "atu-at76c503-i3863-ext",
238: 0
239: },
240: {
241: AT76C503_rfmd_acc,
242: "atu-at76c503-rfmd-acc-int",
243: "atu-at76c503-rfmd-acc-ext",
244: 0
245: },
246: {
247: AT76C505_rfmd,
248: "atu-at76c505-rfmd-int",
249: "atu-at76c505-rfmd-ext",
250: 0
251: }
252: };
253:
254: int atu_newbuf(struct atu_softc *, struct atu_chain *, struct mbuf *);
255: void atu_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
256: void atu_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
257: void atu_start(struct ifnet *);
258: int atu_ioctl(struct ifnet *, u_long, caddr_t);
259: int atu_init(struct ifnet *);
260: void atu_stop(struct ifnet *, int);
261: void atu_watchdog(struct ifnet *);
262: usbd_status atu_usb_request(struct atu_softc *sc, u_int8_t type,
263: u_int8_t request, u_int16_t value, u_int16_t index,
264: u_int16_t length, u_int8_t *data);
265: int atu_send_command(struct atu_softc *sc, u_int8_t *command, int size);
266: int atu_get_cmd_status(struct atu_softc *sc, u_int8_t cmd,
267: u_int8_t *status);
268: int atu_wait_completion(struct atu_softc *sc, u_int8_t cmd,
269: u_int8_t *status);
270: int atu_send_mib(struct atu_softc *sc, u_int8_t type,
271: u_int8_t size, u_int8_t index, void *data);
272: int atu_get_mib(struct atu_softc *sc, u_int8_t type,
273: u_int8_t size, u_int8_t index, u_int8_t *buf);
274: #if 0
275: int atu_start_ibss(struct atu_softc *sc);
276: #endif
277: int atu_start_scan(struct atu_softc *sc);
278: int atu_switch_radio(struct atu_softc *sc, int state);
279: int atu_initial_config(struct atu_softc *sc);
280: int atu_join(struct atu_softc *sc, struct ieee80211_node *node);
281: int8_t atu_get_dfu_state(struct atu_softc *sc);
282: u_int8_t atu_get_opmode(struct atu_softc *sc, u_int8_t *mode);
283: void atu_internal_firmware(void *);
284: void atu_external_firmware(void *);
285: int atu_get_card_config(struct atu_softc *sc);
286: int atu_media_change(struct ifnet *ifp);
287: void atu_media_status(struct ifnet *ifp, struct ifmediareq *req);
288: int atu_tx_list_init(struct atu_softc *);
289: int atu_rx_list_init(struct atu_softc *);
290: void atu_xfer_list_free(struct atu_softc *sc, struct atu_chain *ch,
291: int listlen);
292:
293: void atu_task(void *);
294: int atu_newstate(struct ieee80211com *, enum ieee80211_state, int);
295: int atu_tx_start(struct atu_softc *, struct ieee80211_node *,
296: struct atu_chain *, struct mbuf *);
297: void atu_complete_attach(struct atu_softc *);
298: u_int8_t atu_calculate_padding(int);
299:
300: usbd_status
301: atu_usb_request(struct atu_softc *sc, u_int8_t type,
302: u_int8_t request, u_int16_t value, u_int16_t index, u_int16_t length,
303: u_int8_t *data)
304: {
305: usb_device_request_t req;
306: usbd_xfer_handle xfer;
307: usbd_status err;
308: int total_len = 0, s;
309:
310: req.bmRequestType = type;
311: req.bRequest = request;
312: USETW(req.wValue, value);
313: USETW(req.wIndex, index);
314: USETW(req.wLength, length);
315:
316: #ifdef ATU_DEBUG
317: if (atudebug) {
318: if ((data == NULL) || (type & UT_READ)) {
319: DPRINTFN(20, ("%s: req=%02x val=%02x ind=%02x "
320: "len=%02x\n", sc->atu_dev.dv_xname, request,
321: value, index, length));
322: } else {
323: DPRINTFN(20, ("%s: req=%02x val=%02x ind=%02x "
324: "len=%02x [%8D]\n", sc->atu_dev.dv_xname,
325: request, value, index, length, data, " "));
326: }
327: }
328: #endif /* ATU_DEBUG */
329:
330: s = splnet();
331:
332: xfer = usbd_alloc_xfer(sc->atu_udev);
333: usbd_setup_default_xfer(xfer, sc->atu_udev, 0, 500000, &req, data,
334: length, USBD_SHORT_XFER_OK, 0);
335:
336: err = usbd_sync_transfer(xfer);
337:
338: usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
339:
340: #ifdef ATU_DEBUG
341: if (atudebug) {
342: if (type & UT_READ) {
343: DPRINTFN(20, ("%s: transfered 0x%x bytes in\n",
344: sc->atu_dev.dv_xname, total_len));
345: DPRINTFN(20, ("%s: dump [%10D]\n",
346: sc->atu_dev.dv_xname, data, " "));
347: } else {
348: if (total_len != length)
349: DPRINTF(("%s: ARG! wrote only %x bytes\n",
350: sc->atu_dev.dv_xname, total_len));
351: }
352: }
353: #endif /* ATU_DEBUG */
354:
355: usbd_free_xfer(xfer);
356:
357: splx(s);
358: return(err);
359: }
360:
361: int
362: atu_send_command(struct atu_softc *sc, u_int8_t *command, int size)
363: {
364: return atu_usb_request(sc, UT_WRITE_VENDOR_DEVICE, 0x0e, 0x0000,
365: 0x0000, size, command);
366: }
367:
368: int
369: atu_get_cmd_status(struct atu_softc *sc, u_int8_t cmd, u_int8_t *status)
370: {
371: /*
372: * all other drivers (including Windoze) request 40 bytes of status
373: * and get a short-xfer of just 6 bytes. we can save 34 bytes of
374: * buffer if we just request those 6 bytes in the first place :)
375: */
376: /*
377: return atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x22, cmd,
378: 0x0000, 40, status);
379: */
380: return atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x22, cmd,
381: 0x0000, 6, status);
382: }
383:
384: int
385: atu_wait_completion(struct atu_softc *sc, u_int8_t cmd, u_int8_t *status)
386: {
387: int idle_count = 0, err;
388: u_int8_t statusreq[6];
389:
390: DPRINTFN(15, ("%s: wait-completion: cmd=%02x\n",
391: sc->atu_dev.dv_xname, cmd));
392:
393: while (1) {
394: err = atu_get_cmd_status(sc, cmd, statusreq);
395: if (err)
396: return err;
397:
398: #ifdef ATU_DEBUG
399: if (atudebug) {
400: DPRINTFN(20, ("%s: status=%s cmd=%02x\n",
401: sc->atu_dev.dv_xname,
402: ether_sprintf(statusreq), cmd));
403: }
404: #endif /* ATU_DEBUG */
405:
406: /*
407: * during normal operations waiting on STATUS_IDLE
408: * will never happen more than once
409: */
410: if ((statusreq[5] == STATUS_IDLE) && (idle_count++ > 20)) {
411: DPRINTF(("%s: AAARRGGG!!! FIX ME!\n",
412: sc->atu_dev.dv_xname));
413: return 0;
414: }
415:
416: if ((statusreq[5] != STATUS_IN_PROGRESS) &&
417: (statusreq[5] != STATUS_IDLE)) {
418: if (status != NULL)
419: *status = statusreq[5];
420: return 0;
421: }
422: usbd_delay_ms(sc->atu_udev, 25);
423: }
424: }
425:
426: int
427: atu_send_mib(struct atu_softc *sc, u_int8_t type, u_int8_t size,
428: u_int8_t index, void *data)
429: {
430: int err;
431: struct atu_cmd_set_mib request;
432:
433: /*
434: * We don't construct a MIB packet first and then memcpy it into an
435: * Atmel-command-packet, we just construct it the right way at once :)
436: */
437:
438: memset(&request, 0, sizeof(request));
439:
440: request.AtCmd = CMD_SET_MIB;
441: USETW(request.AtSize, size + 4);
442:
443: request.MIBType = type;
444: request.MIBSize = size;
445: request.MIBIndex = index;
446: request.MIBReserved = 0;
447:
448: /*
449: * For 1 and 2 byte requests we assume a direct value,
450: * everything bigger than 2 bytes we assume a pointer to the data
451: */
452: switch (size) {
453: case 0:
454: break;
455: case 1:
456: request.data[0]=(long)data & 0x000000ff;
457: break;
458: case 2:
459: request.data[0]=(long)data & 0x000000ff;
460: request.data[1]=(long)data >> 8;
461: break;
462: default:
463: memcpy(request.data, data, size);
464: break;
465: }
466:
467: err = atu_usb_request(sc, UT_WRITE_VENDOR_DEVICE, 0x0e, 0x0000,
468: 0x0000, size+8, (uByte *)&request);
469: if (err)
470: return (err);
471:
472: DPRINTFN(15, ("%s: sendmib : waitcompletion...\n",
473: sc->atu_dev.dv_xname));
474: return atu_wait_completion(sc, CMD_SET_MIB, NULL);
475: }
476:
477: int
478: atu_get_mib(struct atu_softc *sc, u_int8_t type, u_int8_t size,
479: u_int8_t index, u_int8_t *buf)
480: {
481:
482: /* linux/at76c503.c - 478 */
483: return atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x033,
484: type << 8, index, size, buf);
485: }
486:
487: #if 0
488: int
489: atu_start_ibss(struct atu_softc *sc)
490: {
491: int err;
492: struct atu_cmd_start_ibss Request;
493:
494: Request.Cmd = CMD_START_IBSS;
495: Request.Reserved = 0;
496: Request.Size = sizeof(Request) - 4;
497:
498: memset(Request.BSSID, 0x00, sizeof(Request.BSSID));
499: memset(Request.SSID, 0x00, sizeof(Request.SSID));
500: memcpy(Request.SSID, sc->atu_ssid, sc->atu_ssidlen);
501: Request.SSIDSize = sc->atu_ssidlen;
502: if (sc->atu_desired_channel != IEEE80211_CHAN_ANY)
503: Request.Channel = (u_int8_t)sc->atu_desired_channel;
504: else
505: Request.Channel = ATU_DEFAULT_CHANNEL;
506: Request.BSSType = AD_HOC_MODE;
507: memset(Request.Res, 0x00, sizeof(Request.Res));
508:
509: /* Write config to adapter */
510: err = atu_send_command(sc, (u_int8_t *)&Request, sizeof(Request));
511: if (err) {
512: DPRINTF(("%s: start ibss failed!\n",
513: sc->atu_dev.dv_xname));
514: return err;
515: }
516:
517: /* Wait for the adapter to do its thing */
518: err = atu_wait_completion(sc, CMD_START_IBSS, NULL);
519: if (err) {
520: DPRINTF(("%s: error waiting for start_ibss\n",
521: sc->atu_dev.dv_xname));
522: return err;
523: }
524:
525: /* Get the current BSSID */
526: err = atu_get_mib(sc, MIB_MAC_MGMT__CURRENT_BSSID, sc->atu_bssid);
527: if (err) {
528: DPRINTF(("%s: could not get BSSID!\n",
529: sc->atu_dev.dv_xname));
530: return err;
531: }
532:
533: DPRINTF(("%s: started a new IBSS (BSSID=%s)\n",
534: sc->atu_dev.dv_xname, ether_sprintf(sc->atu_bssid)));
535: return 0;
536: }
537: #endif
538:
539: int
540: atu_start_scan(struct atu_softc *sc)
541: {
542: struct ieee80211com *ic = &sc->sc_ic;
543: struct atu_cmd_do_scan Scan;
544: usbd_status err;
545: int Cnt;
546:
547: memset(&Scan, 0, sizeof(Scan));
548:
549: Scan.Cmd = CMD_START_SCAN;
550: Scan.Reserved = 0;
551: USETW(Scan.Size, sizeof(Scan) - 4);
552:
553: /* use the broadcast BSSID (in active scan) */
554: for (Cnt=0; Cnt<6; Cnt++)
555: Scan.BSSID[Cnt] = 0xff;
556:
557: memcpy(Scan.SSID, ic->ic_des_essid, ic->ic_des_esslen);
558: Scan.SSID_Len = ic->ic_des_esslen;
559:
560: /* default values for scan */
561: Scan.ScanType = ATU_SCAN_ACTIVE;
562: if (sc->atu_desired_channel != IEEE80211_CHAN_ANY)
563: Scan.Channel = (u_int8_t)sc->atu_desired_channel;
564: else
565: Scan.Channel = sc->atu_channel;
566:
567: /* we like scans to be quick :) */
568: /* the time we wait before sending probe's */
569: USETW(Scan.ProbeDelay, 0);
570: /* the time we stay on one channel */
571: USETW(Scan.MinChannelTime, 100);
572: USETW(Scan.MaxChannelTime, 200);
573: /* whether or not we scan all channels */
574: Scan.InternationalScan = 0xc1;
575:
576: #ifdef ATU_DEBUG
577: if (atudebug) {
578: DPRINTFN(20, ("%s: scan cmd len=%02x\n",
579: sc->atu_dev.dv_xname, sizeof(Scan)));
580: DPRINTFN(20, ("%s: scan cmd: %52D\n", sc->atu_dev.dv_xname,
581: (u_int8_t *)&Scan, " "));
582: }
583: #endif /* ATU_DEBUG */
584:
585: /* Write config to adapter */
586: err = atu_send_command(sc, (u_int8_t *)&Scan, sizeof(Scan));
587: if (err)
588: return err;
589:
590: /*
591: * We don't wait for the command to finish... the mgmt-thread will do
592: * that for us
593: */
594: /*
595: err = atu_wait_completion(sc, CMD_START_SCAN, NULL);
596: if (err)
597: return err;
598: */
599: return 0;
600: }
601:
602: int
603: atu_switch_radio(struct atu_softc *sc, int state)
604: {
605: usbd_status err;
606: struct atu_cmd CmdRadio;
607:
608: if (sc->atu_radio == RadioIntersil) {
609: /*
610: * Intersil doesn't seem to need/support switching the radio
611: * on/off
612: */
613: return 0;
614: }
615:
616: memset(&CmdRadio, 0, sizeof(CmdRadio));
617: CmdRadio.Cmd = CMD_RADIO_ON;
618:
619: if (sc->atu_radio_on != state) {
620: if (state == 0)
621: CmdRadio.Cmd = CMD_RADIO_OFF;
622:
623: err = atu_send_command(sc, (u_int8_t *)&CmdRadio,
624: sizeof(CmdRadio));
625: if (err)
626: return err;
627:
628: err = atu_wait_completion(sc, CmdRadio.Cmd, NULL);
629: if (err)
630: return err;
631:
632: DPRINTFN(10, ("%s: radio turned %s\n",
633: sc->atu_dev.dv_xname, state ? "on" : "off"));
634: sc->atu_radio_on = state;
635: }
636: return 0;
637: }
638:
639: int
640: atu_initial_config(struct atu_softc *sc)
641: {
642: struct ieee80211com *ic = &sc->sc_ic;
643: u_int32_t i;
644: usbd_status err;
645: /* u_int8_t rates[4] = {0x82, 0x84, 0x8B, 0x96};*/
646: u_int8_t rates[4] = {0x82, 0x04, 0x0B, 0x16};
647: struct atu_cmd_card_config cmd;
648: u_int8_t reg_domain;
649:
650: DPRINTFN(10, ("%s: sending mac-addr\n", sc->atu_dev.dv_xname));
651: err = atu_send_mib(sc, MIB_MAC_ADDR__ADDR, ic->ic_myaddr);
652: if (err) {
653: DPRINTF(("%s: error setting mac-addr\n",
654: sc->atu_dev.dv_xname));
655: return err;
656: }
657:
658: /*
659: DPRINTF(("%s: sending reg-domain\n", sc->atu_dev.dv_xname));
660: err = atu_send_mib(sc, MIB_PHY__REG_DOMAIN, NR(0x30));
661: if (err) {
662: DPRINTF(("%s: error setting mac-addr\n",
663: sc->atu_dev.dv_xname));
664: return err;
665: }
666: */
667:
668: memset(&cmd, 0, sizeof(cmd));
669: cmd.Cmd = CMD_STARTUP;
670: cmd.Reserved = 0;
671: USETW(cmd.Size, sizeof(cmd) - 4);
672:
673: if (sc->atu_desired_channel != IEEE80211_CHAN_ANY)
674: cmd.Channel = (u_int8_t)sc->atu_desired_channel;
675: else
676: cmd.Channel = sc->atu_channel;
677: cmd.AutoRateFallback = 1;
678: memcpy(cmd.BasicRateSet, rates, 4);
679:
680: /* ShortRetryLimit should be 7 according to 802.11 spec */
681: cmd.ShortRetryLimit = 7;
682: USETW(cmd.RTS_Threshold, 2347);
683: USETW(cmd.FragThreshold, 2346);
684:
685: /* Doesn't seem to work, but we'll set it to 1 anyway */
686: cmd.PromiscuousMode = 1;
687:
688: /* this goes into the beacon we transmit */
689: cmd.PrivacyInvoked = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0;
690:
691: cmd.ExcludeUnencrypted = 0;
692: switch (ic->ic_nw_keys[ic->ic_wep_txkey].k_cipher) {
693: case IEEE80211_CIPHER_WEP40:
694: cmd.EncryptionType = ATU_WEP_40BITS;
695: break;
696: case IEEE80211_CIPHER_WEP104:
697: cmd.EncryptionType = ATU_WEP_104BITS;
698: break;
699: default:
700: cmd.EncryptionType = ATU_WEP_OFF;
701: break;
702: }
703:
704: cmd.WEP_DefaultKeyID = ic->ic_wep_txkey;
705: for (i = 0; i < IEEE80211_WEP_NKID; i++) {
706: memcpy(cmd.WEP_DefaultKey[i], ic->ic_nw_keys[i].k_key,
707: ic->ic_nw_keys[i].k_len);
708: }
709:
710: /* Setting the SSID here doesn't seem to do anything */
711: memcpy(cmd.SSID, ic->ic_des_essid, ic->ic_des_esslen);
712: cmd.SSID_Len = ic->ic_des_esslen;
713:
714: cmd.ShortPreamble = 0;
715: USETW(cmd.BeaconPeriod, 100);
716: /* cmd.BeaconPeriod = 65535; */
717:
718: /*
719: * TODO:
720: * read reg domain MIB_PHY @ 0x17 (1 byte), (reply = 0x30)
721: * we should do something usefull with this info. right now it's just
722: * ignored
723: */
724: err = atu_get_mib(sc, MIB_PHY__REG_DOMAIN, ®_domain);
725: if (err) {
726: DPRINTF(("%s: could not get regdomain!\n",
727: sc->atu_dev.dv_xname));
728: } else {
729: DPRINTF(("%s: we're in reg domain 0x%x according to the "
730: "adapter\n", sc->atu_dev.dv_xname, reg_domain));
731: }
732:
733: #ifdef ATU_DEBUG
734: if (atudebug) {
735: DPRINTFN(20, ("%s: configlen=%02x\n", sc->atu_dev.dv_xname,
736: sizeof(cmd)));
737: DPRINTFN(20, ("%s: configdata= %108D\n",
738: sc->atu_dev.dv_xname, (u_int8_t *)&cmd, " "));
739: }
740: #endif /* ATU_DEBUG */
741:
742: /* Windoze : driver says exclude-unencrypted=1 & encr-type=1 */
743:
744: err = atu_send_command(sc, (u_int8_t *)&cmd, sizeof(cmd));
745: if (err)
746: return err;
747: err = atu_wait_completion(sc, CMD_STARTUP, NULL);
748: if (err)
749: return err;
750:
751: /* Turn on radio now */
752: err = atu_switch_radio(sc, 1);
753: if (err)
754: return err;
755:
756: /* preamble type = short */
757: err = atu_send_mib(sc, MIB_LOCAL__PREAMBLE, NR(PREAMBLE_SHORT));
758: if (err)
759: return err;
760:
761: /* frag = 1536 */
762: err = atu_send_mib(sc, MIB_MAC__FRAG, NR(2346));
763: if (err)
764: return err;
765:
766: /* rts = 1536 */
767: err = atu_send_mib(sc, MIB_MAC__RTS, NR(2347));
768: if (err)
769: return err;
770:
771: /* auto rate fallback = 1 */
772: err = atu_send_mib(sc, MIB_LOCAL__AUTO_RATE_FALLBACK, NR(1));
773: if (err)
774: return err;
775:
776: /* power mode = full on, no power saving */
777: err = atu_send_mib(sc, MIB_MAC_MGMT__POWER_MODE,
778: NR(POWER_MODE_ACTIVE));
779: if (err)
780: return err;
781:
782: DPRINTFN(10, ("%s: completed initial config\n",
783: sc->atu_dev.dv_xname));
784: return 0;
785: }
786:
787: int
788: atu_join(struct atu_softc *sc, struct ieee80211_node *node)
789: {
790: struct atu_cmd_join join;
791: u_int8_t status;
792: usbd_status err;
793:
794: memset(&join, 0, sizeof(join));
795:
796: join.Cmd = CMD_JOIN;
797: join.Reserved = 0x00;
798: USETW(join.Size, sizeof(join) - 4);
799:
800: DPRINTFN(15, ("%s: pre-join sc->atu_bssid=%s\n",
801: sc->atu_dev.dv_xname, ether_sprintf(sc->atu_bssid)));
802: DPRINTFN(15, ("%s: mode=%d\n", sc->atu_dev.dv_xname,
803: sc->atu_mode));
804: memcpy(join.bssid, node->ni_bssid, IEEE80211_ADDR_LEN);
805: memcpy(join.essid, node->ni_essid, node->ni_esslen);
806: join.essid_size = node->ni_esslen;
807: if (node->ni_capinfo & IEEE80211_CAPINFO_IBSS)
808: join.bss_type = AD_HOC_MODE;
809: else
810: join.bss_type = INFRASTRUCTURE_MODE;
811: join.channel = ieee80211_chan2ieee(&sc->sc_ic, node->ni_chan);
812:
813: USETW(join.timeout, ATU_JOIN_TIMEOUT);
814: join.reserved = 0x00;
815:
816: DPRINTFN(10, ("%s: trying to join BSSID=%s\n",
817: sc->atu_dev.dv_xname, ether_sprintf(join.bssid)));
818: err = atu_send_command(sc, (u_int8_t *)&join, sizeof(join));
819: if (err) {
820: DPRINTF(("%s: ERROR trying to join IBSS\n",
821: sc->atu_dev.dv_xname));
822: return err;
823: }
824: err = atu_wait_completion(sc, CMD_JOIN, &status);
825: if (err) {
826: DPRINTF(("%s: error joining BSS!\n",
827: sc->atu_dev.dv_xname));
828: return err;
829: }
830: if (status != STATUS_COMPLETE) {
831: DPRINTF(("%s: error joining... [status=%02x]\n",
832: sc->atu_dev.dv_xname, status));
833: return status;
834: } else {
835: DPRINTFN(10, ("%s: joined BSS\n", sc->atu_dev.dv_xname));
836: }
837: return err;
838: }
839:
840: /*
841: * Get the state of the DFU unit
842: */
843: int8_t
844: atu_get_dfu_state(struct atu_softc *sc)
845: {
846: u_int8_t state;
847:
848: if (atu_usb_request(sc, DFU_GETSTATE, 0, 0, 1, &state))
849: return -1;
850: return state;
851: }
852:
853: /*
854: * Get MAC opmode
855: */
856: u_int8_t
857: atu_get_opmode(struct atu_softc *sc, u_int8_t *mode)
858: {
859:
860: return atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x33, 0x0001,
861: 0x0000, 1, mode);
862: }
863:
864: /*
865: * Upload the internal firmware into the device
866: */
867: void
868: atu_internal_firmware(void *arg)
869: {
870: struct atu_softc *sc = arg;
871: u_char state, *ptr = NULL, *firm = NULL, status[6];
872: int block_size, block = 0, err, i;
873: size_t bytes_left = 0;
874: char *name = "unknown-device";
875:
876: /*
877: * Uploading firmware is done with the DFU (Device Firmware Upgrade)
878: * interface. See "Universal Serial Bus - Device Class Specification
879: * for Device Firmware Upgrade" pdf for details of the protocol.
880: * Maybe this could be moved to a seperate 'firmware driver' once more
881: * device drivers need it... For now we'll just do it here.
882: *
883: * Just for your information, the Atmel's DFU descriptor looks like
884: * this:
885: *
886: * 07 size
887: * 21 type
888: * 01 capabilities : only firmware download, need reset
889: * after download
890: * 13 05 detach timeout : max 1299ms between DFU_DETACH and
891: * reset
892: * 00 04 max bytes of firmware per transaction : 1024
893: */
894:
895: /* Choose the right firmware for the device */
896: for (i = 0; i < sizeof(atu_radfirm)/sizeof(atu_radfirm[0]); i++)
897: if (sc->atu_radio == atu_radfirm[i].atur_type)
898: name = atu_radfirm[i].atur_internal;
899:
900: DPRINTF(("%s: loading firmware %s...\n",
901: sc->atu_dev.dv_xname, name));
902: err = loadfirmware(name, &firm, &bytes_left);
903: if (err != 0) {
904: printf("%s: %s loadfirmware error %d\n",
905: sc->atu_dev.dv_xname, name, err);
906: return;
907: }
908:
909: ptr = firm;
910: state = atu_get_dfu_state(sc);
911:
912: while (block >= 0 && state > 0) {
913: switch (state) {
914: case DFUState_DnLoadSync:
915: /* get DFU status */
916: err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0 , 6,
917: status);
918: if (err) {
919: DPRINTF(("%s: dfu_getstatus failed!\n",
920: sc->atu_dev.dv_xname));
921: free(firm, M_DEVBUF);
922: return;
923: }
924: /* success means state => DnLoadIdle */
925: state = DFUState_DnLoadIdle;
926: continue;
927: break;
928:
929: case DFUState_DFUIdle:
930: case DFUState_DnLoadIdle:
931: if (bytes_left>=DFU_MaxBlockSize)
932: block_size = DFU_MaxBlockSize;
933: else
934: block_size = bytes_left;
935: DPRINTFN(15, ("%s: firmware block %d\n",
936: sc->atu_dev.dv_xname, block));
937:
938: err = atu_usb_request(sc, DFU_DNLOAD, block++, 0,
939: block_size, ptr);
940: if (err) {
941: DPRINTF(("%s: dfu_dnload failed\n",
942: sc->atu_dev.dv_xname));
943: free(firm, M_DEVBUF);
944: return;
945: }
946:
947: ptr += block_size;
948: bytes_left -= block_size;
949: if (block_size == 0)
950: block = -1;
951: break;
952:
953: default:
954: DPRINTFN(20, ("%s: sleeping for a while\n",
955: sc->atu_dev.dv_xname));
956: usbd_delay_ms(sc->atu_udev, 100);
957: break;
958: }
959:
960: state = atu_get_dfu_state(sc);
961: }
962: free(firm, M_DEVBUF);
963:
964: if (state != DFUState_ManifestSync) {
965: DPRINTF(("%s: state != manifestsync... eek!\n",
966: sc->atu_dev.dv_xname));
967: }
968:
969: err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0, 6, status);
970: if (err) {
971: DPRINTF(("%s: dfu_getstatus failed!\n",
972: sc->atu_dev.dv_xname));
973: return;
974: }
975:
976: DPRINTFN(15, ("%s: sending remap\n", sc->atu_dev.dv_xname));
977: err = atu_usb_request(sc, DFU_REMAP, 0, 0, 0, NULL);
978: if ((err) && (!ISSET(sc->atu_quirk, ATU_QUIRK_NO_REMAP))) {
979: DPRINTF(("%s: remap failed!\n", sc->atu_dev.dv_xname));
980: return;
981: }
982:
983: /* after a lot of trying and measuring I found out the device needs
984: * about 56 miliseconds after sending the remap command before
985: * it's ready to communicate again. So we'll wait just a little bit
986: * longer than that to be sure...
987: */
988: usbd_delay_ms(sc->atu_udev, 56+100);
989:
990: printf("%s: reattaching after firmware upload\n",
991: sc->atu_dev.dv_xname);
992: usb_needs_reattach(sc->atu_udev);
993: }
994:
995: void
996: atu_external_firmware(void *arg)
997: {
998: struct atu_softc *sc = arg;
999: u_char *ptr = NULL, *firm = NULL;
1000: int block_size, block = 0, err, i;
1001: size_t bytes_left = 0;
1002: char *name = "unknown-device";
1003:
1004: for (i = 0; i < sizeof(atu_radfirm)/sizeof(atu_radfirm[0]); i++)
1005: if (sc->atu_radio == atu_radfirm[i].atur_type)
1006: name = atu_radfirm[i].atur_external;
1007:
1008: DPRINTF(("%s: loading external firmware %s\n",
1009: sc->atu_dev.dv_xname, name));
1010: err = loadfirmware(name, &firm, &bytes_left);
1011: if (err != 0) {
1012: printf("%s: %s loadfirmware error %d\n",
1013: sc->atu_dev.dv_xname, name, err);
1014: return;
1015: }
1016: ptr = firm;
1017:
1018: while (bytes_left) {
1019: if (bytes_left > 1024)
1020: block_size = 1024;
1021: else
1022: block_size = bytes_left;
1023:
1024: DPRINTFN(15, ("%s: block:%d size:%d\n",
1025: sc->atu_dev.dv_xname, block, block_size));
1026: err = atu_usb_request(sc, UT_WRITE_VENDOR_DEVICE, 0x0e,
1027: 0x0802, block, block_size, ptr);
1028: if (err) {
1029: DPRINTF(("%s: could not load external firmware "
1030: "block\n", sc->atu_dev.dv_xname));
1031: free(firm, M_DEVBUF);
1032: return;
1033: }
1034:
1035: ptr += block_size;
1036: block++;
1037: bytes_left -= block_size;
1038: }
1039: free(firm, M_DEVBUF);
1040:
1041: err = atu_usb_request(sc, UT_WRITE_VENDOR_DEVICE, 0x0e, 0x0802,
1042: block, 0, NULL);
1043: if (err) {
1044: DPRINTF(("%s: could not load last zero-length firmware "
1045: "block\n", sc->atu_dev.dv_xname));
1046: return;
1047: }
1048:
1049: /*
1050: * The SMC2662w V.4 seems to require some time to do its thing with
1051: * the external firmware... 20 ms isn't enough, but 21 ms works 100
1052: * times out of 100 tries. We'll wait a bit longer just to be sure
1053: */
1054: if (sc->atu_quirk & ATU_QUIRK_FW_DELAY)
1055: usbd_delay_ms(sc->atu_udev, 21 + 100);
1056:
1057: DPRINTFN(10, ("%s: external firmware upload done\n",
1058: sc->atu_dev.dv_xname));
1059: /* complete configuration after the firmwares have been uploaded */
1060: atu_complete_attach(sc);
1061: }
1062:
1063: int
1064: atu_get_card_config(struct atu_softc *sc)
1065: {
1066: struct ieee80211com *ic = &sc->sc_ic;
1067: struct atu_rfmd_conf rfmd_conf;
1068: struct atu_intersil_conf intersil_conf;
1069: int err;
1070:
1071: switch (sc->atu_radio) {
1072:
1073: case RadioRFMD:
1074: case RadioRFMD2958:
1075: case RadioRFMD2958_SMC:
1076: case AT76C503_rfmd_acc:
1077: case AT76C505_rfmd:
1078: err = atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x33,
1079: 0x0a02, 0x0000, sizeof(rfmd_conf),
1080: (u_int8_t *)&rfmd_conf);
1081: if (err) {
1082: DPRINTF(("%s: could not get rfmd config!\n",
1083: sc->atu_dev.dv_xname));
1084: return err;
1085: }
1086: memcpy(ic->ic_myaddr, rfmd_conf.MACAddr, IEEE80211_ADDR_LEN);
1087: break;
1088:
1089: case RadioIntersil:
1090: case AT76C503_i3863:
1091: err = atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x33,
1092: 0x0902, 0x0000, sizeof(intersil_conf),
1093: (u_int8_t *)&intersil_conf);
1094: if (err) {
1095: DPRINTF(("%s: could not get intersil config!\n",
1096: sc->atu_dev.dv_xname));
1097: return err;
1098: }
1099: memcpy(ic->ic_myaddr, intersil_conf.MACAddr,
1100: IEEE80211_ADDR_LEN);
1101: break;
1102: }
1103: return 0;
1104: }
1105:
1106: /*
1107: * Probe for an AT76c503 chip.
1108: */
1109: int
1110: atu_match(struct device *parent, void *match, void *aux)
1111: {
1112: struct usb_attach_arg *uaa = aux;
1113: int i;
1114:
1115: if (!uaa->iface)
1116: return(UMATCH_NONE);
1117:
1118: for (i = 0; i < sizeof(atu_devs)/sizeof(atu_devs[0]); i++) {
1119: struct atu_type *t = &atu_devs[i];
1120:
1121: if (uaa->vendor == t->atu_vid &&
1122: uaa->product == t->atu_pid) {
1123: return(UMATCH_VENDOR_PRODUCT);
1124: }
1125: }
1126: return(UMATCH_NONE);
1127: }
1128:
1129: int
1130: atu_media_change(struct ifnet *ifp)
1131: {
1132: #ifdef ATU_DEBUG
1133: struct atu_softc *sc = ifp->if_softc;
1134: #endif /* ATU_DEBUG */
1135: int err;
1136:
1137: DPRINTFN(10, ("%s: atu_media_change\n", sc->atu_dev.dv_xname));
1138:
1139: err = ieee80211_media_change(ifp);
1140: if (err == ENETRESET) {
1141: if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
1142: (IFF_RUNNING|IFF_UP))
1143: atu_init(ifp);
1144: err = 0;
1145: }
1146:
1147: return (err);
1148: }
1149:
1150: void
1151: atu_media_status(struct ifnet *ifp, struct ifmediareq *req)
1152: {
1153: #ifdef ATU_DEBUG
1154: struct atu_softc *sc = ifp->if_softc;
1155: #endif /* ATU_DEBUG */
1156:
1157: DPRINTFN(10, ("%s: atu_media_status\n", sc->atu_dev.dv_xname));
1158:
1159: ieee80211_media_status(ifp, req);
1160: }
1161:
1162: void
1163: atu_task(void *arg)
1164: {
1165: struct atu_softc *sc = (struct atu_softc *)arg;
1166: struct ieee80211com *ic = &sc->sc_ic;
1167: struct ifnet *ifp = &ic->ic_if;
1168: usbd_status err;
1169: int s;
1170:
1171: DPRINTFN(10, ("%s: atu_task\n", sc->atu_dev.dv_xname));
1172:
1173: if (sc->sc_state != ATU_S_OK)
1174: return;
1175:
1176: switch (sc->sc_cmd) {
1177: case ATU_C_SCAN:
1178:
1179: err = atu_start_scan(sc);
1180: if (err) {
1181: DPRINTFN(1, ("%s: atu_init: couldn't start scan!\n",
1182: sc->atu_dev.dv_xname));
1183: return;
1184: }
1185:
1186: err = atu_wait_completion(sc, CMD_START_SCAN, NULL);
1187: if (err) {
1188: DPRINTF(("%s: atu_init: error waiting for scan\n",
1189: sc->atu_dev.dv_xname));
1190: return;
1191: }
1192:
1193: DPRINTF(("%s: ==========================> END OF SCAN!\n",
1194: sc->atu_dev.dv_xname));
1195:
1196: s = splnet();
1197: /* ieee80211_next_scan(ifp); */
1198: ieee80211_end_scan(ifp);
1199: splx(s);
1200:
1201: DPRINTF(("%s: ----------------------======> END OF SCAN2!\n",
1202: sc->atu_dev.dv_xname));
1203: break;
1204:
1205: case ATU_C_JOIN:
1206: atu_join(sc, ic->ic_bss);
1207: }
1208: }
1209:
1210: int
1211: atu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1212: {
1213: struct ifnet *ifp = &ic->ic_if;
1214: struct atu_softc *sc = ifp->if_softc;
1215: enum ieee80211_state ostate = ic->ic_state;
1216:
1217: DPRINTFN(10, ("%s: atu_newstate: %s -> %s\n", sc->atu_dev.dv_xname,
1218: ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
1219:
1220: switch (nstate) {
1221: case IEEE80211_S_SCAN:
1222: memcpy(ic->ic_chan_scan, ic->ic_chan_active,
1223: sizeof(ic->ic_chan_active));
1224: ieee80211_free_allnodes(ic);
1225:
1226: /* tell the event thread that we want a scan */
1227: sc->sc_cmd = ATU_C_SCAN;
1228: usb_add_task(sc->atu_udev, &sc->sc_task);
1229:
1230: /* handle this ourselves */
1231: ic->ic_state = nstate;
1232: return (0);
1233:
1234: case IEEE80211_S_AUTH:
1235: case IEEE80211_S_RUN:
1236: if (ostate == IEEE80211_S_SCAN) {
1237: sc->sc_cmd = ATU_C_JOIN;
1238: usb_add_task(sc->atu_udev, &sc->sc_task);
1239: }
1240: break;
1241: default:
1242: /* nothing to do */
1243: break;
1244: }
1245:
1246: return (*sc->sc_newstate)(ic, nstate, arg);
1247: }
1248:
1249: /*
1250: * Attach the interface. Allocate softc structures, do
1251: * setup and ethernet/BPF attach.
1252: */
1253: void
1254: atu_attach(struct device *parent, struct device *self, void *aux)
1255: {
1256: struct atu_softc *sc = (struct atu_softc *)self;
1257: struct usb_attach_arg *uaa = aux;
1258: char *devinfop;
1259: usbd_status err;
1260: usbd_device_handle dev = uaa->device;
1261: u_int8_t mode, channel;
1262: int i;
1263:
1264: sc->sc_state = ATU_S_UNCONFIG;
1265:
1266: devinfop = usbd_devinfo_alloc(dev, 0);
1267: printf("\n%s: %s", sc->atu_dev.dv_xname, devinfop);
1268: usbd_devinfo_free(devinfop);
1269:
1270: err = usbd_set_config_no(dev, ATU_CONFIG_NO, 1);
1271: if (err) {
1272: printf("%s: setting config no failed\n",
1273: sc->atu_dev.dv_xname);
1274: return;
1275: }
1276:
1277: err = usbd_device2interface_handle(dev, ATU_IFACE_IDX, &sc->atu_iface);
1278: if (err) {
1279: printf("%s: getting interface handle failed\n",
1280: sc->atu_dev.dv_xname);
1281: return;
1282: }
1283:
1284: sc->atu_unit = self->dv_unit;
1285: sc->atu_udev = dev;
1286:
1287: /*
1288: * look up the radio_type for the device
1289: * basically does the same as USB_MATCH
1290: */
1291: for (i = 0; i < sizeof(atu_devs)/sizeof(atu_devs[0]); i++) {
1292: struct atu_type *t = &atu_devs[i];
1293:
1294: if (uaa->vendor == t->atu_vid &&
1295: uaa->product == t->atu_pid) {
1296: sc->atu_radio = t->atu_radio;
1297: sc->atu_quirk = t->atu_quirk;
1298: }
1299: }
1300:
1301: /*
1302: * Check in the interface descriptor if we're in DFU mode
1303: * If we're in DFU mode, we upload the external firmware
1304: * If we're not, the PC must have rebooted without power-cycling
1305: * the device.. I've tried this out, a reboot only requeres the
1306: * external firmware to be reloaded :)
1307: *
1308: * Hmm. The at76c505a doesn't report a DFU descriptor when it's
1309: * in DFU mode... Let's just try to get the opmode
1310: */
1311: err = atu_get_opmode(sc, &mode);
1312: DPRINTFN(20, ("%s: opmode: %d\n", sc->atu_dev.dv_xname, mode));
1313: if (err || (mode != MODE_NETCARD && mode != MODE_NOFLASHNETCARD)) {
1314: DPRINTF(("%s: starting internal firmware download\n",
1315: sc->atu_dev.dv_xname));
1316:
1317: printf("\n");
1318:
1319: if (rootvp == NULL)
1320: mountroothook_establish(atu_internal_firmware, sc);
1321: else
1322: atu_internal_firmware(sc);
1323: /*
1324: * atu_internal_firmware will cause a reset of the device
1325: * so we don't want to do any more configuration after this
1326: * point.
1327: */
1328: return;
1329: }
1330:
1331: uaa->iface = sc->atu_iface;
1332:
1333: if (mode != MODE_NETCARD) {
1334: DPRINTFN(15, ("%s: device needs external firmware\n",
1335: sc->atu_dev.dv_xname));
1336:
1337: if (mode != MODE_NOFLASHNETCARD) {
1338: DPRINTF(("%s: EEK! unexpected opmode=%d\n",
1339: sc->atu_dev.dv_xname, mode));
1340: }
1341:
1342: /*
1343: * There is no difference in opmode before and after external
1344: * firmware upload with the SMC2662 V.4 . So instead we'll try
1345: * to read the channel number. If we succeed, external
1346: * firmwaremust have been already uploaded...
1347: */
1348: if (sc->atu_radio != RadioIntersil) {
1349: err = atu_get_mib(sc, MIB_PHY__CHANNEL, &channel);
1350: if (!err) {
1351: DPRINTF(("%s: external firmware has already"
1352: " been downloaded\n",
1353: sc->atu_dev.dv_xname));
1354: atu_complete_attach(sc);
1355: return;
1356: }
1357: }
1358:
1359: if (rootvp == NULL)
1360: mountroothook_establish(atu_external_firmware, sc);
1361: else
1362: atu_external_firmware(sc);
1363:
1364: /*
1365: * atu_external_firmware will call atu_complete_attach after
1366: * it's finished so we can just return.
1367: */
1368: } else {
1369: /* all the firmwares are in place, so complete the attach */
1370: atu_complete_attach(sc);
1371: }
1372: }
1373:
1374: void
1375: atu_complete_attach(struct atu_softc *sc)
1376: {
1377: struct ieee80211com *ic = &sc->sc_ic;
1378: struct ifnet *ifp = &ic->ic_if;
1379: usb_interface_descriptor_t *id;
1380: usb_endpoint_descriptor_t *ed;
1381: usbd_status err;
1382: int i;
1383: #ifdef ATU_DEBUG
1384: struct atu_fw fw;
1385: #endif
1386:
1387: id = usbd_get_interface_descriptor(sc->atu_iface);
1388:
1389: /* Find endpoints. */
1390: for (i = 0; i < id->bNumEndpoints; i++) {
1391: ed = usbd_interface2endpoint_descriptor(sc->atu_iface, i);
1392: if (!ed) {
1393: DPRINTF(("%s: num_endp:%d\n", sc->atu_dev.dv_xname,
1394: sc->atu_iface->idesc->bNumEndpoints));
1395: DPRINTF(("%s: couldn't get ep %d\n",
1396: sc->atu_dev.dv_xname, i));
1397: return;
1398: }
1399: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
1400: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1401: sc->atu_ed[ATU_ENDPT_RX] = ed->bEndpointAddress;
1402: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
1403: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1404: sc->atu_ed[ATU_ENDPT_TX] = ed->bEndpointAddress;
1405: }
1406: }
1407:
1408: /* read device config & get MAC address */
1409: err = atu_get_card_config(sc);
1410: if (err) {
1411: printf("\n%s: could not get card cfg!\n",
1412: sc->atu_dev.dv_xname);
1413: return;
1414: }
1415:
1416: #ifdef ATU_DEBUG
1417: /* DEBUG : try to get firmware version */
1418: err = atu_get_mib(sc, MIB_FW_VERSION, sizeof(fw), 0,
1419: (u_int8_t *)&fw);
1420: if (!err) {
1421: DPRINTFN(15, ("%s: firmware: maj:%d min:%d patch:%d "
1422: "build:%d\n", sc->atu_dev.dv_xname, fw.major, fw.minor,
1423: fw.patch, fw.build));
1424: } else {
1425: DPRINTF(("%s: get firmware version failed\n",
1426: sc->atu_dev.dv_xname));
1427: }
1428: #endif /* ATU_DEBUG */
1429:
1430: /* Show the world our MAC address */
1431: printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
1432:
1433: sc->atu_cdata.atu_tx_inuse = 0;
1434:
1435: bzero(sc->atu_bssid, ETHER_ADDR_LEN);
1436: sc->atu_channel = ATU_DEFAULT_CHANNEL;
1437: sc->atu_desired_channel = IEEE80211_CHAN_ANY;
1438: sc->atu_mode = INFRASTRUCTURE_MODE;
1439:
1440: ic->ic_softc = sc;
1441: ic->ic_phytype = IEEE80211_T_DS;
1442: ic->ic_opmode = IEEE80211_M_STA;
1443: ic->ic_state = IEEE80211_S_INIT;
1444: ic->ic_caps = IEEE80211_C_IBSS | IEEE80211_C_WEP | IEEE80211_C_SCANALL;
1445: ic->ic_max_rssi = atu_radfirm[sc->atu_radio].max_rssi;
1446:
1447: ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
1448:
1449: for (i = 1; i <= 14; i++) {
1450: ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B |
1451: IEEE80211_CHAN_PASSIVE;
1452: ic->ic_channels[i].ic_freq = ieee80211_ieee2mhz(i,
1453: ic->ic_channels[i].ic_flags);
1454: }
1455:
1456: ic->ic_ibss_chan = &ic->ic_channels[0];
1457:
1458: ifp->if_softc = sc;
1459: memcpy(ifp->if_xname, sc->atu_dev.dv_xname, IFNAMSIZ);
1460: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1461: ifp->if_start = atu_start;
1462: ifp->if_ioctl = atu_ioctl;
1463: ifp->if_watchdog = atu_watchdog;
1464: ifp->if_mtu = ATU_DEFAULT_MTU;
1465: IFQ_SET_READY(&ifp->if_snd);
1466:
1467: /* Call MI attach routine. */
1468: if_attach(ifp);
1469: ieee80211_ifattach(ifp);
1470:
1471: sc->sc_newstate = ic->ic_newstate;
1472: ic->ic_newstate = atu_newstate;
1473:
1474: /* setup ifmedia interface */
1475: ieee80211_media_init(ifp, atu_media_change, atu_media_status);
1476:
1477: usb_init_task(&sc->sc_task, atu_task, sc);
1478:
1479: #if NBPFILTER > 0
1480: bpfattach(&sc->sc_radiobpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,
1481: sizeof(struct ieee80211_frame) + 64);
1482:
1483: bzero(&sc->sc_rxtapu, sizeof(sc->sc_rxtapu));
1484: sc->sc_rxtap.rr_ihdr.it_len = sizeof(sc->sc_rxtapu);
1485: sc->sc_rxtap.rr_ihdr.it_present = htole32(ATU_RX_RADIOTAP_PRESENT);
1486:
1487: bzero(&sc->sc_txtapu, sizeof(sc->sc_txtapu));
1488: sc->sc_txtap.rt_ihdr.it_len = sizeof(sc->sc_txtapu);
1489: sc->sc_txtap.rt_ihdr.it_present = htole32(ATU_TX_RADIOTAP_PRESENT);
1490: #endif
1491:
1492: sc->sc_state = ATU_S_OK;
1493: }
1494:
1495: int
1496: atu_detach(struct device *self, int flags)
1497: {
1498: struct atu_softc *sc = (struct atu_softc *)self;
1499: struct ifnet *ifp = &sc->sc_ic.ic_if;
1500:
1501: DPRINTFN(10, ("%s: atu_detach state=%d\n", sc->atu_dev.dv_xname,
1502: sc->sc_state));
1503:
1504: if (sc->sc_state != ATU_S_UNCONFIG) {
1505: atu_stop(ifp, 1);
1506: ieee80211_ifdetach(ifp);
1507: if_detach(ifp);
1508:
1509: if (sc->atu_ep[ATU_ENDPT_TX] != NULL)
1510: usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_TX]);
1511: if (sc->atu_ep[ATU_ENDPT_RX] != NULL)
1512: usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_RX]);
1513:
1514: usb_rem_task(sc->atu_udev, &sc->sc_task);
1515: }
1516:
1517: return(0);
1518: }
1519:
1520: int
1521: atu_activate(struct device *self, enum devact act)
1522: {
1523: struct atu_softc *sc = (struct atu_softc *)self;
1524:
1525: switch (act) {
1526: case DVACT_ACTIVATE:
1527: break;
1528: case DVACT_DEACTIVATE:
1529: if (sc->sc_state != ATU_S_UNCONFIG)
1530: sc->sc_state = ATU_S_DEAD;
1531: break;
1532: }
1533: return (0);
1534: }
1535:
1536: /*
1537: * Initialize an RX descriptor and attach an MBUF cluster.
1538: */
1539: int
1540: atu_newbuf(struct atu_softc *sc, struct atu_chain *c, struct mbuf *m)
1541: {
1542: struct mbuf *m_new = NULL;
1543:
1544: if (m == NULL) {
1545: MGETHDR(m_new, M_DONTWAIT, MT_DATA);
1546: if (m_new == NULL) {
1547: DPRINTF(("%s: no memory for rx list\n",
1548: sc->atu_dev.dv_xname));
1549: return(ENOBUFS);
1550: }
1551:
1552: MCLGET(m_new, M_DONTWAIT);
1553: if (!(m_new->m_flags & M_EXT)) {
1554: DPRINTF(("%s: no memory for rx list\n",
1555: sc->atu_dev.dv_xname));
1556: m_freem(m_new);
1557: return(ENOBUFS);
1558: }
1559: m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
1560: } else {
1561: m_new = m;
1562: m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
1563: m_new->m_data = m_new->m_ext.ext_buf;
1564: }
1565: c->atu_mbuf = m_new;
1566: return(0);
1567: }
1568:
1569: int
1570: atu_rx_list_init(struct atu_softc *sc)
1571: {
1572: struct atu_cdata *cd = &sc->atu_cdata;
1573: struct atu_chain *c;
1574: int i;
1575:
1576: DPRINTFN(15, ("%s: atu_rx_list_init: enter\n",
1577: sc->atu_dev.dv_xname));
1578:
1579: for (i = 0; i < ATU_RX_LIST_CNT; i++) {
1580: c = &cd->atu_rx_chain[i];
1581: c->atu_sc = sc;
1582: c->atu_idx = i;
1583: if (c->atu_xfer == NULL) {
1584: c->atu_xfer = usbd_alloc_xfer(sc->atu_udev);
1585: if (c->atu_xfer == NULL)
1586: return (ENOBUFS);
1587: c->atu_buf = usbd_alloc_buffer(c->atu_xfer,
1588: ATU_RX_BUFSZ);
1589: if (c->atu_buf == NULL) /* XXX free xfer */
1590: return (ENOBUFS);
1591: if (atu_newbuf(sc, c, NULL) == ENOBUFS) /* XXX free? */
1592: return(ENOBUFS);
1593: }
1594: }
1595: return (0);
1596: }
1597:
1598: int
1599: atu_tx_list_init(struct atu_softc *sc)
1600: {
1601: struct atu_cdata *cd = &sc->atu_cdata;
1602: struct atu_chain *c;
1603: int i;
1604:
1605: DPRINTFN(15, ("%s: atu_tx_list_init\n",
1606: sc->atu_dev.dv_xname));
1607:
1608: SLIST_INIT(&cd->atu_tx_free);
1609: sc->atu_cdata.atu_tx_inuse = 0;
1610:
1611: for (i = 0; i < ATU_TX_LIST_CNT; i++) {
1612: c = &cd->atu_tx_chain[i];
1613: c->atu_sc = sc;
1614: c->atu_idx = i;
1615: if (c->atu_xfer == NULL) {
1616: c->atu_xfer = usbd_alloc_xfer(sc->atu_udev);
1617: if (c->atu_xfer == NULL)
1618: return(ENOBUFS);
1619: c->atu_mbuf = NULL;
1620: c->atu_buf = usbd_alloc_buffer(c->atu_xfer,
1621: ATU_TX_BUFSZ);
1622: if (c->atu_buf == NULL)
1623: return(ENOBUFS); /* XXX free xfer */
1624: SLIST_INSERT_HEAD(&cd->atu_tx_free, c, atu_list);
1625: }
1626: }
1627: return(0);
1628: }
1629:
1630: void
1631: atu_xfer_list_free(struct atu_softc *sc, struct atu_chain *ch,
1632: int listlen)
1633: {
1634: int i;
1635:
1636: /* Free resources. */
1637: for (i = 0; i < listlen; i++) {
1638: if (ch[i].atu_buf != NULL)
1639: ch[i].atu_buf = NULL;
1640: if (ch[i].atu_mbuf != NULL) {
1641: m_freem(ch[i].atu_mbuf);
1642: ch[i].atu_mbuf = NULL;
1643: }
1644: if (ch[i].atu_xfer != NULL) {
1645: usbd_free_xfer(ch[i].atu_xfer);
1646: ch[i].atu_xfer = NULL;
1647: }
1648: }
1649: }
1650:
1651: /*
1652: * A frame has been uploaded: pass the resulting mbuf chain up to
1653: * the higher level protocols.
1654: */
1655: void
1656: atu_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1657: {
1658: struct atu_chain *c = (struct atu_chain *)priv;
1659: struct atu_softc *sc = c->atu_sc;
1660: struct ieee80211com *ic = &sc->sc_ic;
1661: struct ifnet *ifp = &ic->ic_if;
1662: struct atu_rx_hdr *h;
1663: struct ieee80211_frame *wh;
1664: struct ieee80211_node *ni;
1665: struct mbuf *m;
1666: u_int32_t len;
1667: int s;
1668:
1669: DPRINTFN(25, ("%s: atu_rxeof\n", sc->atu_dev.dv_xname));
1670:
1671: if (sc->sc_state != ATU_S_OK)
1672: return;
1673:
1674: if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP))
1675: goto done;
1676:
1677: if (status != USBD_NORMAL_COMPLETION) {
1678: DPRINTF(("%s: status != USBD_NORMAL_COMPLETION\n",
1679: sc->atu_dev.dv_xname));
1680: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1681: return;
1682: }
1683: #if 0
1684: if (status == USBD_IOERROR) {
1685: DPRINTF(("%s: rx: EEK! lost device?\n",
1686: sc->atu_dev.dv_xname));
1687:
1688: /*
1689: * My experience with USBD_IOERROR is that trying to
1690: * restart the transfer will always fail and we'll
1691: * keep on looping restarting transfers untill someone
1692: * pulls the plug of the device.
1693: * So we don't restart the transfer, but just let it
1694: * die... If someone knows of a situation where we can
1695: * recover from USBD_IOERROR, let me know.
1696: */
1697: splx(s);
1698: return;
1699: }
1700: #endif /* 0 */
1701:
1702: if (usbd_ratecheck(&sc->atu_rx_notice)) {
1703: DPRINTF(("%s: usb error on rx: %s\n",
1704: sc->atu_dev.dv_xname, usbd_errstr(status)));
1705: }
1706: if (status == USBD_STALLED)
1707: usbd_clear_endpoint_stall_async(
1708: sc->atu_ep[ATU_ENDPT_RX]);
1709: goto done;
1710: }
1711:
1712: usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1713:
1714: if (len <= 1) {
1715: DPRINTF(("%s: atu_rxeof: too short\n",
1716: sc->atu_dev.dv_xname));
1717: goto done;
1718: }
1719:
1720: h = (struct atu_rx_hdr *)c->atu_buf;
1721: len = UGETW(h->length) - 4; /* XXX magic number */
1722:
1723: m = c->atu_mbuf;
1724: memcpy(mtod(m, char *), c->atu_buf + ATU_RX_HDRLEN, len);
1725: m->m_pkthdr.rcvif = ifp;
1726: m->m_pkthdr.len = m->m_len = len;
1727:
1728: wh = mtod(m, struct ieee80211_frame *);
1729: ni = ieee80211_find_rxnode(ic, wh);
1730:
1731: ifp->if_ipackets++;
1732:
1733: s = splnet();
1734:
1735: if (atu_newbuf(sc, c, NULL) == ENOBUFS) {
1736: ifp->if_ierrors++;
1737: goto done1; /* XXX if we can't allocate, why restart it? */
1738: }
1739:
1740: #if NBPFILTER > 0
1741: if (sc->sc_radiobpf != NULL) {
1742: struct mbuf mb;
1743: struct atu_rx_radiotap_header *rr = &sc->sc_rxtap;
1744:
1745: rr->rr_flags = 0;
1746: rr->rr_chan_freq =
1747: htole16(ic->ic_bss->ni_chan->ic_freq);
1748: rr->rr_chan_flags =
1749: htole16(ic->ic_bss->ni_chan->ic_flags);
1750: rr->rr_rssi = h->rssi;
1751: rr->rr_max_rssi = ic->ic_max_rssi;
1752:
1753: mb.m_data = (caddr_t)rr;
1754: mb.m_len = sizeof(sc->sc_txtapu);
1755: mb.m_next = m;
1756: mb.m_nextpkt = NULL;
1757: mb.m_type = 0;
1758: mb.m_flags = 0;
1759: bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_IN);
1760: }
1761: #endif /* NPBFILTER > 0 */
1762:
1763: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1764: /*
1765: * WEP is decrypted by hardware. Clear WEP bit
1766: * header for ieee80211_input().
1767: */
1768: wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
1769: }
1770:
1771: ieee80211_input(ifp, m, ni, h->rssi, UGETDW(h->rx_time));
1772:
1773: ieee80211_release_node(ic, ni);
1774: done1:
1775: splx(s);
1776: done:
1777: /* Setup new transfer. */
1778: usbd_setup_xfer(c->atu_xfer, sc->atu_ep[ATU_ENDPT_RX], c, c->atu_buf,
1779: ATU_RX_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1780: atu_rxeof);
1781: usbd_transfer(c->atu_xfer);
1782: }
1783:
1784: /*
1785: * A frame was downloaded to the chip. It's safe for us to clean up
1786: * the list buffers.
1787: */
1788: void
1789: atu_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1790: {
1791: struct atu_chain *c = (struct atu_chain *)priv;
1792: struct atu_softc *sc = c->atu_sc;
1793: struct ifnet *ifp = &sc->sc_ic.ic_if;
1794: usbd_status err;
1795: int s;
1796:
1797: DPRINTFN(25, ("%s: atu_txeof status=%d\n", sc->atu_dev.dv_xname,
1798: status));
1799:
1800: if (c->atu_mbuf != NULL) {
1801: m_freem(c->atu_mbuf);
1802: c->atu_mbuf = NULL;
1803: }
1804:
1805: if (status != USBD_NORMAL_COMPLETION) {
1806: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1807: return;
1808:
1809: DPRINTF(("%s: usb error on tx: %s\n", sc->atu_dev.dv_xname,
1810: usbd_errstr(status)));
1811: if (status == USBD_STALLED)
1812: usbd_clear_endpoint_stall_async(sc->atu_ep[ATU_ENDPT_TX]);
1813: return;
1814: }
1815:
1816: usbd_get_xfer_status(c->atu_xfer, NULL, NULL, NULL, &err);
1817:
1818: if (err)
1819: ifp->if_oerrors++;
1820: else
1821: ifp->if_opackets++;
1822:
1823: s = splnet();
1824: SLIST_INSERT_HEAD(&sc->atu_cdata.atu_tx_free, c, atu_list);
1825: sc->atu_cdata.atu_tx_inuse--;
1826: if (sc->atu_cdata.atu_tx_inuse == 0)
1827: ifp->if_timer = 0;
1828: ifp->if_flags &= ~IFF_OACTIVE;
1829: splx(s);
1830:
1831: atu_start(ifp);
1832: }
1833:
1834: u_int8_t
1835: atu_calculate_padding(int size)
1836: {
1837: size %= 64;
1838:
1839: if (size < 50)
1840: return (50 - size);
1841: if (size >=61)
1842: return (64 + 50 - size);
1843: return (0);
1844: }
1845:
1846: int
1847: atu_tx_start(struct atu_softc *sc, struct ieee80211_node *ni,
1848: struct atu_chain *c, struct mbuf *m)
1849: {
1850: int len;
1851: struct atu_tx_hdr *h;
1852: usbd_status err;
1853: u_int8_t pad;
1854: #if NBPFILTER > 0
1855: struct ieee80211com *ic = &sc->sc_ic;
1856: #endif
1857:
1858: DPRINTFN(25, ("%s: atu_tx_start\n", sc->atu_dev.dv_xname));
1859:
1860: /* Don't try to send when we're shutting down the driver */
1861: if (sc->sc_state != ATU_S_OK) {
1862: m_freem(m);
1863: return(EIO);
1864: }
1865:
1866: #if NBPFILTER > 0
1867: if (sc->sc_radiobpf != NULL) {
1868: struct mbuf mb;
1869: struct atu_tx_radiotap_header *rt = &sc->sc_txtap;
1870:
1871: rt->rt_flags = 0;
1872: rt->rt_chan_freq =
1873: htole16(ic->ic_bss->ni_chan->ic_freq);
1874: rt->rt_chan_flags =
1875: htole16(ic->ic_bss->ni_chan->ic_flags);
1876:
1877: mb.m_data = (caddr_t)rt;
1878: mb.m_len = sizeof(sc->sc_txtapu);
1879: mb.m_next = m;
1880: mb.m_nextpkt = NULL;
1881: mb.m_type = 0;
1882: mb.m_flags = 0;
1883: bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_OUT);
1884: }
1885: #endif
1886:
1887: /*
1888: * Copy the mbuf data into a contiguous buffer, leaving
1889: * enough room for the atmel headers
1890: */
1891: len = m->m_pkthdr.len;
1892:
1893: m_copydata(m, 0, m->m_pkthdr.len, c->atu_buf + ATU_TX_HDRLEN);
1894:
1895: h = (struct atu_tx_hdr *)c->atu_buf;
1896: memset(h, 0, ATU_TX_HDRLEN);
1897: USETW(h->length, len);
1898: h->tx_rate = 4; /* XXX rate = auto */
1899: len += ATU_TX_HDRLEN;
1900:
1901: pad = atu_calculate_padding(len);
1902: len += pad;
1903: h->padding = pad;
1904:
1905: c->atu_length = len;
1906: c->atu_mbuf = m;
1907:
1908: usbd_setup_xfer(c->atu_xfer, sc->atu_ep[ATU_ENDPT_TX],
1909: c, c->atu_buf, c->atu_length, USBD_NO_COPY, ATU_TX_TIMEOUT,
1910: atu_txeof);
1911:
1912: /* Let's get this thing into the air! */
1913: c->atu_in_xfer = 1;
1914: err = usbd_transfer(c->atu_xfer);
1915: if (err != USBD_IN_PROGRESS) {
1916: DPRINTFN(25, ("%s: atu_tx_start: err=%d\n",
1917: sc->atu_dev.dv_xname, err));
1918: c->atu_mbuf = NULL;
1919: m_freem(m);
1920: return(EIO);
1921: }
1922:
1923: return (0);
1924: }
1925:
1926: void
1927: atu_start(struct ifnet *ifp)
1928: {
1929: struct atu_softc *sc = ifp->if_softc;
1930: struct ieee80211com *ic = &sc->sc_ic;
1931: struct atu_cdata *cd = &sc->atu_cdata;
1932: struct ieee80211_node *ni;
1933: struct ieee80211_frame *wh;
1934: struct atu_chain *c;
1935: struct mbuf *m = NULL;
1936: int s;
1937:
1938: DPRINTFN(25, ("%s: atu_start: enter\n", sc->atu_dev.dv_xname));
1939:
1940: if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP)) {
1941: DPRINTFN(30, ("%s: atu_start: not running or up\n",
1942: sc->atu_dev.dv_xname));
1943: return;
1944: }
1945:
1946: if (ifp->if_flags & IFF_OACTIVE) {
1947: DPRINTFN(30, ("%s: atu_start: IFF_OACTIVE\n",
1948: sc->atu_dev.dv_xname));
1949: return;
1950: }
1951:
1952: for (;;) {
1953: /* grab a TX buffer */
1954: s = splnet();
1955: c = SLIST_FIRST(&cd->atu_tx_free);
1956: if (c != NULL) {
1957: SLIST_REMOVE_HEAD(&cd->atu_tx_free, atu_list);
1958: cd->atu_tx_inuse++;
1959: if (cd->atu_tx_inuse == ATU_TX_LIST_CNT)
1960: ifp->if_flags |= IFF_OACTIVE;
1961: }
1962: splx(s);
1963: if (c == NULL) {
1964: DPRINTFN(10, ("%s: out of tx xfers\n",
1965: sc->atu_dev.dv_xname));
1966: ifp->if_flags |= IFF_OACTIVE;
1967: break;
1968: }
1969:
1970: /*
1971: * Poll the management queue for frames, it has priority over
1972: * normal data frames.
1973: */
1974: IF_DEQUEUE(&ic->ic_mgtq, m);
1975: if (m == NULL) {
1976: DPRINTFN(10, ("%s: atu_start: data packet\n",
1977: sc->atu_dev.dv_xname));
1978: if (ic->ic_state != IEEE80211_S_RUN) {
1979: DPRINTFN(25, ("%s: no data till running\n",
1980: sc->atu_dev.dv_xname));
1981: /* put the xfer back on the list */
1982: s = splnet();
1983: SLIST_INSERT_HEAD(&cd->atu_tx_free, c,
1984: atu_list);
1985: cd->atu_tx_inuse--;
1986: splx(s);
1987: break;
1988: }
1989:
1990: IFQ_DEQUEUE(&ifp->if_snd, m);
1991: if (m == NULL) {
1992: DPRINTFN(25, ("%s: nothing to send\n",
1993: sc->atu_dev.dv_xname));
1994: s = splnet();
1995: SLIST_INSERT_HEAD(&cd->atu_tx_free, c,
1996: atu_list);
1997: cd->atu_tx_inuse--;
1998: splx(s);
1999: break;
2000: }
2001:
2002: #if NBPFILTER > 0
2003: if (ifp->if_bpf)
2004: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
2005: #endif
2006:
2007: m = ieee80211_encap(ifp, m, &ni);
2008: if (m == NULL)
2009: goto bad;
2010: wh = mtod(m, struct ieee80211_frame *);
2011:
2012: #if NBPFILTER > 0
2013: if (ic->ic_rawbpf != NULL)
2014: bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
2015: #endif
2016: } else {
2017: DPRINTFN(25, ("%s: atu_start: mgmt packet\n",
2018: sc->atu_dev.dv_xname));
2019:
2020: /*
2021: * Hack! The referenced node pointer is in the
2022: * rcvif field of the packet header. This is
2023: * placed there by ieee80211_mgmt_output because
2024: * we need to hold the reference with the frame
2025: * and there's no other way (other than packet
2026: * tags which we consider too expensive to use)
2027: * to pass it along.
2028: */
2029: ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
2030: m->m_pkthdr.rcvif = NULL;
2031:
2032: wh = mtod(m, struct ieee80211_frame *);
2033: /* sc->sc_stats.ast_tx_mgmt++; */
2034: }
2035:
2036: if (atu_tx_start(sc, ni, c, m)) {
2037: bad:
2038: s = splnet();
2039: SLIST_INSERT_HEAD(&cd->atu_tx_free, c,
2040: atu_list);
2041: cd->atu_tx_inuse--;
2042: splx(s);
2043: /* ifp_if_oerrors++; */
2044: if (ni != NULL)
2045: ieee80211_release_node(ic, ni);
2046: continue;
2047: }
2048: ifp->if_timer = 5;
2049: }
2050: }
2051:
2052: int
2053: atu_init(struct ifnet *ifp)
2054: {
2055: struct atu_softc *sc = ifp->if_softc;
2056: struct ieee80211com *ic = &sc->sc_ic;
2057: struct atu_chain *c;
2058: usbd_status err;
2059: int i, s;
2060:
2061: s = splnet();
2062:
2063: DPRINTFN(10, ("%s: atu_init\n", sc->atu_dev.dv_xname));
2064:
2065: if (ifp->if_flags & IFF_RUNNING) {
2066: splx(s);
2067: return(0);
2068: }
2069:
2070: /* Init TX ring */
2071: if (atu_tx_list_init(sc))
2072: printf("%s: tx list init failed\n", sc->atu_dev.dv_xname);
2073:
2074: /* Init RX ring */
2075: if (atu_rx_list_init(sc))
2076: printf("%s: rx list init failed\n", sc->atu_dev.dv_xname);
2077:
2078: /* Load the multicast filter. */
2079: /*atu_setmulti(sc); */
2080:
2081: /* Open RX and TX pipes. */
2082: err = usbd_open_pipe(sc->atu_iface, sc->atu_ed[ATU_ENDPT_RX],
2083: USBD_EXCLUSIVE_USE, &sc->atu_ep[ATU_ENDPT_RX]);
2084: if (err) {
2085: DPRINTF(("%s: open rx pipe failed: %s\n",
2086: sc->atu_dev.dv_xname, usbd_errstr(err)));
2087: splx(s);
2088: return(EIO);
2089: }
2090:
2091: err = usbd_open_pipe(sc->atu_iface, sc->atu_ed[ATU_ENDPT_TX],
2092: USBD_EXCLUSIVE_USE, &sc->atu_ep[ATU_ENDPT_TX]);
2093: if (err) {
2094: DPRINTF(("%s: open tx pipe failed: %s\n",
2095: sc->atu_dev.dv_xname, usbd_errstr(err)));
2096: splx(s);
2097: return(EIO);
2098: }
2099:
2100: /* Start up the receive pipe. */
2101: for (i = 0; i < ATU_RX_LIST_CNT; i++) {
2102: c = &sc->atu_cdata.atu_rx_chain[i];
2103:
2104: usbd_setup_xfer(c->atu_xfer, sc->atu_ep[ATU_ENDPT_RX], c,
2105: c->atu_buf, ATU_RX_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
2106: USBD_NO_TIMEOUT, atu_rxeof);
2107: usbd_transfer(c->atu_xfer);
2108: }
2109:
2110: DPRINTFN(10, ("%s: starting up using MAC=%s\n",
2111: sc->atu_dev.dv_xname, ether_sprintf(ic->ic_myaddr)));
2112:
2113: /* Do initial setup */
2114: err = atu_initial_config(sc);
2115: if (err) {
2116: DPRINTF(("%s: initial config failed!\n",
2117: sc->atu_dev.dv_xname));
2118: splx(s);
2119: return(EIO);
2120: }
2121: DPRINTFN(10, ("%s: initialised transceiver\n",
2122: sc->atu_dev.dv_xname));
2123:
2124: /* sc->atu_rxfilt = ATU_RXFILT_UNICAST|ATU_RXFILT_BROADCAST; */
2125:
2126: /* If we want promiscuous mode, set the allframes bit. */
2127: /*
2128: if (ifp->if_flags & IFF_PROMISC)
2129: sc->atu_rxfilt |= ATU_RXFILT_PROMISC;
2130: */
2131:
2132: ifp->if_flags |= IFF_RUNNING;
2133: ifp->if_flags &= ~IFF_OACTIVE;
2134: splx(s);
2135:
2136: /* XXX the following HAS to be replaced */
2137: s = splnet();
2138: err = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2139: if (err)
2140: DPRINTFN(1, ("%s: atu_init: error calling "
2141: "ieee80211_net_state", sc->atu_dev.dv_xname));
2142: splx(s);
2143:
2144: return 0;
2145: }
2146:
2147: int
2148: atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
2149: {
2150: struct atu_softc *sc = ifp->if_softc;
2151: struct ifaddr *ifa;
2152: int err = 0, s;
2153:
2154: s = splnet();
2155: switch (command) {
2156: case SIOCSIFADDR:
2157: DPRINTFN(15, ("%s: SIOCSIFADDR\n", sc->atu_dev.dv_xname));
2158:
2159: ifa = (struct ifaddr *)data;
2160: ifp->if_flags |= IFF_UP;
2161: atu_init(ifp);
2162:
2163: switch (ifa->ifa_addr->sa_family) {
2164: #ifdef INET
2165: case AF_INET:
2166: arp_ifinit(&sc->sc_ic.ic_ac, ifa);
2167: break;
2168: #endif /* INET */
2169: }
2170: break;
2171:
2172: case SIOCSIFFLAGS:
2173: DPRINTFN(15, ("%s: SIOCSIFFLAGS\n", sc->atu_dev.dv_xname));
2174:
2175: if (ifp->if_flags & IFF_UP) {
2176: if (ifp->if_flags & IFF_RUNNING &&
2177: ifp->if_flags & IFF_PROMISC &&
2178: !(sc->atu_if_flags & IFF_PROMISC)) {
2179: /* enable promisc */
2180: #if 0
2181: sc->atu_rxfilt |= ATU_RXFILT_PROMISC;
2182: atu_setword(sc, ATU_CMD_SET_PKT_FILTER,
2183: sc->atu_rxfilt);
2184: #endif
2185: } else if (ifp->if_flags & IFF_RUNNING &&
2186: !(ifp->if_flags & IFF_PROMISC) &&
2187: sc->atu_if_flags & IFF_PROMISC) {
2188: /* disable promisc */
2189: #if 0
2190: sc->atu_rxfilt &= ~ATU_RXFILT_PROMISC;
2191: atu_setword(sc, ATU_CMD_SET_PKT_FILTER,
2192: sc->atu_rxfilt);
2193: #endif
2194: } else if (!(ifp->if_flags & IFF_RUNNING))
2195: atu_init(ifp);
2196:
2197: DPRINTFN(15, ("%s: ioctl calling atu_init()\n",
2198: sc->atu_dev.dv_xname));
2199: atu_init(ifp);
2200: err = atu_switch_radio(sc, 1);
2201: } else {
2202: if (ifp->if_flags & IFF_RUNNING)
2203: atu_stop(ifp, 0);
2204: err = atu_switch_radio(sc, 0);
2205: }
2206: sc->atu_if_flags = ifp->if_flags;
2207: err = 0;
2208: break;
2209:
2210: case SIOCADDMULTI:
2211: DPRINTFN(15, ("%s: SIOCADDMULTI\n", sc->atu_dev.dv_xname));
2212: /* TODO: implement */
2213: err = 0;
2214: break;
2215:
2216: case SIOCDELMULTI:
2217: DPRINTFN(15, ("%s: SIOCDELMULTI\n", sc->atu_dev.dv_xname));
2218: /* TODO: implement */
2219: err = 0;
2220: break;
2221:
2222: default:
2223: DPRINTFN(15, ("%s: ieee80211_ioctl (%lu)\n",
2224: sc->atu_dev.dv_xname, command));
2225: err = ieee80211_ioctl(ifp, command, data);
2226: break;
2227: }
2228:
2229: if (err == ENETRESET) {
2230: if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
2231: (IFF_RUNNING|IFF_UP)) {
2232: DPRINTF(("%s: atu_ioctl(): netreset\n",
2233: sc->atu_dev.dv_xname));
2234: atu_init(ifp);
2235: }
2236: err = 0;
2237: }
2238:
2239: splx(s);
2240: return (err);
2241: }
2242:
2243: void
2244: atu_watchdog(struct ifnet *ifp)
2245: {
2246: struct atu_softc *sc = ifp->if_softc;
2247: struct atu_chain *c;
2248: usbd_status stat;
2249: int cnt, s;
2250:
2251: DPRINTF(("%s: atu_watchdog\n", sc->atu_dev.dv_xname));
2252:
2253: ifp->if_timer = 0;
2254:
2255: if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP))
2256: return;
2257:
2258: if (sc->sc_state != ATU_S_OK)
2259: return;
2260:
2261: sc = ifp->if_softc;
2262: s = splnet();
2263: ifp->if_oerrors++;
2264: DPRINTF(("%s: watchdog timeout\n", sc->atu_dev.dv_xname));
2265:
2266: /*
2267: * TODO:
2268: * we should change this since we have multiple TX transfers...
2269: */
2270: for (cnt = 0; cnt < ATU_TX_LIST_CNT; cnt++) {
2271: c = &sc->atu_cdata.atu_tx_chain[cnt];
2272: if (c->atu_in_xfer) {
2273: usbd_get_xfer_status(c->atu_xfer, NULL, NULL, NULL,
2274: &stat);
2275: atu_txeof(c->atu_xfer, c, stat);
2276: }
2277: }
2278:
2279: if (!IFQ_IS_EMPTY(&ifp->if_snd))
2280: atu_start(ifp);
2281: splx(s);
2282:
2283: ieee80211_watchdog(ifp);
2284: }
2285:
2286: /*
2287: * Stop the adapter and free any mbufs allocated to the
2288: * RX and TX lists.
2289: */
2290: void
2291: atu_stop(struct ifnet *ifp, int disable)
2292: {
2293: struct atu_softc *sc = ifp->if_softc;
2294: struct atu_cdata *cd;
2295: usbd_status err;
2296: int s;
2297:
2298: s = splnet();
2299: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
2300: ifp->if_timer = 0;
2301:
2302: /* Stop transfers. */
2303: if (sc->atu_ep[ATU_ENDPT_RX] != NULL) {
2304: err = usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_RX]);
2305: if (err) {
2306: DPRINTF(("%s: abort rx pipe failed: %s\n",
2307: sc->atu_dev.dv_xname, usbd_errstr(err)));
2308: }
2309: err = usbd_close_pipe(sc->atu_ep[ATU_ENDPT_RX]);
2310: if (err) {
2311: DPRINTF(("%s: close rx pipe failed: %s\n",
2312: sc->atu_dev.dv_xname, usbd_errstr(err)));
2313: }
2314: sc->atu_ep[ATU_ENDPT_RX] = NULL;
2315: }
2316:
2317: if (sc->atu_ep[ATU_ENDPT_TX] != NULL) {
2318: err = usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_TX]);
2319: if (err) {
2320: DPRINTF(("%s: abort tx pipe failed: %s\n",
2321: sc->atu_dev.dv_xname, usbd_errstr(err)));
2322: }
2323: err = usbd_close_pipe(sc->atu_ep[ATU_ENDPT_TX]);
2324: if (err) {
2325: DPRINTF(("%s: close tx pipe failed: %s\n",
2326: sc->atu_dev.dv_xname, usbd_errstr(err)));
2327: }
2328: sc->atu_ep[ATU_ENDPT_TX] = NULL;
2329: }
2330:
2331: /* Free RX/TX/MGMT list resources. */
2332: cd = &sc->atu_cdata;
2333: atu_xfer_list_free(sc, cd->atu_rx_chain, ATU_RX_LIST_CNT);
2334: atu_xfer_list_free(sc, cd->atu_tx_chain, ATU_TX_LIST_CNT);
2335:
2336: /* Let's be nice and turn off the radio before we leave */
2337: atu_switch_radio(sc, 0);
2338:
2339: splx(s);
2340: }
CVSweb