awi.c revision 1.83 1 /* $NetBSD: awi.c,v 1.83 2009/09/15 18:32:00 dyoung Exp $ */
2
3 /*-
4 * Copyright (c) 1999,2000,2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Bill Sommerfeld
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 /*
32 * Driver for AMD 802.11 firmware.
33 * Uses am79c930 chip driver to talk to firmware running on the am79c930.
34 *
35 * More-or-less a generic ethernet-like if driver, with 802.11 gorp added.
36 */
37
38 /*
39 * todo:
40 * - flush tx queue on resynch.
41 * - clear oactive on "down".
42 * - rewrite copy-into-mbuf code
43 * - mgmt state machine gets stuck retransmitting assoc requests.
44 * - multicast filter.
45 * - fix device reset so it's more likely to work
46 * - show status goo through ifmedia.
47 *
48 * more todo:
49 * - deal with more 802.11 frames.
50 * - send reassoc request
51 * - deal with reassoc response
52 * - send/deal with disassociation
53 * - deal with "full" access points (no room for me).
54 * - power save mode
55 *
56 * later:
57 * - SSID preferences
58 * - need ioctls for poking at the MIBs
59 * - implement ad-hoc mode (including bss creation).
60 * - decide when to do "ad hoc" vs. infrastructure mode (IFF_LINK flags?)
61 * (focus on inf. mode since that will be needed for ietf)
62 * - deal with DH vs. FH versions of the card
63 * - deal with faster cards (2mb/s)
64 * - ?WEP goo (mmm, rc4) (it looks not particularly useful).
65 * - ifmedia revision.
66 * - common 802.11 mibish things.
67 * - common 802.11 media layer.
68 */
69
70 /*
71 * Driver for AMD 802.11 PCnetMobile firmware.
72 * Uses am79c930 chip driver to talk to firmware running on the am79c930.
73 *
74 * The initial version of the driver was written by
75 * Bill Sommerfeld <sommerfeld (at) NetBSD.org>.
76 * Then the driver module completely rewritten to support cards with DS phy
77 * and to support adhoc mode by Atsushi Onoe <onoe (at) NetBSD.org>
78 */
79
80 #include <sys/cdefs.h>
81 __KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.83 2009/09/15 18:32:00 dyoung Exp $");
82
83 #include "opt_inet.h"
84 #include "bpfilter.h"
85
86 #include <sys/param.h>
87 #include <sys/systm.h>
88 #include <sys/kernel.h>
89 #include <sys/mbuf.h>
90 #include <sys/malloc.h>
91 #include <sys/proc.h>
92 #include <sys/socket.h>
93 #include <sys/sockio.h>
94 #include <sys/errno.h>
95 #include <sys/endian.h>
96 #include <sys/device.h>
97
98 #include <net/if.h>
99 #include <net/if_dl.h>
100 #include <net/if_ether.h>
101 #include <net/if_media.h>
102 #include <net/if_llc.h>
103
104 #include <net80211/ieee80211_netbsd.h>
105 #include <net80211/ieee80211_var.h>
106
107 #if NBPFILTER > 0
108 #include <net/bpf.h>
109 #endif
110
111 #include <sys/cpu.h>
112 #include <sys/bus.h>
113
114 #include <dev/ic/am79c930reg.h>
115 #include <dev/ic/am79c930var.h>
116 #include <dev/ic/awireg.h>
117 #include <dev/ic/awivar.h>
118
119 static int awi_init(struct ifnet *);
120 static void awi_stop(struct ifnet *, int);
121 static void awi_start(struct ifnet *);
122 static void awi_watchdog(struct ifnet *);
123 static int awi_ioctl(struct ifnet *, u_long, void *);
124 static int awi_media_change(struct ifnet *);
125 static void awi_media_status(struct ifnet *, struct ifmediareq *);
126 static int awi_mode_init(struct awi_softc *);
127 static void awi_rx_int(struct awi_softc *);
128 static void awi_tx_int(struct awi_softc *);
129 static struct mbuf *awi_devget(struct awi_softc *, u_int32_t, u_int16_t);
130 static int awi_hw_init(struct awi_softc *);
131 static int awi_init_mibs(struct awi_softc *);
132 static int awi_mib(struct awi_softc *, u_int8_t, u_int8_t, int);
133 static int awi_cmd(struct awi_softc *, u_int8_t, int);
134 static int awi_cmd_wait(struct awi_softc *);
135 static void awi_cmd_done(struct awi_softc *);
136 static int awi_next_txd(struct awi_softc *, int, u_int32_t *, u_int32_t *);
137 static int awi_lock(struct awi_softc *);
138 static void awi_unlock(struct awi_softc *);
139 static int awi_intr_lock(struct awi_softc *);
140 static void awi_intr_unlock(struct awi_softc *);
141 static int awi_newstate(struct ieee80211com *, enum ieee80211_state, int);
142 static void awi_recv_mgmt(struct ieee80211com *, struct mbuf *,
143 struct ieee80211_node *, int, int, u_int32_t);
144 static int awi_send_mgmt(struct ieee80211com *, struct ieee80211_node *, int,
145 int);
146 static struct mbuf *awi_ether_encap(struct awi_softc *, struct mbuf *);
147 static struct mbuf *awi_ether_modcap(struct awi_softc *, struct mbuf *);
148
149 /* unaligned little endian access */
150 #define LE_READ_2(p) \
151 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8))
152 #define LE_READ_4(p) \
153 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \
154 (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))
155 #define LE_WRITE_2(p, v) \
156 ((((u_int8_t *)(p))[0] = (((u_int32_t)(v) ) & 0xff)), \
157 (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >> 8) & 0xff)))
158 #define LE_WRITE_4(p, v) \
159 ((((u_int8_t *)(p))[0] = (((u_int32_t)(v) ) & 0xff)), \
160 (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >> 8) & 0xff)), \
161 (((u_int8_t *)(p))[2] = (((u_int32_t)(v) >> 16) & 0xff)), \
162 (((u_int8_t *)(p))[3] = (((u_int32_t)(v) >> 24) & 0xff)))
163
164 struct awi_chanset awi_chanset[] = {
165 /* PHY type domain min max def */
166 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_JP, 6, 17, 6 },
167 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_ES, 0, 26, 1 },
168 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_FR, 0, 32, 1 },
169 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_US, 0, 77, 1 },
170 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_CA, 0, 77, 1 },
171 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_EU, 0, 77, 1 },
172 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_JP, 14, 14, 14 },
173 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_ES, 10, 11, 10 },
174 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_FR, 10, 13, 10 },
175 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_US, 1, 11, 3 },
176 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_CA, 1, 11, 3 },
177 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_EU, 1, 13, 3 },
178 { 0, 0, 0, 0, 0 }
179 };
180
181 #ifdef AWI_DEBUG
182 int awi_debug = 0;
183
184 #define DPRINTF(X) if (awi_debug) printf X
185 #define DPRINTF2(X) if (awi_debug > 1) printf X
186 #else
187 #define DPRINTF(X)
188 #define DPRINTF2(X)
189 #endif
190
191 int
192 awi_attach(struct awi_softc *sc)
193 {
194 struct ieee80211com *ic = &sc->sc_ic;
195 struct ifnet *ifp = &sc->sc_if;
196 int s, i, error, nrate;
197 int mword;
198 enum ieee80211_phymode mode;
199
200 s = splnet();
201 sc->sc_busy = 1;
202 sc->sc_attached = 0;
203 sc->sc_substate = AWI_ST_NONE;
204 if ((error = awi_hw_init(sc)) != 0) {
205 sc->sc_invalid = 1;
206 splx(s);
207 return error;
208 }
209 error = awi_init_mibs(sc);
210 if (error != 0) {
211 sc->sc_invalid = 1;
212 splx(s);
213 return error;
214 }
215 ifp->if_softc = sc;
216 ifp->if_flags =
217 #ifdef IFF_NOTRAILERS
218 IFF_NOTRAILERS |
219 #endif
220 IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
221 ifp->if_ioctl = awi_ioctl;
222 ifp->if_start = awi_start;
223 ifp->if_watchdog = awi_watchdog;
224 ifp->if_init = awi_init;
225 ifp->if_stop = awi_stop;
226 IFQ_SET_READY(&ifp->if_snd);
227 memcpy(ifp->if_xname, device_xname(&sc->sc_dev), IFNAMSIZ);
228
229 ic->ic_ifp = ifp;
230 ic->ic_caps = IEEE80211_C_WEP | IEEE80211_C_IBSS | IEEE80211_C_HOSTAP;
231 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
232 ic->ic_phytype = IEEE80211_T_FH;
233 mode = IEEE80211_MODE_FH;
234 } else {
235 ic->ic_phytype = IEEE80211_T_DS;
236 ic->ic_caps |= IEEE80211_C_AHDEMO;
237 mode = IEEE80211_MODE_11B;
238 }
239 ic->ic_opmode = IEEE80211_M_STA;
240 nrate = sc->sc_mib_phy.aSuprt_Data_Rates[1];
241 memcpy(ic->ic_sup_rates[mode].rs_rates,
242 sc->sc_mib_phy.aSuprt_Data_Rates + 2, nrate);
243 ic->ic_sup_rates[mode].rs_nrates = nrate;
244 IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_mib_addr.aMAC_Address);
245
246 printf("%s: IEEE802.11 %s (firmware %s)\n", ifp->if_xname,
247 (ic->ic_phytype == IEEE80211_T_FH) ? "FH" : "DS", sc->sc_banner);
248 printf("%s: 802.11 address: %s\n", ifp->if_xname,
249 ether_sprintf(ic->ic_myaddr));
250
251 if_attach(ifp);
252 ieee80211_ifattach(ic);
253
254 sc->sc_newstate = ic->ic_newstate;
255 ic->ic_newstate = awi_newstate;
256
257 sc->sc_recv_mgmt = ic->ic_recv_mgmt;
258 ic->ic_recv_mgmt = awi_recv_mgmt;
259
260 sc->sc_send_mgmt = ic->ic_send_mgmt;
261 ic->ic_send_mgmt = awi_send_mgmt;
262
263 ieee80211_media_init(ic, awi_media_change, awi_media_status);
264
265 /* Melco compatibility mode. */
266 #define ADD(s, o) ifmedia_add(&ic->ic_media, \
267 IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL)
268 ADD(IFM_AUTO, IFM_FLAG0);
269
270 for (i = 0; i < nrate; i++) {
271 mword = ieee80211_rate2media(ic,
272 ic->ic_sup_rates[mode].rs_rates[i], mode);
273 if (mword == 0)
274 continue;
275 ADD(mword, IFM_FLAG0);
276 }
277 #undef ADD
278
279 if ((sc->sc_sdhook = shutdownhook_establish(awi_shutdown, sc)) == NULL)
280 printf("%s: WARNING: unable to establish shutdown hook\n",
281 ifp->if_xname);
282 if ((sc->sc_powerhook =
283 powerhook_establish(ifp->if_xname, awi_power, sc)) == NULL)
284 printf("%s: WARNING: unable to establish power hook\n",
285 ifp->if_xname);
286 sc->sc_attached = 1;
287 splx(s);
288
289 /* ready to accept ioctl */
290 awi_unlock(sc);
291
292 return 0;
293 }
294
295 int
296 awi_detach(struct awi_softc *sc)
297 {
298 struct ieee80211com *ic = &sc->sc_ic;
299 struct ifnet *ifp = &sc->sc_if;
300 int s;
301
302 if (!sc->sc_attached)
303 return 0;
304
305 s = splnet();
306 sc->sc_invalid = 1;
307 awi_stop(ifp, 1);
308
309 while (sc->sc_sleep_cnt > 0) {
310 wakeup(sc);
311 (void)tsleep(sc, PWAIT, "awidet", 1);
312 }
313 sc->sc_attached = 0;
314 ieee80211_ifdetach(ic);
315 if_detach(ifp);
316 shutdownhook_disestablish(sc->sc_sdhook);
317 powerhook_disestablish(sc->sc_powerhook);
318 splx(s);
319 return 0;
320 }
321
322 int
323 awi_activate(device_t self, enum devact act)
324 {
325 struct awi_softc *sc = (struct awi_softc *)self;
326 struct ifnet *ifp = &sc->sc_if;
327 int s, error = 0;
328
329 s = splnet();
330 switch (act) {
331 case DVACT_ACTIVATE:
332 error = EOPNOTSUPP;
333 break;
334 case DVACT_DEACTIVATE:
335 sc->sc_invalid = 1;
336 if_deactivate(ifp);
337 break;
338 }
339 splx(s);
340 return error;
341 }
342
343 void
344 awi_power(int why, void *arg)
345 {
346 struct awi_softc *sc = arg;
347 struct ifnet *ifp = &sc->sc_if;
348 int s;
349 int ocansleep;
350
351 DPRINTF(("awi_power: %d\n", why));
352 s = splnet();
353 ocansleep = sc->sc_cansleep;
354 sc->sc_cansleep = 0;
355 switch (why) {
356 case PWR_SUSPEND:
357 case PWR_STANDBY:
358 awi_stop(ifp, 1);
359 break;
360 case PWR_RESUME:
361 if (ifp->if_flags & IFF_UP) {
362 awi_init(ifp);
363 (void)awi_intr(sc); /* make sure */
364 }
365 break;
366 case PWR_SOFTSUSPEND:
367 case PWR_SOFTSTANDBY:
368 case PWR_SOFTRESUME:
369 break;
370 }
371 sc->sc_cansleep = ocansleep;
372 splx(s);
373 }
374
375 void
376 awi_shutdown(void *arg)
377 {
378 struct awi_softc *sc = arg;
379 struct ifnet *ifp = &sc->sc_if;
380
381 if (sc->sc_attached)
382 awi_stop(ifp, 1);
383 }
384
385 int
386 awi_intr(void *arg)
387 {
388 struct awi_softc *sc = arg;
389 u_int16_t status;
390 int handled = 0, ocansleep;
391 #ifdef AWI_DEBUG
392 static const char *intname[] = {
393 "CMD", "RX", "TX", "SCAN_CMPLT",
394 "CFP_START", "DTIM", "CFP_ENDING", "GROGGY",
395 "TXDATA", "TXBCAST", "TXPS", "TXCF",
396 "TXMGT", "#13", "RXDATA", "RXMGT"
397 };
398 #endif
399
400 if (!sc->sc_enabled || !sc->sc_enab_intr || sc->sc_invalid) {
401 DPRINTF(("awi_intr: stray interrupt: "
402 "enabled %d enab_intr %d invalid %d\n",
403 sc->sc_enabled, sc->sc_enab_intr, sc->sc_invalid));
404 return 0;
405 }
406
407 am79c930_gcr_setbits(&sc->sc_chip,
408 AM79C930_GCR_DISPWDN | AM79C930_GCR_ECINT);
409 awi_write_1(sc, AWI_DIS_PWRDN, 1);
410 ocansleep = sc->sc_cansleep;
411 sc->sc_cansleep = 0;
412
413 for (;;) {
414 if (awi_intr_lock(sc) != 0)
415 break;
416 status = awi_read_1(sc, AWI_INTSTAT);
417 awi_write_1(sc, AWI_INTSTAT, 0);
418 awi_write_1(sc, AWI_INTSTAT, 0);
419 status |= awi_read_1(sc, AWI_INTSTAT2) << 8;
420 awi_write_1(sc, AWI_INTSTAT2, 0);
421 DELAY(10);
422 awi_intr_unlock(sc);
423 if (!sc->sc_cmd_inprog)
424 status &= ~AWI_INT_CMD; /* make sure */
425 if (status == 0)
426 break;
427 #ifdef AWI_DEBUG
428 if (awi_debug > 1) {
429 int i;
430
431 printf("awi_intr: status 0x%04x", status);
432 for (i = 0; i < sizeof(intname)/sizeof(intname[0]);
433 i++) {
434 if (status & (1 << i))
435 printf(" %s", intname[i]);
436 }
437 printf("\n");
438 }
439 #endif
440 handled = 1;
441 if (status & AWI_INT_RX)
442 awi_rx_int(sc);
443 if (status & AWI_INT_TX)
444 awi_tx_int(sc);
445 if (status & AWI_INT_CMD)
446 awi_cmd_done(sc);
447 if (status & AWI_INT_SCAN_CMPLT) {
448 if (sc->sc_ic.ic_state == IEEE80211_S_SCAN &&
449 sc->sc_substate == AWI_ST_NONE)
450 ieee80211_next_scan(&sc->sc_ic);
451 }
452 }
453 sc->sc_cansleep = ocansleep;
454 am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_DISPWDN);
455 awi_write_1(sc, AWI_DIS_PWRDN, 0);
456 return handled;
457 }
458
459
460 static int
461 awi_init(struct ifnet *ifp)
462 {
463 struct awi_softc *sc = ifp->if_softc;
464 struct ieee80211com *ic = &sc->sc_ic;
465 struct ieee80211_node *ni = ic->ic_bss;
466 struct ieee80211_rateset *rs;
467 int error, rate, i;
468
469 DPRINTF(("awi_init: enabled=%d\n", sc->sc_enabled));
470 if (sc->sc_enabled) {
471 awi_stop(ifp, 0);
472 } else {
473 if (sc->sc_enable)
474 (*sc->sc_enable)(sc);
475 sc->sc_enabled = 1;
476 if ((error = awi_hw_init(sc)) != 0) {
477 if (sc->sc_disable)
478 (*sc->sc_disable)(sc);
479 sc->sc_enabled = 0;
480 return error;
481 }
482 }
483 ic->ic_state = IEEE80211_S_INIT;
484
485 ic->ic_flags &= ~IEEE80211_F_IBSSON;
486 switch (ic->ic_opmode) {
487 case IEEE80211_M_STA:
488 sc->sc_mib_local.Network_Mode = 1;
489 sc->sc_mib_local.Acting_as_AP = 0;
490 break;
491 case IEEE80211_M_IBSS:
492 ic->ic_flags |= IEEE80211_F_IBSSON;
493 /* FALLTHRU */
494 case IEEE80211_M_AHDEMO:
495 sc->sc_mib_local.Network_Mode = 0;
496 sc->sc_mib_local.Acting_as_AP = 0;
497 break;
498 case IEEE80211_M_HOSTAP:
499 sc->sc_mib_local.Network_Mode = 1;
500 sc->sc_mib_local.Acting_as_AP = 1;
501 break;
502 case IEEE80211_M_MONITOR:
503 return ENODEV;
504 }
505 #if 0
506 IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
507 #endif
508 memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
509 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
510 sc->sc_mib_mac.aDesired_ESS_ID[1] = ic->ic_des_esslen;
511 memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], ic->ic_des_essid,
512 ic->ic_des_esslen);
513
514 /* configure basic rate */
515 if (ic->ic_phytype == IEEE80211_T_FH)
516 rs = &ic->ic_sup_rates[IEEE80211_MODE_FH];
517 else
518 rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
519 if (ic->ic_fixed_rate != -1) {
520 rate = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
521 } else {
522 rate = 0;
523 for (i = 0; i < rs->rs_nrates; i++) {
524 if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
525 rate < (rs->rs_rates[i] & IEEE80211_RATE_VAL))
526 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
527 }
528 }
529 rate *= 5;
530 LE_WRITE_2(&sc->sc_mib_mac.aStation_Basic_Rate, rate);
531
532 if ((error = awi_mode_init(sc)) != 0) {
533 DPRINTF(("awi_init: awi_mode_init failed %d\n", error));
534 awi_stop(ifp, 1);
535 return error;
536 }
537
538 /* start transmitter */
539 sc->sc_txdone = sc->sc_txnext = sc->sc_txbase;
540 awi_write_4(sc, sc->sc_txbase + AWI_TXD_START, 0);
541 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NEXT, 0);
542 awi_write_4(sc, sc->sc_txbase + AWI_TXD_LENGTH, 0);
543 awi_write_1(sc, sc->sc_txbase + AWI_TXD_RATE, 0);
544 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NDA, 0);
545 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NRA, 0);
546 awi_write_1(sc, sc->sc_txbase + AWI_TXD_STATE, 0);
547 awi_write_4(sc, AWI_CA_TX_DATA, sc->sc_txbase);
548 awi_write_4(sc, AWI_CA_TX_MGT, 0);
549 awi_write_4(sc, AWI_CA_TX_BCAST, 0);
550 awi_write_4(sc, AWI_CA_TX_PS, 0);
551 awi_write_4(sc, AWI_CA_TX_CF, 0);
552 if ((error = awi_cmd(sc, AWI_CMD_INIT_TX, AWI_WAIT)) != 0) {
553 DPRINTF(("awi_init: failed to start transmitter: %d\n", error));
554 awi_stop(ifp, 1);
555 return error;
556 }
557
558 /* start receiver */
559 if ((error = awi_cmd(sc, AWI_CMD_INIT_RX, AWI_WAIT)) != 0) {
560 DPRINTF(("awi_init: failed to start receiver: %d\n", error));
561 awi_stop(ifp, 1);
562 return error;
563 }
564 sc->sc_rxdoff = awi_read_4(sc, AWI_CA_IRX_DATA_DESC);
565 sc->sc_rxmoff = awi_read_4(sc, AWI_CA_IRX_PS_DESC);
566
567 ifp->if_flags |= IFF_RUNNING;
568 ifp->if_flags &= ~IFF_OACTIVE;
569 ic->ic_state = IEEE80211_S_INIT;
570
571 if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
572 ic->ic_opmode == IEEE80211_M_HOSTAP) {
573 ni->ni_chan = ic->ic_ibss_chan;
574 ni->ni_intval = ic->ic_lintval;
575 ni->ni_rssi = 0;
576 ni->ni_rstamp = 0;
577 memset(&ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
578 ni->ni_rates =
579 ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
580 IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
581 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
582 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
583 ni->ni_esslen = ic->ic_des_esslen;
584 memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
585 ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
586 if (ic->ic_phytype == IEEE80211_T_FH) {
587 ni->ni_fhdwell = 200; /* XXX */
588 ni->ni_fhindex = 1;
589 }
590 } else {
591 ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
592 memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN);
593 ni->ni_esslen = 0;
594 }
595 if (ic->ic_flags & IEEE80211_F_PRIVACY)
596 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
597 if (ic->ic_opmode != IEEE80211_M_AHDEMO)
598 ic->ic_flags |= IEEE80211_F_SIBSS;
599 ic->ic_state = IEEE80211_S_SCAN; /*XXX*/
600 sc->sc_substate = AWI_ST_NONE;
601 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
602 } else {
603 /* XXX check sc->sc_cur_chan */
604 ni->ni_chan = &ic->ic_channels[sc->sc_cur_chan];
605 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
606 }
607 return 0;
608 }
609
610 static void
611 awi_stop(struct ifnet *ifp, int disable)
612 {
613 struct awi_softc *sc = ifp->if_softc;
614
615 if (!sc->sc_enabled)
616 return;
617
618 DPRINTF(("awi_stop(%d)\n", disable));
619
620 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
621
622 if (!sc->sc_invalid) {
623 if (sc->sc_cmd_inprog)
624 (void)awi_cmd_wait(sc);
625 (void)awi_cmd(sc, AWI_CMD_KILL_RX, AWI_WAIT);
626 sc->sc_cmd_inprog = AWI_CMD_FLUSH_TX;
627 awi_write_1(sc, AWI_CA_FTX_DATA, 1);
628 awi_write_1(sc, AWI_CA_FTX_MGT, 0);
629 awi_write_1(sc, AWI_CA_FTX_BCAST, 0);
630 awi_write_1(sc, AWI_CA_FTX_PS, 0);
631 awi_write_1(sc, AWI_CA_FTX_CF, 0);
632 (void)awi_cmd(sc, AWI_CMD_FLUSH_TX, AWI_WAIT);
633 }
634 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
635 ifp->if_timer = 0;
636 sc->sc_tx_timer = sc->sc_rx_timer = 0;
637 if (sc->sc_rxpend != NULL) {
638 m_freem(sc->sc_rxpend);
639 sc->sc_rxpend = NULL;
640 }
641 IFQ_PURGE(&ifp->if_snd);
642
643 if (disable) {
644 if (!sc->sc_invalid)
645 am79c930_gcr_setbits(&sc->sc_chip,
646 AM79C930_GCR_CORESET);
647 if (sc->sc_disable)
648 (*sc->sc_disable)(sc);
649 sc->sc_enabled = 0;
650 }
651 }
652
653 static void
654 awi_start(struct ifnet *ifp)
655 {
656 struct awi_softc *sc = ifp->if_softc;
657 struct ieee80211com *ic = &sc->sc_ic;
658 struct ether_header *eh;
659 struct ieee80211_node *ni;
660 struct ieee80211_frame *wh;
661 struct mbuf *m, *m0;
662 int len, dowep;
663 u_int32_t txd, frame, ntxd;
664 u_int8_t rate;
665
666 if (!sc->sc_enabled || sc->sc_invalid)
667 return;
668
669 for (;;) {
670 txd = sc->sc_txnext;
671 IF_POLL(&ic->ic_mgtq, m0);
672 dowep = 0;
673 if (m0 != NULL) {
674 len = m0->m_pkthdr.len;
675 if (awi_next_txd(sc, len, &frame, &ntxd)) {
676 ifp->if_flags |= IFF_OACTIVE;
677 break;
678 }
679 IF_DEQUEUE(&ic->ic_mgtq, m0);
680 ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
681 } else {
682 if (ic->ic_state != IEEE80211_S_RUN)
683 break;
684 IFQ_POLL(&ifp->if_snd, m0);
685 if (m0 == NULL)
686 break;
687 /*
688 * Need to calculate the real length to determine
689 * if the transmit buffer has a room for the packet.
690 */
691 len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame);
692 if (!(ifp->if_flags & IFF_LINK0) && !sc->sc_adhoc_ap)
693 len += sizeof(struct llc) -
694 sizeof(struct ether_header);
695 if (ic->ic_flags & IEEE80211_F_PRIVACY) {
696 dowep = 1;
697 len += IEEE80211_WEP_IVLEN +
698 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
699 }
700 if (awi_next_txd(sc, len, &frame, &ntxd)) {
701 ifp->if_flags |= IFF_OACTIVE;
702 break;
703 }
704 IFQ_DEQUEUE(&ifp->if_snd, m0);
705 ifp->if_opackets++;
706 #if NBPFILTER > 0
707 if (ifp->if_bpf)
708 bpf_mtap(ifp->if_bpf, m0);
709 #endif
710 eh = mtod(m0, struct ether_header *);
711 ni = ieee80211_find_txnode(ic, eh->ether_dhost);
712 if (ni == NULL) {
713 ifp->if_oerrors++;
714 continue;
715 }
716 if ((ifp->if_flags & IFF_LINK0) || sc->sc_adhoc_ap)
717 m0 = awi_ether_encap(sc, m0);
718 else {
719 m0 = ieee80211_encap(ic, m0, ni);
720 }
721 if (m0 == NULL) {
722 ieee80211_free_node(ni);
723 ifp->if_oerrors++;
724 continue;
725 }
726 wh = mtod(m0, struct ieee80211_frame *);
727 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
728 (ic->ic_opmode == IEEE80211_M_HOSTAP ||
729 ic->ic_opmode == IEEE80211_M_IBSS) &&
730 sc->sc_adhoc_ap == 0 &&
731 (ifp->if_flags & IFF_LINK0) == 0 &&
732 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
733 IEEE80211_FC0_TYPE_DATA) {
734 m_freem(m0);
735 ieee80211_free_node(ni);
736 ifp->if_oerrors++;
737 continue;
738 }
739 }
740 #if NBPFILTER > 0
741 if (ic->ic_rawbpf)
742 bpf_mtap(ic->ic_rawbpf, m0);
743 #endif
744 if (dowep) {
745 if ((ieee80211_crypto_encap(ic, ni, m0)) == NULL) {
746 m_freem(m0);
747 ieee80211_free_node(ni);
748 ifp->if_oerrors++;
749 continue;
750 }
751 }
752 ieee80211_free_node(ni);
753 #ifdef DIAGNOSTIC
754 if (m0->m_pkthdr.len != len) {
755 printf("%s: length %d should be %d\n",
756 sc->sc_if.if_xname, m0->m_pkthdr.len, len);
757 m_freem(m0);
758 ifp->if_oerrors++;
759 continue;
760 }
761 #endif
762
763 if ((ifp->if_flags & IFF_DEBUG) && (ifp->if_flags & IFF_LINK2))
764 ieee80211_dump_pkt(m0->m_data, m0->m_len,
765 ic->ic_bss->ni_rates.
766 rs_rates[ic->ic_bss->ni_txrate] &
767 IEEE80211_RATE_VAL, -1);
768
769 for (m = m0, len = 0; m != NULL; m = m->m_next) {
770 awi_write_bytes(sc, frame + len, mtod(m, u_int8_t *),
771 m->m_len);
772 len += m->m_len;
773 }
774 m_freem(m0);
775 rate = (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] &
776 IEEE80211_RATE_VAL) * 5;
777 awi_write_1(sc, ntxd + AWI_TXD_STATE, 0);
778 awi_write_4(sc, txd + AWI_TXD_START, frame);
779 awi_write_4(sc, txd + AWI_TXD_NEXT, ntxd);
780 awi_write_4(sc, txd + AWI_TXD_LENGTH, len);
781 awi_write_1(sc, txd + AWI_TXD_RATE, rate);
782 awi_write_4(sc, txd + AWI_TXD_NDA, 0);
783 awi_write_4(sc, txd + AWI_TXD_NRA, 0);
784 awi_write_1(sc, txd + AWI_TXD_STATE, AWI_TXD_ST_OWN);
785 sc->sc_txnext = ntxd;
786
787 sc->sc_tx_timer = 5;
788 ifp->if_timer = 1;
789 }
790 }
791
792 static void
793 awi_watchdog(struct ifnet *ifp)
794 {
795 struct awi_softc *sc = ifp->if_softc;
796 u_int32_t prevdone;
797 int ocansleep;
798
799 ifp->if_timer = 0;
800 if (!sc->sc_enabled || sc->sc_invalid)
801 return;
802
803 ocansleep = sc->sc_cansleep;
804 sc->sc_cansleep = 0;
805 if (sc->sc_tx_timer) {
806 if (--sc->sc_tx_timer == 0) {
807 printf("%s: device timeout\n", ifp->if_xname);
808 prevdone = sc->sc_txdone;
809 awi_tx_int(sc);
810 if (sc->sc_txdone == prevdone) {
811 ifp->if_oerrors++;
812 awi_init(ifp);
813 goto out;
814 }
815 }
816 ifp->if_timer = 1;
817 }
818 if (sc->sc_rx_timer) {
819 if (--sc->sc_rx_timer == 0) {
820 if (sc->sc_ic.ic_state == IEEE80211_S_RUN) {
821 ieee80211_new_state(&sc->sc_ic,
822 IEEE80211_S_SCAN, -1);
823 goto out;
824 }
825 } else
826 ifp->if_timer = 1;
827 }
828 /* TODO: rate control */
829 ieee80211_watchdog(&sc->sc_ic);
830 out:
831 sc->sc_cansleep = ocansleep;
832 }
833
834 static int
835 awi_ioctl(struct ifnet *ifp, u_long cmd, void *data)
836 {
837 struct awi_softc *sc = ifp->if_softc;
838 struct ifreq *ifr = (struct ifreq *)data;
839 int s, error;
840
841 s = splnet();
842 /* serialize ioctl, since we may sleep */
843 if ((error = awi_lock(sc)) != 0)
844 goto cantlock;
845
846 switch (cmd) {
847 case SIOCSIFFLAGS:
848 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
849 break;
850 if (ifp->if_flags & IFF_UP) {
851 if (sc->sc_enabled) {
852 /*
853 * To avoid rescanning another access point,
854 * do not call awi_init() here. Instead,
855 * only reflect promisc mode settings.
856 */
857 error = awi_mode_init(sc);
858 } else
859 error = awi_init(ifp);
860 } else if (sc->sc_enabled)
861 awi_stop(ifp, 1);
862 break;
863 case SIOCSIFMEDIA:
864 case SIOCGIFMEDIA:
865 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ic.ic_media, cmd);
866 break;
867 case SIOCADDMULTI:
868 case SIOCDELMULTI:
869 error = ether_ioctl(ifp, cmd, data);
870 if (error == ENETRESET) {
871 /* do not rescan */
872 if (ifp->if_flags & IFF_RUNNING)
873 error = awi_mode_init(sc);
874 else
875 error = 0;
876 }
877 break;
878 default:
879 error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
880 if (error == ENETRESET) {
881 if (sc->sc_enabled)
882 error = awi_init(ifp);
883 else
884 error = 0;
885 }
886 break;
887 }
888 awi_unlock(sc);
889 cantlock:
890 splx(s);
891 return error;
892 }
893
894 /*
895 * Called from ifmedia_ioctl via awi_ioctl with lock obtained.
896 *
897 * TBD factor with ieee80211_media_change
898 */
899 static int
900 awi_media_change(struct ifnet *ifp)
901 {
902 struct awi_softc *sc = ifp->if_softc;
903 struct ieee80211com *ic = &sc->sc_ic;
904 struct ifmedia_entry *ime;
905 enum ieee80211_opmode newmode;
906 int i, rate, newadhoc_ap, error = 0;
907
908 ime = ic->ic_media.ifm_cur;
909 if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) {
910 i = -1;
911 } else {
912 struct ieee80211_rateset *rs =
913 &ic->ic_sup_rates[(ic->ic_phytype == IEEE80211_T_FH)
914 ? IEEE80211_MODE_FH : IEEE80211_MODE_11B];
915 rate = ieee80211_media2rate(ime->ifm_media);
916 if (rate == 0)
917 return EINVAL;
918 for (i = 0; i < rs->rs_nrates; i++) {
919 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate)
920 break;
921 }
922 if (i == rs->rs_nrates)
923 return EINVAL;
924 }
925 if (ic->ic_fixed_rate != i) {
926 ic->ic_fixed_rate = i;
927 error = ENETRESET;
928 }
929
930 /*
931 * combination of mediaopt
932 *
933 * hostap adhoc flag0 opmode adhoc_ap comment
934 * + - - HOSTAP 0 HostAP
935 * - + - IBSS 0 IBSS
936 * - + + AHDEMO 0 WaveLAN adhoc
937 * - - + IBSS 1 Melco old Sta
938 * also LINK0
939 * - - - STA 0 Infra Station
940 */
941 newadhoc_ap = 0;
942 if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
943 newmode = IEEE80211_M_HOSTAP;
944 else if (ime->ifm_media & IFM_IEEE80211_ADHOC) {
945 if (ic->ic_phytype == IEEE80211_T_DS &&
946 (ime->ifm_media & IFM_FLAG0))
947 newmode = IEEE80211_M_AHDEMO;
948 else
949 newmode = IEEE80211_M_IBSS;
950 } else if (ime->ifm_media & IFM_FLAG0) {
951 newmode = IEEE80211_M_IBSS;
952 newadhoc_ap = 1;
953 } else
954 newmode = IEEE80211_M_STA;
955 if (ic->ic_opmode != newmode || sc->sc_adhoc_ap != newadhoc_ap) {
956 ic->ic_opmode = newmode;
957 sc->sc_adhoc_ap = newadhoc_ap;
958 error = ENETRESET;
959 }
960
961 if (error == ENETRESET) {
962 if (sc->sc_enabled)
963 error = awi_init(ifp);
964 else
965 error = 0;
966 }
967 return error;
968 }
969
970 static void
971 awi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
972 {
973 struct awi_softc *sc = ifp->if_softc;
974 struct ieee80211com *ic = &sc->sc_ic;
975 int rate;
976 enum ieee80211_phymode mode;
977
978 imr->ifm_status = IFM_AVALID;
979 if (ic->ic_state == IEEE80211_S_RUN)
980 imr->ifm_status |= IFM_ACTIVE;
981 imr->ifm_active = IFM_IEEE80211;
982 if (ic->ic_phytype == IEEE80211_T_FH)
983 mode = IEEE80211_MODE_FH;
984 else
985 mode = IEEE80211_MODE_11B;
986 if (ic->ic_state == IEEE80211_S_RUN) {
987 rate = ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] &
988 IEEE80211_RATE_VAL;
989 } else {
990 if (ic->ic_fixed_rate == -1)
991 rate = 0;
992 else
993 rate = ic->ic_sup_rates[mode].
994 rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
995 }
996 imr->ifm_active |= ieee80211_rate2media(ic, rate, mode);
997 switch (ic->ic_opmode) {
998 case IEEE80211_M_MONITOR: /* we should never reach here */
999 break;
1000 case IEEE80211_M_STA:
1001 break;
1002 case IEEE80211_M_IBSS:
1003 if (sc->sc_adhoc_ap)
1004 imr->ifm_active |= IFM_FLAG0;
1005 else
1006 imr->ifm_active |= IFM_IEEE80211_ADHOC;
1007 break;
1008 case IEEE80211_M_AHDEMO:
1009 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
1010 break;
1011 case IEEE80211_M_HOSTAP:
1012 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
1013 break;
1014 }
1015 }
1016
1017 static int
1018 awi_mode_init(struct awi_softc *sc)
1019 {
1020 struct ifnet *ifp = &sc->sc_if;
1021 int n, error;
1022 struct ether_multi *enm;
1023 struct ether_multistep step;
1024
1025 /* reinitialize muticast filter */
1026 n = 0;
1027 sc->sc_mib_local.Accept_All_Multicast_Dis = 0;
1028 if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP &&
1029 (ifp->if_flags & IFF_PROMISC)) {
1030 sc->sc_mib_mac.aPromiscuous_Enable = 1;
1031 goto set_mib;
1032 }
1033 sc->sc_mib_mac.aPromiscuous_Enable = 0;
1034 ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
1035 while (enm != NULL) {
1036 if (n == AWI_GROUP_ADDR_SIZE ||
1037 !IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi))
1038 goto set_mib;
1039 IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n],
1040 enm->enm_addrlo);
1041 n++;
1042 ETHER_NEXT_MULTI(step, enm);
1043 }
1044 for (; n < AWI_GROUP_ADDR_SIZE; n++)
1045 memset(sc->sc_mib_addr.aGroup_Addresses[n], 0,
1046 IEEE80211_ADDR_LEN);
1047 sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
1048
1049 set_mib:
1050 if (sc->sc_mib_local.Accept_All_Multicast_Dis)
1051 ifp->if_flags &= ~IFF_ALLMULTI;
1052 else
1053 ifp->if_flags |= IFF_ALLMULTI;
1054 sc->sc_mib_mgt.Wep_Required =
1055 (sc->sc_ic.ic_flags & IEEE80211_F_PRIVACY) ? AWI_WEP_ON : AWI_WEP_OFF;
1056
1057 if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) ||
1058 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_ADDR, AWI_WAIT)) ||
1059 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MAC, AWI_WAIT)) ||
1060 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT, AWI_WAIT)) ||
1061 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_PHY, AWI_WAIT))) {
1062 DPRINTF(("awi_mode_init: MIB set failed: %d\n", error));
1063 return error;
1064 }
1065 return 0;
1066 }
1067
1068 static void
1069 awi_rx_int(struct awi_softc *sc)
1070 {
1071 struct ieee80211com *ic = &sc->sc_ic;
1072 struct ifnet *ifp = &sc->sc_if;
1073 struct ieee80211_frame_min *wh;
1074 struct ieee80211_node *ni;
1075 u_int8_t state, rate, rssi;
1076 u_int16_t len;
1077 u_int32_t frame, next, rstamp, rxoff;
1078 struct mbuf *m;
1079
1080 rxoff = sc->sc_rxdoff;
1081 for (;;) {
1082 state = awi_read_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE);
1083 if (state & AWI_RXD_ST_OWN)
1084 break;
1085 if (!(state & AWI_RXD_ST_CONSUMED)) {
1086 if (sc->sc_substate != AWI_ST_NONE)
1087 goto rx_next;
1088 if (state & AWI_RXD_ST_RXERROR) {
1089 ifp->if_ierrors++;
1090 goto rx_next;
1091 }
1092 len = awi_read_2(sc, rxoff + AWI_RXD_LEN);
1093 rate = awi_read_1(sc, rxoff + AWI_RXD_RATE);
1094 rssi = awi_read_1(sc, rxoff + AWI_RXD_RSSI);
1095 frame = awi_read_4(sc, rxoff + AWI_RXD_START_FRAME) &
1096 0x7fff;
1097 rstamp = awi_read_4(sc, rxoff + AWI_RXD_LOCALTIME);
1098 m = awi_devget(sc, frame, len);
1099 if (m == NULL) {
1100 ifp->if_ierrors++;
1101 goto rx_next;
1102 }
1103 if (state & AWI_RXD_ST_LF) {
1104 /* TODO check my bss */
1105 if (!(sc->sc_ic.ic_flags & IEEE80211_F_SIBSS) &&
1106 sc->sc_ic.ic_state == IEEE80211_S_RUN) {
1107 sc->sc_rx_timer = 10;
1108 ifp->if_timer = 1;
1109 }
1110 if ((ifp->if_flags & IFF_DEBUG) &&
1111 (ifp->if_flags & IFF_LINK2))
1112 ieee80211_dump_pkt(m->m_data, m->m_len,
1113 rate / 5, rssi);
1114 if ((ifp->if_flags & IFF_LINK0) ||
1115 sc->sc_adhoc_ap)
1116 m = awi_ether_modcap(sc, m);
1117 else
1118 m = m_pullup(m, sizeof(*wh));
1119 if (m == NULL) {
1120 ifp->if_ierrors++;
1121 goto rx_next;
1122 }
1123 wh = mtod(m, struct ieee80211_frame_min *);
1124 ni = ieee80211_find_rxnode(ic, wh);
1125 ieee80211_input(ic, m, ni, rssi, rstamp);
1126 /*
1127 * The frame may have caused the
1128 * node to be marked for reclamation
1129 * (e.g. in response to a DEAUTH
1130 * message) so use release_node here
1131 * instead of unref_node.
1132 */
1133 ieee80211_free_node(ni);
1134 } else
1135 sc->sc_rxpend = m;
1136 rx_next:
1137 state |= AWI_RXD_ST_CONSUMED;
1138 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
1139 }
1140 next = awi_read_4(sc, rxoff + AWI_RXD_NEXT);
1141 if (next & AWI_RXD_NEXT_LAST)
1142 break;
1143 /* make sure the next pointer is correct */
1144 if (next != awi_read_4(sc, rxoff + AWI_RXD_NEXT))
1145 break;
1146 state |= AWI_RXD_ST_OWN;
1147 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
1148 rxoff = next & 0x7fff;
1149 }
1150 sc->sc_rxdoff = rxoff;
1151 }
1152
1153 static void
1154 awi_tx_int(struct awi_softc *sc)
1155 {
1156 struct ifnet *ifp = &sc->sc_if;
1157 u_int8_t flags;
1158
1159 while (sc->sc_txdone != sc->sc_txnext) {
1160 flags = awi_read_1(sc, sc->sc_txdone + AWI_TXD_STATE);
1161 if ((flags & AWI_TXD_ST_OWN) || !(flags & AWI_TXD_ST_DONE))
1162 break;
1163 if (flags & AWI_TXD_ST_ERROR)
1164 ifp->if_oerrors++;
1165 sc->sc_txdone = awi_read_4(sc, sc->sc_txdone + AWI_TXD_NEXT) &
1166 0x7fff;
1167 }
1168 DPRINTF2(("awi_txint: txdone %d txnext %d txbase %d txend %d\n",
1169 sc->sc_txdone, sc->sc_txnext, sc->sc_txbase, sc->sc_txend));
1170 sc->sc_tx_timer = 0;
1171 ifp->if_flags &= ~IFF_OACTIVE;
1172 awi_start(ifp);
1173 }
1174
1175 static struct mbuf *
1176 awi_devget(struct awi_softc *sc, u_int32_t off, u_int16_t len)
1177 {
1178 struct ifnet *ifp = &sc->sc_if;
1179 struct mbuf *m;
1180 struct mbuf *top, **mp;
1181 u_int tlen;
1182
1183 top = sc->sc_rxpend;
1184 mp = ⊤
1185 if (top != NULL) {
1186 sc->sc_rxpend = NULL;
1187 top->m_pkthdr.len += len;
1188 m = top;
1189 while (*mp != NULL) {
1190 m = *mp;
1191 mp = &m->m_next;
1192 }
1193 if (m->m_flags & M_EXT)
1194 tlen = m->m_ext.ext_size;
1195 else if (m->m_flags & M_PKTHDR)
1196 tlen = MHLEN;
1197 else
1198 tlen = MLEN;
1199 tlen -= m->m_len;
1200 if (tlen > len)
1201 tlen = len;
1202 awi_read_bytes(sc, off, mtod(m, u_int8_t *) + m->m_len, tlen);
1203 off += tlen;
1204 len -= tlen;
1205 }
1206
1207 while (len > 0) {
1208 if (top == NULL) {
1209 MGETHDR(m, M_DONTWAIT, MT_DATA);
1210 if (m == NULL)
1211 return NULL;
1212 m->m_pkthdr.rcvif = ifp;
1213 m->m_pkthdr.len = len;
1214 m->m_len = MHLEN;
1215 m->m_flags |= M_HASFCS;
1216 } else {
1217 MGET(m, M_DONTWAIT, MT_DATA);
1218 if (m == NULL) {
1219 m_freem(top);
1220 return NULL;
1221 }
1222 m->m_len = MLEN;
1223 }
1224 if (len >= MINCLSIZE) {
1225 MCLGET(m, M_DONTWAIT);
1226 if (m->m_flags & M_EXT)
1227 m->m_len = m->m_ext.ext_size;
1228 }
1229 if (top == NULL) {
1230 int hdrlen = sizeof(struct ieee80211_frame) +
1231 sizeof(struct llc);
1232 char *newdata = (char *)
1233 ALIGN(m->m_data + hdrlen) - hdrlen;
1234 m->m_len -= newdata - m->m_data;
1235 m->m_data = newdata;
1236 }
1237 if (m->m_len > len)
1238 m->m_len = len;
1239 awi_read_bytes(sc, off, mtod(m, u_int8_t *), m->m_len);
1240 off += m->m_len;
1241 len -= m->m_len;
1242 *mp = m;
1243 mp = &m->m_next;
1244 }
1245 return top;
1246 }
1247
1248 /*
1249 * Initialize hardware and start firmware to accept commands.
1250 * Called everytime after power on firmware.
1251 */
1252
1253 static int
1254 awi_hw_init(struct awi_softc *sc)
1255 {
1256 u_int8_t status;
1257 u_int16_t intmask;
1258 int i, error;
1259
1260 sc->sc_enab_intr = 0;
1261 sc->sc_invalid = 0; /* XXX: really? */
1262 awi_drvstate(sc, AWI_DRV_RESET);
1263
1264 /* reset firmware */
1265 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_CORESET);
1266 DELAY(100);
1267 awi_write_1(sc, AWI_SELFTEST, 0);
1268 awi_write_1(sc, AWI_CMD, 0);
1269 awi_write_1(sc, AWI_BANNER, 0);
1270 am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_CORESET);
1271 DELAY(100);
1272
1273 /* wait for selftest completion */
1274 for (i = 0; ; i++) {
1275 if (sc->sc_invalid)
1276 return ENXIO;
1277 if (i >= AWI_SELFTEST_TIMEOUT*hz/1000) {
1278 printf("%s: failed to complete selftest (timeout)\n",
1279 sc->sc_if.if_xname);
1280 return ENXIO;
1281 }
1282 status = awi_read_1(sc, AWI_SELFTEST);
1283 if ((status & 0xf0) == 0xf0)
1284 break;
1285 if (sc->sc_cansleep) {
1286 sc->sc_sleep_cnt++;
1287 (void)tsleep(sc, PWAIT, "awitst", 1);
1288 sc->sc_sleep_cnt--;
1289 } else {
1290 DELAY(1000*1000/hz);
1291 }
1292 }
1293 if (status != AWI_SELFTEST_PASSED) {
1294 printf("%s: failed to complete selftest (code %x)\n",
1295 sc->sc_if.if_xname, status);
1296 return ENXIO;
1297 }
1298
1299 /* check banner to confirm firmware write it */
1300 awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
1301 if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) {
1302 printf("%s: failed to complete selftest (bad banner)\n",
1303 sc->sc_if.if_xname);
1304 for (i = 0; i < AWI_BANNER_LEN; i++)
1305 printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]);
1306 printf("\n");
1307 return ENXIO;
1308 }
1309
1310 /* initializing interrupt */
1311 sc->sc_enab_intr = 1;
1312 error = awi_intr_lock(sc);
1313 if (error)
1314 return error;
1315 intmask = AWI_INT_GROGGY | AWI_INT_SCAN_CMPLT |
1316 AWI_INT_TX | AWI_INT_RX | AWI_INT_CMD;
1317 awi_write_1(sc, AWI_INTMASK, ~intmask & 0xff);
1318 awi_write_1(sc, AWI_INTMASK2, 0);
1319 awi_write_1(sc, AWI_INTSTAT, 0);
1320 awi_write_1(sc, AWI_INTSTAT2, 0);
1321 awi_intr_unlock(sc);
1322 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT);
1323
1324 /* issuing interface test command */
1325 error = awi_cmd(sc, AWI_CMD_NOP, AWI_WAIT);
1326 if (error) {
1327 printf("%s: failed to complete selftest",
1328 sc->sc_if.if_xname);
1329 if (error == ENXIO)
1330 printf(" (no hardware)\n");
1331 else if (error != EWOULDBLOCK)
1332 printf(" (error %d)\n", error);
1333 else if (sc->sc_cansleep)
1334 printf(" (lost interrupt)\n");
1335 else
1336 printf(" (command timeout)\n");
1337 return error;
1338 }
1339
1340 /* Initialize VBM */
1341 awi_write_1(sc, AWI_VBM_OFFSET, 0);
1342 awi_write_1(sc, AWI_VBM_LENGTH, 1);
1343 awi_write_1(sc, AWI_VBM_BITMAP, 0);
1344 return 0;
1345 }
1346
1347 /*
1348 * Extract the factory default MIB value from firmware and assign the driver
1349 * default value.
1350 * Called once at attaching the interface.
1351 */
1352
1353 static int
1354 awi_init_mibs(struct awi_softc *sc)
1355 {
1356 int chan, i, error;
1357 struct ieee80211com *ic = &sc->sc_ic;
1358 struct awi_chanset *cs;
1359
1360 if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) ||
1361 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_ADDR, AWI_WAIT)) ||
1362 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MAC, AWI_WAIT)) ||
1363 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT, AWI_WAIT)) ||
1364 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_PHY, AWI_WAIT))) {
1365 printf("%s: failed to get default mib value (error %d)\n",
1366 sc->sc_if.if_xname, error);
1367 return error;
1368 }
1369
1370 memset(&sc->sc_ic.ic_chan_avail, 0, sizeof(sc->sc_ic.ic_chan_avail));
1371 for (cs = awi_chanset; ; cs++) {
1372 if (cs->cs_type == 0) {
1373 printf("%s: failed to set available channel\n",
1374 sc->sc_if.if_xname);
1375 return ENXIO;
1376 }
1377 if (cs->cs_type == sc->sc_mib_phy.IEEE_PHY_Type &&
1378 cs->cs_region == sc->sc_mib_phy.aCurrent_Reg_Domain)
1379 break;
1380 }
1381 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
1382 for (i = cs->cs_min; i <= cs->cs_max; i++) {
1383 chan = IEEE80211_FH_CHAN(i % 3 + 1, i);
1384 setbit(sc->sc_ic.ic_chan_avail, chan);
1385 /* XXX for FHSS, does frequency matter? */
1386 ic->ic_channels[chan].ic_freq = 0;
1387 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_FHSS;
1388 /*
1389 * According to the IEEE 802.11 specification,
1390 * hop pattern parameter for FH phy should be
1391 * incremented by 3 for given hop chanset, i.e.,
1392 * the chanset parameter is calculated for given
1393 * hop patter. However, BayStack 650 Access Points
1394 * apparently use fixed hop chanset parameter value
1395 * 1 for any hop pattern. So we also try this
1396 * combination of hop chanset and pattern.
1397 */
1398 chan = IEEE80211_FH_CHAN(1, i);
1399 setbit(sc->sc_ic.ic_chan_avail, chan);
1400 ic->ic_channels[chan].ic_freq = 0; /* XXX */
1401 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_FHSS;
1402 }
1403 } else {
1404 for (i = cs->cs_min; i <= cs->cs_max; i++) {
1405 setbit(sc->sc_ic.ic_chan_avail, i);
1406 ic->ic_channels[i].ic_freq =
1407 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
1408 ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
1409 }
1410 }
1411 sc->sc_cur_chan = cs->cs_def;
1412 ic->ic_ibss_chan = &ic->ic_channels[cs->cs_def];
1413
1414 sc->sc_mib_local.Fragmentation_Dis = 1;
1415 sc->sc_mib_local.Add_PLCP_Dis = 0;
1416 sc->sc_mib_local.MAC_Hdr_Prsv = 0;
1417 sc->sc_mib_local.Rx_Mgmt_Que_En = 0;
1418 sc->sc_mib_local.Re_Assembly_Dis = 1;
1419 sc->sc_mib_local.Strip_PLCP_Dis = 0;
1420 sc->sc_mib_local.Power_Saving_Mode_Dis = 1;
1421 sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
1422 sc->sc_mib_local.Check_Seq_Cntl_Dis = 0;
1423 sc->sc_mib_local.Flush_CFP_Queue_On_CF_End = 0;
1424 sc->sc_mib_local.Network_Mode = 1;
1425 sc->sc_mib_local.PWD_Lvl = 0;
1426 sc->sc_mib_local.CFP_Mode = 0;
1427
1428 /* allocate buffers */
1429 sc->sc_txbase = AWI_BUFFERS;
1430 sc->sc_txend = sc->sc_txbase +
1431 (AWI_TXD_SIZE + sizeof(struct ieee80211_frame) +
1432 sizeof(struct ether_header) + ETHERMTU) * AWI_NTXBUFS;
1433 LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Offset, sc->sc_txbase);
1434 LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Size,
1435 sc->sc_txend - sc->sc_txbase);
1436 LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Offset, sc->sc_txend);
1437 LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Size,
1438 AWI_BUFFERS_END - sc->sc_txend);
1439 sc->sc_mib_local.Acting_as_AP = 0;
1440 sc->sc_mib_local.Fill_CFP = 0;
1441
1442 memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
1443 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
1444
1445 sc->sc_mib_mgt.aPower_Mgt_Mode = 0;
1446 sc->sc_mib_mgt.aDTIM_Period = 1;
1447 LE_WRITE_2(&sc->sc_mib_mgt.aATIM_Window, 0);
1448 return 0;
1449 }
1450
1451 static int
1452 awi_mib(struct awi_softc *sc, u_int8_t cmd, u_int8_t mib, int wflag)
1453 {
1454 int error;
1455 u_int8_t size, *ptr;
1456
1457 switch (mib) {
1458 case AWI_MIB_LOCAL:
1459 ptr = (u_int8_t *)&sc->sc_mib_local;
1460 size = sizeof(sc->sc_mib_local);
1461 break;
1462 case AWI_MIB_ADDR:
1463 ptr = (u_int8_t *)&sc->sc_mib_addr;
1464 size = sizeof(sc->sc_mib_addr);
1465 break;
1466 case AWI_MIB_MAC:
1467 ptr = (u_int8_t *)&sc->sc_mib_mac;
1468 size = sizeof(sc->sc_mib_mac);
1469 break;
1470 case AWI_MIB_STAT:
1471 ptr = (u_int8_t *)&sc->sc_mib_stat;
1472 size = sizeof(sc->sc_mib_stat);
1473 break;
1474 case AWI_MIB_MGT:
1475 ptr = (u_int8_t *)&sc->sc_mib_mgt;
1476 size = sizeof(sc->sc_mib_mgt);
1477 break;
1478 case AWI_MIB_PHY:
1479 ptr = (u_int8_t *)&sc->sc_mib_phy;
1480 size = sizeof(sc->sc_mib_phy);
1481 break;
1482 default:
1483 return EINVAL;
1484 }
1485 if (sc->sc_cmd_inprog) {
1486 if ((error = awi_cmd_wait(sc)) != 0) {
1487 if (error == EWOULDBLOCK) {
1488 DPRINTF(("awi_mib: cmd %d inprog",
1489 sc->sc_cmd_inprog));
1490 }
1491 return error;
1492 }
1493 }
1494 sc->sc_cmd_inprog = cmd;
1495 if (cmd == AWI_CMD_SET_MIB)
1496 awi_write_bytes(sc, AWI_CA_MIB_DATA, ptr, size);
1497 awi_write_1(sc, AWI_CA_MIB_TYPE, mib);
1498 awi_write_1(sc, AWI_CA_MIB_SIZE, size);
1499 awi_write_1(sc, AWI_CA_MIB_INDEX, 0);
1500 if ((error = awi_cmd(sc, cmd, wflag)) != 0)
1501 return error;
1502 if (cmd == AWI_CMD_GET_MIB) {
1503 awi_read_bytes(sc, AWI_CA_MIB_DATA, ptr, size);
1504 #ifdef AWI_DEBUG
1505 if (awi_debug) {
1506 int i;
1507
1508 printf("awi_mib: #%d:", mib);
1509 for (i = 0; i < size; i++)
1510 printf(" %02x", ptr[i]);
1511 printf("\n");
1512 }
1513 #endif
1514 }
1515 return 0;
1516 }
1517
1518 static int
1519 awi_cmd(struct awi_softc *sc, u_int8_t cmd, int wflag)
1520 {
1521 u_int8_t status;
1522 int error = 0;
1523 #ifdef AWI_DEBUG
1524 static const char *cmdname[] = {
1525 "IDLE", "NOP", "SET_MIB", "INIT_TX", "FLUSH_TX", "INIT_RX",
1526 "KILL_RX", "SLEEP", "WAKE", "GET_MIB", "SCAN", "SYNC", "RESUME"
1527 };
1528 #endif
1529
1530 #ifdef AWI_DEBUG
1531 if (awi_debug > 1) {
1532 if (cmd >= sizeof(cmdname)/sizeof(cmdname[0]))
1533 printf("awi_cmd: #%d", cmd);
1534 else
1535 printf("awi_cmd: %s", cmdname[cmd]);
1536 printf(" %s\n", wflag == AWI_NOWAIT ? "nowait" : "wait");
1537 }
1538 #endif
1539 sc->sc_cmd_inprog = cmd;
1540 awi_write_1(sc, AWI_CMD_STATUS, AWI_STAT_IDLE);
1541 awi_write_1(sc, AWI_CMD, cmd);
1542 if (wflag == AWI_NOWAIT)
1543 return EINPROGRESS;
1544 if ((error = awi_cmd_wait(sc)) != 0)
1545 return error;
1546 status = awi_read_1(sc, AWI_CMD_STATUS);
1547 awi_write_1(sc, AWI_CMD, 0);
1548 switch (status) {
1549 case AWI_STAT_OK:
1550 break;
1551 case AWI_STAT_BADPARM:
1552 return EINVAL;
1553 default:
1554 printf("%s: command %d failed %x\n",
1555 sc->sc_if.if_xname, cmd, status);
1556 return ENXIO;
1557 }
1558 return 0;
1559 }
1560
1561 static int
1562 awi_cmd_wait(struct awi_softc *sc)
1563 {
1564 int i, error = 0;
1565
1566 i = 0;
1567 while (sc->sc_cmd_inprog) {
1568 if (sc->sc_invalid)
1569 return ENXIO;
1570 if (awi_read_1(sc, AWI_CMD) != sc->sc_cmd_inprog) {
1571 printf("%s: failed to access hardware\n",
1572 sc->sc_if.if_xname);
1573 sc->sc_invalid = 1;
1574 return ENXIO;
1575 }
1576 if (sc->sc_cansleep) {
1577 sc->sc_sleep_cnt++;
1578 error = tsleep(sc, PWAIT, "awicmd",
1579 AWI_CMD_TIMEOUT*hz/1000);
1580 sc->sc_sleep_cnt--;
1581 } else {
1582 if (awi_read_1(sc, AWI_CMD_STATUS) != AWI_STAT_IDLE) {
1583 awi_cmd_done(sc);
1584 break;
1585 }
1586 if (i++ >= AWI_CMD_TIMEOUT*1000/10)
1587 error = EWOULDBLOCK;
1588 else
1589 DELAY(10);
1590 }
1591 if (error)
1592 break;
1593 }
1594 if (error) {
1595 DPRINTF(("awi_cmd_wait: cmd 0x%x, error %d\n",
1596 sc->sc_cmd_inprog, error));
1597 }
1598 return error;
1599 }
1600
1601 static void
1602 awi_cmd_done(struct awi_softc *sc)
1603 {
1604 u_int8_t cmd, status;
1605
1606 status = awi_read_1(sc, AWI_CMD_STATUS);
1607 if (status == AWI_STAT_IDLE)
1608 return; /* stray interrupt */
1609
1610 cmd = sc->sc_cmd_inprog;
1611 sc->sc_cmd_inprog = 0;
1612 wakeup(sc);
1613 awi_write_1(sc, AWI_CMD, 0);
1614
1615 if (status != AWI_STAT_OK) {
1616 printf("%s: command %d failed %x\n",
1617 sc->sc_if.if_xname, cmd, status);
1618 sc->sc_substate = AWI_ST_NONE;
1619 return;
1620 }
1621 if (sc->sc_substate != AWI_ST_NONE)
1622 (void)ieee80211_new_state(&sc->sc_ic, sc->sc_nstate, -1);
1623 }
1624
1625 static int
1626 awi_next_txd(struct awi_softc *sc, int len, u_int32_t *framep, u_int32_t *ntxdp)
1627 {
1628 u_int32_t txd, ntxd, frame;
1629
1630 txd = sc->sc_txnext;
1631 frame = txd + AWI_TXD_SIZE;
1632 if (frame + len > sc->sc_txend)
1633 frame = sc->sc_txbase;
1634 ntxd = frame + len;
1635 if (ntxd + AWI_TXD_SIZE > sc->sc_txend)
1636 ntxd = sc->sc_txbase;
1637 *framep = frame;
1638 *ntxdp = ntxd;
1639 /*
1640 * Determine if there are any room in ring buffer.
1641 * --- send wait, === new data, +++ conflict (ENOBUFS)
1642 * base........................end
1643 * done----txd=====ntxd OK
1644 * --txd=====done++++ntxd-- full
1645 * --txd=====ntxd done-- OK
1646 * ==ntxd done----txd=== OK
1647 * ==done++++ntxd----txd=== full
1648 * ++ntxd txd=====done++ full
1649 */
1650 if (txd < ntxd) {
1651 if (txd < sc->sc_txdone && ntxd + AWI_TXD_SIZE > sc->sc_txdone)
1652 return ENOBUFS;
1653 } else {
1654 if (txd < sc->sc_txdone || ntxd + AWI_TXD_SIZE > sc->sc_txdone)
1655 return ENOBUFS;
1656 }
1657 return 0;
1658 }
1659
1660 static int
1661 awi_lock(struct awi_softc *sc)
1662 {
1663 int error = 0;
1664
1665 if (curlwp == NULL)
1666 {
1667 /*
1668 * XXX
1669 * Though driver ioctl should be called with context,
1670 * KAME ipv6 stack calls ioctl in interrupt for now.
1671 * We simply abort the request if there are other
1672 * ioctl requests in progress.
1673 */
1674 if (sc->sc_busy) {
1675 if (sc->sc_invalid)
1676 return ENXIO;
1677 return EWOULDBLOCK;
1678 }
1679 sc->sc_busy = 1;
1680 sc->sc_cansleep = 0;
1681 return 0;
1682 }
1683 while (sc->sc_busy) {
1684 if (sc->sc_invalid)
1685 return ENXIO;
1686 sc->sc_sleep_cnt++;
1687 error = tsleep(sc, PWAIT | PCATCH, "awilck", 0);
1688 sc->sc_sleep_cnt--;
1689 if (error)
1690 return error;
1691 }
1692 sc->sc_busy = 1;
1693 sc->sc_cansleep = 1;
1694 return 0;
1695 }
1696
1697 static void
1698 awi_unlock(struct awi_softc *sc)
1699 {
1700 sc->sc_busy = 0;
1701 sc->sc_cansleep = 0;
1702 if (sc->sc_sleep_cnt)
1703 wakeup(sc);
1704 }
1705
1706 static int
1707 awi_intr_lock(struct awi_softc *sc)
1708 {
1709 u_int8_t status;
1710 int i, retry;
1711
1712 status = 1;
1713 for (retry = 0; retry < 10; retry++) {
1714 for (i = 0; i < AWI_LOCKOUT_TIMEOUT*1000/5; i++) {
1715 if ((status = awi_read_1(sc, AWI_LOCKOUT_HOST)) == 0)
1716 break;
1717 DELAY(5);
1718 }
1719 if (status != 0)
1720 break;
1721 awi_write_1(sc, AWI_LOCKOUT_MAC, 1);
1722 if ((status = awi_read_1(sc, AWI_LOCKOUT_HOST)) == 0)
1723 break;
1724 awi_write_1(sc, AWI_LOCKOUT_MAC, 0);
1725 }
1726 if (status != 0) {
1727 printf("%s: failed to lock interrupt\n",
1728 sc->sc_if.if_xname);
1729 return ENXIO;
1730 }
1731 return 0;
1732 }
1733
1734 static void
1735 awi_intr_unlock(struct awi_softc *sc)
1736 {
1737
1738 awi_write_1(sc, AWI_LOCKOUT_MAC, 0);
1739 }
1740
1741 static int
1742 awi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1743 {
1744 struct ifnet *ifp = ic->ic_ifp;
1745 struct awi_softc *sc = ifp->if_softc;
1746 struct ieee80211_node *ni;
1747 int error;
1748 u_int8_t newmode;
1749 enum ieee80211_state ostate;
1750 #ifdef AWI_DEBUG
1751 static const char *stname[] =
1752 { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
1753 static const char *substname[] =
1754 { "NONE", "SCAN_INIT", "SCAN_SETMIB", "SCAN_SCCMD",
1755 "SUB_INIT", "SUB_SETSS", "SUB_SYNC" };
1756 #endif /* AWI_DEBUG */
1757
1758 ostate = ic->ic_state;
1759 DPRINTF(("awi_newstate: %s (%s/%s) -> %s\n", stname[ostate],
1760 stname[sc->sc_nstate], substname[sc->sc_substate], stname[nstate]));
1761
1762 /* set LED */
1763 switch (nstate) {
1764 case IEEE80211_S_INIT:
1765 awi_drvstate(sc, AWI_DRV_RESET);
1766 break;
1767 case IEEE80211_S_SCAN:
1768 if (ic->ic_opmode == IEEE80211_M_IBSS ||
1769 ic->ic_opmode == IEEE80211_M_AHDEMO)
1770 awi_drvstate(sc, AWI_DRV_ADHSC);
1771 else
1772 awi_drvstate(sc, AWI_DRV_INFSY);
1773 break;
1774 case IEEE80211_S_AUTH:
1775 awi_drvstate(sc, AWI_DRV_INFSY);
1776 break;
1777 case IEEE80211_S_ASSOC:
1778 awi_drvstate(sc, AWI_DRV_INFAUTH);
1779 break;
1780 case IEEE80211_S_RUN:
1781 if (ic->ic_opmode == IEEE80211_M_IBSS ||
1782 ic->ic_opmode == IEEE80211_M_AHDEMO)
1783 awi_drvstate(sc, AWI_DRV_ADHSY);
1784 else
1785 awi_drvstate(sc, AWI_DRV_INFASSOC);
1786 break;
1787 }
1788
1789 if (nstate == IEEE80211_S_INIT) {
1790 sc->sc_substate = AWI_ST_NONE;
1791 ic->ic_flags &= ~IEEE80211_F_SIBSS;
1792 return (*sc->sc_newstate)(ic, nstate, arg);
1793 }
1794
1795 /* state transition */
1796 if (nstate == IEEE80211_S_SCAN) {
1797 /* SCAN substate */
1798 if (sc->sc_substate == AWI_ST_NONE) {
1799 sc->sc_nstate = nstate; /* next state in transition */
1800 sc->sc_substate = AWI_ST_SCAN_INIT;
1801 }
1802 switch (sc->sc_substate) {
1803 case AWI_ST_SCAN_INIT:
1804 sc->sc_substate = AWI_ST_SCAN_SETMIB;
1805 switch (ostate) {
1806 case IEEE80211_S_RUN:
1807 /* beacon miss */
1808 if (ifp->if_flags & IFF_DEBUG)
1809 printf("%s: no recent beacons from %s;"
1810 " rescanning\n",
1811 ifp->if_xname,
1812 ether_sprintf(ic->ic_bss->ni_bssid));
1813 /* FALLTHRU */
1814 case IEEE80211_S_AUTH:
1815 case IEEE80211_S_ASSOC:
1816 case IEEE80211_S_INIT:
1817 ieee80211_begin_scan(ic, 1);
1818 /* FALLTHRU */
1819 case IEEE80211_S_SCAN:
1820 /* scan next */
1821 break;
1822 }
1823 if (ic->ic_flags & IEEE80211_F_ASCAN)
1824 newmode = AWI_SCAN_ACTIVE;
1825 else
1826 newmode = AWI_SCAN_PASSIVE;
1827 if (sc->sc_mib_mgt.aScan_Mode != newmode) {
1828 sc->sc_mib_mgt.aScan_Mode = newmode;
1829 if ((error = awi_mib(sc, AWI_CMD_SET_MIB,
1830 AWI_MIB_MGT, AWI_NOWAIT)) != 0)
1831 break;
1832 }
1833 /* FALLTHRU */
1834 case AWI_ST_SCAN_SETMIB:
1835 sc->sc_substate = AWI_ST_SCAN_SCCMD;
1836 if (sc->sc_cmd_inprog) {
1837 if ((error = awi_cmd_wait(sc)) != 0)
1838 break;
1839 }
1840 sc->sc_cmd_inprog = AWI_CMD_SCAN;
1841 ni = ic->ic_bss;
1842 awi_write_2(sc, AWI_CA_SCAN_DURATION,
1843 (ic->ic_flags & IEEE80211_F_ASCAN) ?
1844 AWI_ASCAN_DURATION : AWI_PSCAN_DURATION);
1845 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
1846 awi_write_1(sc, AWI_CA_SCAN_SET,
1847 IEEE80211_FH_CHANSET(
1848 ieee80211_chan2ieee(ic, ni->ni_chan)));
1849 awi_write_1(sc, AWI_CA_SCAN_PATTERN,
1850 IEEE80211_FH_CHANPAT(
1851 ieee80211_chan2ieee(ic, ni->ni_chan)));
1852 awi_write_1(sc, AWI_CA_SCAN_IDX, 1);
1853 } else {
1854 awi_write_1(sc, AWI_CA_SCAN_SET,
1855 ieee80211_chan2ieee(ic, ni->ni_chan));
1856 awi_write_1(sc, AWI_CA_SCAN_PATTERN, 0);
1857 awi_write_1(sc, AWI_CA_SCAN_IDX, 0);
1858 }
1859 awi_write_1(sc, AWI_CA_SCAN_SUSP, 0);
1860 sc->sc_cur_chan = ieee80211_chan2ieee(ic, ni->ni_chan);
1861 if ((error = awi_cmd(sc, AWI_CMD_SCAN, AWI_NOWAIT))
1862 != 0)
1863 break;
1864 /* FALLTHRU */
1865 case AWI_ST_SCAN_SCCMD:
1866 ic->ic_state = nstate;
1867 sc->sc_substate = AWI_ST_NONE;
1868 error = EINPROGRESS;
1869 break;
1870 default:
1871 DPRINTF(("awi_newstate: unexpected state %s/%s\n",
1872 stname[nstate], substname[sc->sc_substate]));
1873 sc->sc_substate = AWI_ST_NONE;
1874 error = EIO;
1875 break;
1876 }
1877 goto out;
1878 }
1879
1880 if (ostate == IEEE80211_S_SCAN) {
1881 /* set SSID and channel */
1882 /* substate */
1883 if (sc->sc_substate == AWI_ST_NONE) {
1884 sc->sc_nstate = nstate; /* next state in transition */
1885 sc->sc_substate = AWI_ST_SUB_INIT;
1886 }
1887 ni = ic->ic_bss;
1888 switch (sc->sc_substate) {
1889 case AWI_ST_SUB_INIT:
1890 sc->sc_substate = AWI_ST_SUB_SETSS;
1891 IEEE80211_ADDR_COPY(&sc->sc_mib_mgt.aCurrent_BSS_ID,
1892 ni->ni_bssid);
1893 memset(&sc->sc_mib_mgt.aCurrent_ESS_ID, 0,
1894 AWI_ESS_ID_SIZE);
1895 sc->sc_mib_mgt.aCurrent_ESS_ID[0] =
1896 IEEE80211_ELEMID_SSID;
1897 sc->sc_mib_mgt.aCurrent_ESS_ID[1] = ni->ni_esslen;
1898 memcpy(&sc->sc_mib_mgt.aCurrent_ESS_ID[2],
1899 ni->ni_essid, ni->ni_esslen);
1900 LE_WRITE_2(&sc->sc_mib_mgt.aBeacon_Period,
1901 ni->ni_intval);
1902 if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT,
1903 AWI_NOWAIT)) != 0)
1904 break;
1905 /* FALLTHRU */
1906 case AWI_ST_SUB_SETSS:
1907 sc->sc_substate = AWI_ST_SUB_SYNC;
1908 if (sc->sc_cmd_inprog) {
1909 if ((error = awi_cmd_wait(sc)) != 0)
1910 break;
1911 }
1912 sc->sc_cmd_inprog = AWI_CMD_SYNC;
1913 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
1914 awi_write_1(sc, AWI_CA_SYNC_SET,
1915 IEEE80211_FH_CHANSET(
1916 ieee80211_chan2ieee(ic, ni->ni_chan)));
1917 awi_write_1(sc, AWI_CA_SYNC_PATTERN,
1918 IEEE80211_FH_CHANPAT(
1919 ieee80211_chan2ieee(ic, ni->ni_chan)));
1920 awi_write_1(sc, AWI_CA_SYNC_IDX,
1921 ni->ni_fhindex);
1922 awi_write_2(sc, AWI_CA_SYNC_DWELL,
1923 ni->ni_fhdwell);
1924 } else {
1925 awi_write_1(sc, AWI_CA_SYNC_SET,
1926 ieee80211_chan2ieee(ic, ni->ni_chan));
1927 awi_write_1(sc, AWI_CA_SYNC_PATTERN, 0);
1928 awi_write_1(sc, AWI_CA_SYNC_IDX, 0);
1929 awi_write_2(sc, AWI_CA_SYNC_DWELL, 0);
1930 }
1931 if (ic->ic_flags & IEEE80211_F_SIBSS) {
1932 memset(&ni->ni_tstamp, 0,
1933 sizeof(ni->ni_tstamp));
1934 ni->ni_rstamp = 0;
1935 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 1);
1936 } else
1937 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 0);
1938 awi_write_2(sc, AWI_CA_SYNC_MBZ, 0);
1939 awi_write_bytes(sc, AWI_CA_SYNC_TIMESTAMP,
1940 ni->ni_tstamp.data, sizeof(ni->ni_tstamp.data));
1941 awi_write_4(sc, AWI_CA_SYNC_REFTIME, ni->ni_rstamp);
1942 sc->sc_cur_chan = ieee80211_chan2ieee(ic, ni->ni_chan);
1943 if ((error = awi_cmd(sc, AWI_CMD_SYNC, AWI_NOWAIT))
1944 != 0)
1945 break;
1946 /* FALLTHRU */
1947 case AWI_ST_SUB_SYNC:
1948 sc->sc_substate = AWI_ST_NONE;
1949 if (ic->ic_flags & IEEE80211_F_SIBSS) {
1950 if ((error = awi_mib(sc, AWI_CMD_GET_MIB,
1951 AWI_MIB_MGT, AWI_WAIT)) != 0)
1952 break;
1953 IEEE80211_ADDR_COPY(ni->ni_bssid,
1954 &sc->sc_mib_mgt.aCurrent_BSS_ID);
1955 } else {
1956 if (nstate == IEEE80211_S_RUN) {
1957 sc->sc_rx_timer = 10;
1958 ifp->if_timer = 1;
1959 }
1960 }
1961 error = 0;
1962 break;
1963 default:
1964 DPRINTF(("awi_newstate: unexpected state %s/%s\n",
1965 stname[nstate], substname[sc->sc_substate]));
1966 sc->sc_substate = AWI_ST_NONE;
1967 error = EIO;
1968 break;
1969 }
1970 goto out;
1971 }
1972
1973 sc->sc_substate = AWI_ST_NONE;
1974
1975 return (*sc->sc_newstate)(ic, nstate, arg);
1976 out:
1977 if (error != 0) {
1978 if (error == EINPROGRESS)
1979 error = 0;
1980 return error;
1981 }
1982 return (*sc->sc_newstate)(ic, nstate, arg);
1983 }
1984
1985 static void
1986 awi_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
1987 struct ieee80211_node *ni,
1988 int subtype, int rssi, u_int32_t rstamp)
1989 {
1990 struct awi_softc *sc = ic->ic_ifp->if_softc;
1991
1992 /* probe request is handled by hardware */
1993 if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ)
1994 return;
1995 (*sc->sc_recv_mgmt)(ic, m0, ni, subtype, rssi, rstamp);
1996 }
1997
1998 static int
1999 awi_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
2000 int type, int arg)
2001 {
2002 struct awi_softc *sc = ic->ic_ifp->if_softc;
2003
2004 /* probe request is handled by hardware */
2005 if (type == IEEE80211_FC0_SUBTYPE_PROBE_REQ)
2006 return 0;
2007 return (*sc->sc_send_mgmt)(ic, ni, type, arg);
2008 }
2009
2010 static struct mbuf *
2011 awi_ether_encap(struct awi_softc *sc, struct mbuf *m)
2012 {
2013 struct ieee80211com *ic = &sc->sc_ic;
2014 struct ieee80211_node *ni = ic->ic_bss;
2015 struct ether_header *eh;
2016 struct ieee80211_frame *wh;
2017
2018 if (m->m_len < sizeof(struct ether_header)) {
2019 m = m_pullup(m, sizeof(struct ether_header));
2020 if (m == NULL)
2021 return NULL;
2022 }
2023 eh = mtod(m, struct ether_header *);
2024 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
2025 if (m == NULL)
2026 return NULL;
2027 wh = mtod(m, struct ieee80211_frame *);
2028 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
2029 *(u_int16_t *)wh->i_dur = 0;
2030 *(u_int16_t *)wh->i_seq =
2031 htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);
2032 ni->ni_txseqs[0]++;
2033 if (ic->ic_opmode == IEEE80211_M_IBSS ||
2034 ic->ic_opmode == IEEE80211_M_AHDEMO) {
2035 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
2036 if (sc->sc_adhoc_ap)
2037 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
2038 else
2039 IEEE80211_ADDR_COPY(wh->i_addr1, eh->ether_dhost);
2040 IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost);
2041 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
2042 } else {
2043 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
2044 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
2045 IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost);
2046 IEEE80211_ADDR_COPY(wh->i_addr3, eh->ether_dhost);
2047 }
2048 return m;
2049 }
2050
2051 static struct mbuf *
2052 awi_ether_modcap(struct awi_softc *sc, struct mbuf *m)
2053 {
2054 struct ieee80211com *ic = &sc->sc_ic;
2055 struct ether_header eh;
2056 struct ieee80211_frame wh;
2057 struct llc *llc;
2058
2059 if (m->m_len < sizeof(wh) + sizeof(eh)) {
2060 m = m_pullup(m, sizeof(wh) + sizeof(eh));
2061 if (m == NULL)
2062 return NULL;
2063 }
2064 memcpy(&wh, mtod(m, void *), sizeof(wh));
2065 if (wh.i_fc[0] != (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA))
2066 return m;
2067 memcpy(&eh, mtod(m, char *) + sizeof(wh), sizeof(eh));
2068 m_adj(m, sizeof(eh) - sizeof(*llc));
2069 if (ic->ic_opmode == IEEE80211_M_IBSS ||
2070 ic->ic_opmode == IEEE80211_M_AHDEMO)
2071 IEEE80211_ADDR_COPY(wh.i_addr2, eh.ether_shost);
2072 memcpy(mtod(m, void *), &wh, sizeof(wh));
2073 llc = (struct llc *)(mtod(m, char *) + sizeof(wh));
2074 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
2075 llc->llc_control = LLC_UI;
2076 llc->llc_snap.org_code[0] = 0;
2077 llc->llc_snap.org_code[1] = 0;
2078 llc->llc_snap.org_code[2] = 0;
2079 llc->llc_snap.ether_type = eh.ether_type;
2080 return m;
2081 }
2082