wi.c revision 1.17.2.22 1 /* $NetBSD: wi.c,v 1.17.2.22 2002/12/29 20:49:17 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1997, 1998, 1999
5 * Bill Paul <wpaul (at) ctr.columbia.edu>. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*
36 * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for NetBSD.
37 *
38 * Original FreeBSD driver written by Bill Paul <wpaul (at) ctr.columbia.edu>
39 * Electrical Engineering Department
40 * Columbia University, New York City
41 */
42
43 /*
44 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
45 * from Lucent. Unlike the older cards, the new ones are programmed
46 * entirely via a firmware-driven controller called the Hermes.
47 * Unfortunately, Lucent will not release the Hermes programming manual
48 * without an NDA (if at all). What they do release is an API library
49 * called the HCF (Hardware Control Functions) which is supposed to
50 * do the device-specific operations of a device driver for you. The
51 * publically available version of the HCF library (the 'HCF Light') is
52 * a) extremely gross, b) lacks certain features, particularly support
53 * for 802.11 frames, and c) is contaminated by the GNU Public License.
54 *
55 * This driver does not use the HCF or HCF Light at all. Instead, it
56 * programs the Hermes controller directly, using information gleaned
57 * from the HCF Light code and corresponding documentation.
58 *
59 * This driver supports both the PCMCIA and ISA versions of the
60 * WaveLAN/IEEE cards. Note however that the ISA card isn't really
61 * anything of the sort: it's actually a PCMCIA bridge adapter
62 * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
63 * inserted. Consequently, you need to use the pccard support for
64 * both the ISA and PCMCIA adapters.
65 */
66
67 /*
68 * FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
69 * Oslo IETF plenary meeting.
70 */
71
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.17.2.22 2002/12/29 20:49:17 thorpej Exp $");
74
75 #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
76 #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
77
78 #include "bpfilter.h"
79
80 #include <sys/param.h>
81 #include <sys/systm.h>
82 #include <sys/callout.h>
83 #include <sys/device.h>
84 #include <sys/socket.h>
85 #include <sys/mbuf.h>
86 #include <sys/ioctl.h>
87 #include <sys/kernel.h> /* for hz */
88 #include <sys/proc.h>
89
90 #include <net/if.h>
91 #include <net/if_dl.h>
92 #include <net/if_media.h>
93 #include <net/if_ether.h>
94 #include <net/if_ieee80211.h>
95
96 #if NBPFILTER > 0
97 #include <net/bpf.h>
98 #include <net/bpfdesc.h>
99 #endif
100
101 #include <machine/bus.h>
102
103 #include <dev/ic/wi_ieee.h>
104 #include <dev/ic/wireg.h>
105 #include <dev/ic/wivar.h>
106
107 static int wi_init(struct ifnet *);
108 static void wi_stop(struct ifnet *, int);
109 static void wi_start(struct ifnet *);
110 static int wi_reset(struct wi_softc *);
111 static void wi_watchdog(struct ifnet *);
112 static int wi_ioctl(struct ifnet *, u_long, caddr_t);
113 static int wi_media_change(struct ifnet *);
114 static void wi_media_status(struct ifnet *, struct ifmediareq *);
115
116 static void wi_rx_intr(struct wi_softc *);
117 static void wi_tx_intr(struct wi_softc *);
118 static void wi_info_intr(struct wi_softc *);
119
120 static int wi_get_cfg(struct ifnet *, u_long, caddr_t);
121 static int wi_set_cfg(struct ifnet *, u_long, caddr_t);
122 static int wi_write_txrate(struct wi_softc *);
123 static int wi_write_wep(struct wi_softc *);
124 static int wi_write_multi(struct wi_softc *);
125 static int wi_alloc_fid(struct wi_softc *, int, int *);
126 static void wi_read_nicid(struct wi_softc *);
127 static int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
128
129 static int wi_cmd(struct wi_softc *, int, int, int, int);
130 static int wi_seek_bap(struct wi_softc *, int, int);
131 static int wi_read_bap(struct wi_softc *, int, int, void *, int);
132 static int wi_write_bap(struct wi_softc *, int, int, void *, int);
133 static int wi_read_rid(struct wi_softc *, int, void *, int *);
134 static int wi_write_rid(struct wi_softc *, int, void *, int);
135
136 static int wi_newstate(void *, enum ieee80211_state);
137
138 static int wi_scan_ap(struct wi_softc *);
139 static void wi_scan_result(struct wi_softc *, int, int);
140
141 static inline int
142 wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
143 {
144
145 val = htole16(val);
146 return wi_write_rid(sc, rid, &val, sizeof(val));
147 }
148
149 #ifdef WI_DEBUG
150 int wi_debug = 0;
151
152 #define DPRINTF(X) if (wi_debug) printf X
153 #define DPRINTF2(X) if (wi_debug > 1) printf X
154 #else
155 #define DPRINTF(X)
156 #define DPRINTF2(X)
157 #endif
158
159 #define WI_INTRS (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO)
160
161 struct wi_card_ident
162 wi_card_ident[] = {
163 /* CARD_ID CARD_NAME FIRM_TYPE */
164 { WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT },
165 { WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT },
166 { WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT },
167 { WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL },
168 { WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL },
169 { WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL },
170 { WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL },
171 { WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL },
172 { WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL },
173 { WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL },
174 { WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL },
175 { WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL },
176 { WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
177 { WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
178 { WI_NIC_3842_PCMCIA_ATM_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
179 { WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
180 { WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
181 { WI_NIC_3842_MINI_ATM_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
182 { WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
183 { WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
184 { WI_NIC_3842_PCI_ATM_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
185 { WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL },
186 { WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL },
187 { WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL },
188 { WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL },
189 { 0, NULL, 0 },
190 };
191
192 int
193 wi_attach(struct wi_softc *sc)
194 {
195 struct ieee80211com *ic = &sc->sc_ic;
196 struct ifnet *ifp = &ic->ic_if;
197 int i, nrate, mword, buflen;
198 u_int8_t r;
199 u_int16_t val;
200 u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
201 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
203 };
204 int s;
205
206 s = splnet();
207
208 /* Make sure interrupts are disabled. */
209 CSR_WRITE_2(sc, WI_INT_EN, 0);
210 CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
211
212 /* Reset the NIC. */
213 if (wi_reset(sc) != 0) {
214 splx(s);
215 return 1;
216 }
217
218 buflen = IEEE80211_ADDR_LEN;
219 if (wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen) != 0 ||
220 IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
221 printf(" could not get mac address, attach failed\n");
222 splx(s);
223 return 1;
224 }
225
226 printf(" 802.11 address %s\n", ether_sprintf(ic->ic_myaddr));
227
228 /* Read NIC identification */
229 wi_read_nicid(sc);
230
231 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
232 ifp->if_softc = sc;
233 ifp->if_start = wi_start;
234 ifp->if_ioctl = wi_ioctl;
235 ifp->if_watchdog = wi_watchdog;
236 ifp->if_init = wi_init;
237 ifp->if_stop = wi_stop;
238 ifp->if_flags =
239 IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST | IFF_NOTRAILERS;
240 IFQ_SET_READY(&ifp->if_snd);
241
242 ic->ic_phytype = IEEE80211_T_DS;
243 ic->ic_opmode = IEEE80211_M_STA;
244 ic->ic_flags = IEEE80211_F_HASPMGT | IEEE80211_F_HASAHDEMO;
245 ic->ic_state = IEEE80211_S_INIT;
246 ic->ic_newstate = wi_newstate;
247
248 /* Find available channel */
249 buflen = sizeof(val);
250 if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0)
251 val = htole16(0x1fff); /* assume 1-11 */
252 for (i = 0; i < 16; i++) {
253 if (isset((u_int8_t*)&val, i))
254 setbit(ic->ic_chan_avail, i + 1);
255 }
256
257 sc->sc_dbm_adjust = 100; /* default */
258
259 buflen = sizeof(val);
260 if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
261 wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0) {
262 sc->sc_dbm_adjust = le16toh(val);
263 }
264
265 /* Find default IBSS channel */
266 buflen = sizeof(val);
267 if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0)
268 ic->ic_ibss_chan = le16toh(val);
269 else {
270 /* use lowest available channel */
271 for (i = 0; i < 16; i++) {
272 if (isset(ic->ic_chan_avail, i))
273 break;
274 }
275 ic->ic_ibss_chan = i;
276 }
277
278 /*
279 * Set flags based on firmware version.
280 */
281 switch (sc->sc_firmware_type) {
282 case WI_LUCENT:
283 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
284 #ifdef WI_HERMES_AUTOINC_WAR
285 /* XXX: not confirmed, but never seen for recent firmware */
286 if (sc->sc_sta_firmware_ver < 40000) {
287 sc->sc_flags |= WI_FLAGS_BUG_AUTOINC;
288 }
289 #endif
290 if (sc->sc_sta_firmware_ver >= 60000)
291 sc->sc_flags |= WI_FLAGS_HAS_MOR;
292 if (sc->sc_sta_firmware_ver >= 60006)
293 ic->ic_flags |= IEEE80211_F_HASIBSS;
294 sc->sc_ibss_port = 1;
295 break;
296
297 case WI_INTERSIL:
298 sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
299 sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
300 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
301 if (sc->sc_sta_firmware_ver > 10101)
302 sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
303 if (sc->sc_sta_firmware_ver >= 800) {
304 ic->ic_flags |= IEEE80211_F_HASHOSTAP;
305 ic->ic_flags |= IEEE80211_F_HASIBSS;
306 }
307 sc->sc_ibss_port = 0;
308 break;
309
310 case WI_SYMBOL:
311 sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
312 if (sc->sc_sta_firmware_ver >= 20000)
313 ic->ic_flags |= IEEE80211_F_HASIBSS;
314 sc->sc_ibss_port = 4;
315 break;
316 }
317
318 /*
319 * Find out if we support WEP on this card.
320 */
321 buflen = sizeof(val);
322 if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 &&
323 val != htole16(0))
324 ic->ic_flags |= IEEE80211_F_HASWEP;
325
326 /* Find supported rates. */
327 buflen = sizeof(ratebuf);
328 if (wi_read_rid(sc, WI_RID_DATA_RATES, ratebuf, &buflen) == 0) {
329 nrate = le16toh(*(u_int16_t *)ratebuf);
330 if (nrate > IEEE80211_RATE_SIZE)
331 nrate = IEEE80211_RATE_SIZE;
332 memcpy(ic->ic_sup_rates, ratebuf + 2, nrate);
333 }
334 buflen = sizeof(val);
335
336 sc->sc_max_datalen = 2304;
337 sc->sc_rts_thresh = 2347;
338 sc->sc_frag_thresh = 2346;
339 sc->sc_system_scale = 1;
340 sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
341 sc->sc_roaming_mode = 1;
342
343 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
344 printf("%s: supported rates: ", sc->sc_dev.dv_xname);
345 #define ADD(s, o) ifmedia_add(&sc->sc_media, \
346 IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL)
347 ADD(IFM_AUTO, 0);
348 if (ic->ic_flags & IEEE80211_F_HASHOSTAP)
349 ADD(IFM_AUTO, IFM_IEEE80211_HOSTAP);
350 if (ic->ic_flags & IEEE80211_F_HASIBSS)
351 ADD(IFM_AUTO, IFM_IEEE80211_ADHOC);
352 ADD(IFM_AUTO, IFM_IEEE80211_ADHOC | IFM_FLAG0);
353 for (i = 0; i < nrate; i++) {
354 r = ic->ic_sup_rates[i];
355 mword = ieee80211_rate2media(r, IEEE80211_T_DS);
356 if (mword == 0)
357 continue;
358 printf("%s%d%sMbps", (i != 0 ? " " : ""),
359 (r & IEEE80211_RATE_VAL) / 2, ((r & 0x1) != 0 ? ".5" : ""));
360 ADD(mword, 0);
361 if (ic->ic_flags & IEEE80211_F_HASHOSTAP)
362 ADD(mword, IFM_IEEE80211_HOSTAP);
363 if (ic->ic_flags & IEEE80211_F_HASIBSS)
364 ADD(mword, IFM_IEEE80211_ADHOC);
365 ADD(mword, IFM_IEEE80211_ADHOC | IFM_FLAG0);
366 }
367 printf("\n");
368 ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
369 #undef ADD
370
371 /*
372 * Call MI attach routines.
373 */
374
375 if_attach(ifp);
376 ieee80211_ifattach(ifp);
377
378 /* Attach is successful. */
379 sc->sc_attached = 1;
380
381 splx(s);
382 return 0;
383 }
384
385 int
386 wi_detach(struct wi_softc *sc)
387 {
388 struct ifnet *ifp = &sc->sc_ic.ic_if;
389 int s;
390
391 if (!sc->sc_attached)
392 return 0;
393
394 s = splnet();
395
396 /* Delete all remaining media. */
397 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
398
399 ieee80211_ifdetach(ifp);
400 if_detach(ifp);
401 if (sc->sc_enabled) {
402 if (sc->sc_disable)
403 (*sc->sc_disable)(sc);
404 sc->sc_enabled = 0;
405 }
406 splx(s);
407 return 0;
408 }
409
410 int
411 wi_activate(struct device *self, enum devact act)
412 {
413 struct wi_softc *sc = (struct wi_softc *)self;
414 int rv = 0, s;
415
416 s = splnet();
417 switch (act) {
418 case DVACT_ACTIVATE:
419 rv = EOPNOTSUPP;
420 break;
421
422 case DVACT_DEACTIVATE:
423 if_deactivate(&sc->sc_ic.ic_if);
424 break;
425 }
426 splx(s);
427 return rv;
428 }
429
430 void
431 wi_power(struct wi_softc *sc, int why)
432 {
433 struct ifnet *ifp = &sc->sc_ic.ic_if;
434 int s;
435
436 s = splnet();
437 switch (why) {
438 case PWR_SUSPEND:
439 case PWR_STANDBY:
440 wi_stop(ifp, 1);
441 break;
442 case PWR_RESUME:
443 if (ifp->if_flags & IFF_UP) {
444 wi_init(ifp);
445 (void)wi_intr(sc);
446 }
447 break;
448 case PWR_SOFTSUSPEND:
449 case PWR_SOFTSTANDBY:
450 case PWR_SOFTRESUME:
451 break;
452 }
453 splx(s);
454 }
455
456 void
457 wi_shutdown(struct wi_softc *sc)
458 {
459 struct ifnet *ifp = &sc->sc_ic.ic_if;
460
461 if (sc->sc_attached)
462 wi_stop(ifp, 1);
463 }
464
465 int
466 wi_intr(void *arg)
467 {
468 int i;
469 struct wi_softc *sc = arg;
470 struct ifnet *ifp = &sc->sc_ic.ic_if;
471 u_int16_t status, raw_status, last_status;
472
473 if (sc->sc_enabled == 0 ||
474 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
475 (ifp->if_flags & IFF_RUNNING) == 0)
476 return 0;
477
478 if ((ifp->if_flags & IFF_UP) == 0) {
479 CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
480 CSR_WRITE_2(sc, WI_INT_EN, 0);
481 return 1;
482 }
483
484 /* maximum 10 loops per interrupt */
485 last_status = 0;
486 for (i = 0; i < 10; i++) {
487 /*
488 * Only believe a status bit when we enter wi_intr, or when
489 * the bit was "off" the last time through the loop. This is
490 * my strategy to avoid racing the hardware/firmware if I
491 * can re-read the event status register more quickly than
492 * it is updated.
493 */
494 raw_status = CSR_READ_2(sc, WI_EVENT_STAT);
495 status = raw_status & ~last_status;
496 if ((status & WI_INTRS) == 0)
497 break;
498 last_status = raw_status;
499
500 if (status & WI_EV_RX)
501 wi_rx_intr(sc);
502
503 if (status & WI_EV_ALLOC)
504 wi_tx_intr(sc);
505
506 if (status & WI_EV_INFO)
507 wi_info_intr(sc);
508
509 if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
510 (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
511 !IFQ_IS_EMPTY(&ifp->if_snd))
512 wi_start(ifp);
513 }
514
515 return 1;
516 }
517
518 static int
519 wi_init(struct ifnet *ifp)
520 {
521 struct wi_softc *sc = ifp->if_softc;
522 struct ieee80211com *ic = &sc->sc_ic;
523 struct wi_joinreq join;
524 int i;
525 int error = 0, wasenabled;
526
527 DPRINTF(("wi_init: enabled %d\n", sc->sc_enabled));
528 wasenabled = sc->sc_enabled;
529 if (!sc->sc_enabled) {
530 if ((error = (*sc->sc_enable)(sc)) != 0)
531 goto out;
532 sc->sc_enabled = 1;
533 } else
534 wi_stop(ifp, 0);
535
536 /* Symbol firmware cannot be initialized more than once */
537 if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
538 if ((error = wi_reset(sc)) != 0)
539 goto out;
540 }
541
542 /* common 802.11 configuration */
543 ic->ic_flags &= ~IEEE80211_F_IBSSON;
544 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
545 switch (ic->ic_opmode) {
546 case IEEE80211_M_STA:
547 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
548 break;
549 case IEEE80211_M_IBSS:
550 wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
551 ic->ic_flags |= IEEE80211_F_IBSSON;
552 break;
553 case IEEE80211_M_AHDEMO:
554 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
555 break;
556 case IEEE80211_M_HOSTAP:
557 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
558 break;
559 }
560
561 /* Intersil interprets this RID as joining ESS even in IBSS mode */
562 if (sc->sc_firmware_type == WI_LUCENT &&
563 (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0)
564 wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
565 else
566 wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
567 wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
568 wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid,
569 ic->ic_des_esslen);
570 wi_write_val(sc, WI_RID_OWN_CHNL, ic->ic_ibss_chan);
571 wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen);
572 IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
573 wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
574 wi_write_val(sc, WI_RID_PM_ENABLED,
575 (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
576
577 /* not yet common 802.11 configuration */
578 wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
579 wi_write_val(sc, WI_RID_RTS_THRESH, sc->sc_rts_thresh);
580 if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
581 wi_write_val(sc, WI_RID_FRAG_THRESH, sc->sc_frag_thresh);
582
583 /* driver specific 802.11 configuration */
584 if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)
585 wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale);
586 if (sc->sc_flags & WI_FLAGS_HAS_ROAMING)
587 wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode);
588 if (sc->sc_flags & WI_FLAGS_HAS_MOR)
589 wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven);
590 wi_write_txrate(sc);
591 wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
592
593 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
594 sc->sc_firmware_type == WI_INTERSIL) {
595 wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_lintval);
596 wi_write_val(sc, WI_RID_BASIC_RATE, 0x03); /* 1, 2 */
597 wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */
598 wi_write_val(sc, WI_RID_DTIM_PERIOD, 1);
599 }
600
601 /*
602 * Initialize promisc mode.
603 * Being in the Host-AP mode causes a great
604 * deal of pain if primisc mode is set.
605 * Therefore we avoid confusing the firmware
606 * and always reset promisc mode in Host-AP
607 * mode. Host-AP sees all the packets anyway.
608 */
609 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
610 (ifp->if_flags & IFF_PROMISC) != 0) {
611 wi_write_val(sc, WI_RID_PROMISC, 1);
612 } else {
613 wi_write_val(sc, WI_RID_PROMISC, 0);
614 }
615
616 /* Configure WEP. */
617 if (ic->ic_flags & IEEE80211_F_HASWEP)
618 wi_write_wep(sc);
619
620 /* Set multicast filter. */
621 wi_write_multi(sc);
622
623 if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
624 sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
625 if (sc->sc_firmware_type == WI_SYMBOL)
626 sc->sc_buflen = 1585; /* XXX */
627 for (i = 0; i < WI_NTXBUF; i++) {
628 error = wi_alloc_fid(sc, sc->sc_buflen,
629 &sc->sc_txd[i].d_fid);
630 if (error) {
631 printf("%s: tx buffer allocation failed\n",
632 sc->sc_dev.dv_xname);
633 goto out;
634 }
635 DPRINTF2(("wi_init: txbuf %d allocated %x\n", i,
636 sc->sc_txd[i].d_fid));
637 sc->sc_txd[i].d_len = 0;
638 }
639 }
640 sc->sc_txcur = sc->sc_txnext = 0;
641
642 /* Enable port 0 */
643 wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
644 ifp->if_flags |= IFF_RUNNING;
645 ifp->if_flags &= ~IFF_OACTIVE;
646 if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
647 ic->ic_opmode == IEEE80211_M_HOSTAP)
648 wi_newstate(sc, IEEE80211_S_RUN);
649
650 /* Enable interrupts */
651 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
652
653 if (!wasenabled &&
654 ic->ic_opmode == IEEE80211_M_HOSTAP &&
655 sc->sc_firmware_type == WI_INTERSIL) {
656 /* XXX: some card need to be re-enabled for hostap */
657 wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
658 wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
659 }
660
661 if (ic->ic_opmode == IEEE80211_M_STA &&
662 ((ic->ic_flags & IEEE80211_F_DESBSSID) ||
663 ic->ic_des_chan != IEEE80211_CHAN_ANY)) {
664 memset(&join, 0, sizeof(join));
665 if (ic->ic_flags & IEEE80211_F_DESBSSID)
666 IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
667 if (ic->ic_des_chan != IEEE80211_CHAN_ANY)
668 join.wi_chan = htole16(ic->ic_des_chan);
669 /* Lucent firmware does not support the JOIN RID. */
670 if (sc->sc_firmware_type != WI_LUCENT)
671 wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
672 }
673
674 out:
675 if (error) {
676 printf("%s: interface not running\n", sc->sc_dev.dv_xname);
677 wi_stop(ifp, 0);
678 }
679 DPRINTF(("wi_init: return %d\n", error));
680 return error;
681 }
682
683 static void
684 wi_stop(struct ifnet *ifp, int disable)
685 {
686 struct wi_softc *sc = ifp->if_softc;
687
688 DPRINTF(("wi_stop: disable %d\n", disable));
689 ieee80211_new_state(ifp, IEEE80211_S_INIT, -1);
690 if (sc->sc_enabled) {
691 CSR_WRITE_2(sc, WI_INT_EN, 0);
692 wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
693 if (disable) {
694 if (sc->sc_disable)
695 (*sc->sc_disable)(sc);
696 sc->sc_enabled = 0;
697 }
698 }
699
700 sc->sc_tx_timer = 0;
701 sc->sc_scan_timer = 0;
702 sc->sc_naps = 0;
703 ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
704 ifp->if_timer = 0;
705 }
706
707 static void
708 wi_start(struct ifnet *ifp)
709 {
710 struct wi_softc *sc = ifp->if_softc;
711 struct ieee80211com *ic = &sc->sc_ic;
712 struct ieee80211_node *ni;
713 struct ieee80211_frame *wh;
714 struct mbuf *m0, *m;
715 struct wi_frame frmhdr;
716 int cur, fid, off;
717
718 if (ifp->if_flags & IFF_OACTIVE)
719 return;
720 if (sc->sc_flags & WI_FLAGS_OUTRANGE)
721 return;
722
723 memset(&frmhdr, 0, sizeof(frmhdr));
724 cur = sc->sc_txnext;
725 for (;;) {
726 IF_POLL(&ic->ic_mgtq, m0);
727 if (m0 != NULL) {
728 if (sc->sc_txd[cur].d_len != 0) {
729 ifp->if_flags |= IFF_OACTIVE;
730 break;
731 }
732 IF_DEQUEUE(&ic->ic_mgtq, m0);
733 m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
734 (caddr_t)&frmhdr.wi_ehdr);
735 frmhdr.wi_ehdr.ether_type = 0;
736 wh = mtod(m0, struct ieee80211_frame *);
737 } else {
738 if (ic->ic_state != IEEE80211_S_RUN)
739 break;
740 IFQ_POLL(&ifp->if_snd, m0);
741 if (m0 == NULL)
742 break;
743 if (sc->sc_txd[cur].d_len != 0) {
744 ifp->if_flags |= IFF_OACTIVE;
745 break;
746 }
747 IFQ_DEQUEUE(&ifp->if_snd, m0);
748 ifp->if_opackets++;
749 m_copydata(m0, 0, ETHER_HDR_LEN,
750 (caddr_t)&frmhdr.wi_ehdr);
751 #if NBPFILTER > 0
752 if (ifp->if_bpf)
753 bpf_mtap(ifp->if_bpf, m0);
754 #endif
755
756 if ((m0 = ieee80211_encap(ifp, m0)) == NULL) {
757 ifp->if_oerrors++;
758 continue;
759 }
760 wh = mtod(m0, struct ieee80211_frame *);
761 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
762 !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
763 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
764 IEEE80211_FC0_TYPE_DATA &&
765 ((ni = ieee80211_find_node(ic, wh->i_addr1)) ==
766 NULL || ni->ni_associd == 0)) {
767 m_freem(m0);
768 ifp->if_oerrors++;
769 continue;
770 }
771 if (ic->ic_flags & IEEE80211_F_WEPON)
772 wh->i_fc[1] |= IEEE80211_FC1_WEP;
773
774 }
775 #if NBPFILTER > 0
776 if (ic->ic_rawbpf)
777 bpf_mtap(ic->ic_rawbpf, m0);
778 #endif
779 frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11);
780 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
781 (wh->i_fc[1] & IEEE80211_FC1_WEP)) {
782 if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) {
783 ifp->if_oerrors++;
784 continue;
785 }
786 frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
787 }
788 m_copydata(m0, 0, sizeof(struct ieee80211_frame),
789 (caddr_t)&frmhdr.wi_whdr);
790 m_adj(m0, sizeof(struct ieee80211_frame));
791 frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
792 #if NBPFILTER > 0
793 if (sc->sc_drvbpf) {
794 struct mbuf mb;
795
796 M_COPY_PKTHDR(&mb, m0);
797 mb.m_data = (caddr_t)&frmhdr;
798 mb.m_len = sizeof(frmhdr);
799 mb.m_next = m0;
800 mb.m_pkthdr.len += mb.m_len;
801 bpf_mtap(sc->sc_drvbpf, &mb);
802 }
803 #endif
804 fid = sc->sc_txd[cur].d_fid;
805 wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr));
806 off = sizeof(frmhdr);
807 for (m = m0; m != NULL; m = m->m_next) {
808 if (m->m_len == 0)
809 continue;
810 wi_write_bap(sc, fid, off, m->m_data, m->m_len);
811 off += m->m_len;
812 }
813 m_freem(m0);
814 sc->sc_txd[cur].d_len = off;
815 if (sc->sc_txcur == cur) {
816 if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
817 printf("%s: xmit failed\n",
818 sc->sc_dev.dv_xname);
819 sc->sc_txd[cur].d_len = 0;
820 continue;
821 }
822 sc->sc_tx_timer = 5;
823 ifp->if_timer = 1;
824 }
825 sc->sc_txnext = cur = (cur + 1) % WI_NTXBUF;
826 }
827 }
828
829
830 static int
831 wi_reset(struct wi_softc *sc)
832 {
833 int i, error;
834
835 DPRINTF(("wi_reset\n"));
836 error = 0;
837 for (i = 0; i < 5; i++) {
838 DELAY(20*1000); /* XXX: way too long! */
839 if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
840 break;
841 }
842 if (error) {
843 printf("%s: init failed\n", sc->sc_dev.dv_xname);
844 return error;
845 }
846 CSR_WRITE_2(sc, WI_INT_EN, 0);
847 CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
848
849 /* Calibrate timer. */
850 wi_write_val(sc, WI_RID_TICK_TIME, 0);
851 return 0;
852 }
853
854 static void
855 wi_watchdog(struct ifnet *ifp)
856 {
857 struct wi_softc *sc = ifp->if_softc;
858
859 ifp->if_timer = 0;
860 if (!sc->sc_enabled)
861 return;
862
863 if (sc->sc_tx_timer) {
864 if (--sc->sc_tx_timer == 0) {
865 printf("%s: device timeout\n", ifp->if_xname);
866 ifp->if_oerrors++;
867 wi_init(ifp);
868 return;
869 }
870 ifp->if_timer = 1;
871 }
872
873 if (sc->sc_scan_timer) {
874 if (--sc->sc_scan_timer <= WI_SCAN_WAIT - WI_SCAN_INQWAIT &&
875 sc->sc_firmware_type == WI_INTERSIL) {
876 DPRINTF(("wi_watchdog: inquire scan\n"));
877 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
878 }
879 if (sc->sc_scan_timer)
880 ifp->if_timer = 1;
881 }
882
883 /* TODO: rate control */
884 ieee80211_watchdog(ifp);
885 }
886
887 static int
888 wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
889 {
890 struct wi_softc *sc = ifp->if_softc;
891 struct ieee80211com *ic = &sc->sc_ic;
892 struct ifreq *ifr = (struct ifreq *)data;
893 int s, error = 0;
894
895 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
896 return ENXIO;
897
898 s = splnet();
899
900 switch (cmd) {
901 case SIOCSIFFLAGS:
902 if (ifp->if_flags & IFF_UP) {
903 if (sc->sc_enabled) {
904 /*
905 * To avoid rescanning another access point,
906 * do not call wi_init() here. Instead,
907 * only reflect promisc mode settings.
908 */
909 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
910 (ifp->if_flags & IFF_PROMISC) != 0)
911 wi_write_val(sc, WI_RID_PROMISC, 1);
912 else
913 wi_write_val(sc, WI_RID_PROMISC, 0);
914 } else
915 error = wi_init(ifp);
916 } else if (sc->sc_enabled)
917 wi_stop(ifp, 1);
918 break;
919 case SIOCSIFMEDIA:
920 case SIOCGIFMEDIA:
921 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
922 break;
923 case SIOCADDMULTI:
924 case SIOCDELMULTI:
925 error = (cmd == SIOCADDMULTI) ?
926 ether_addmulti(ifr, &sc->sc_ic.ic_ec) :
927 ether_delmulti(ifr, &sc->sc_ic.ic_ec);
928 if (error == ENETRESET) {
929 if (sc->sc_enabled) {
930 /* do not rescan */
931 error = wi_write_multi(sc);
932 } else
933 error = 0;
934 }
935 break;
936 case SIOCGIFGENERIC:
937 error = wi_get_cfg(ifp, cmd, data);
938 break;
939 case SIOCSIFGENERIC:
940 error = suser(curproc->p_ucred, &curproc->p_acflag);
941 if (error)
942 break;
943 error = wi_set_cfg(ifp, cmd, data);
944 if (error == ENETRESET) {
945 if (sc->sc_enabled)
946 error = wi_init(ifp);
947 else
948 error = 0;
949 }
950 break;
951 case SIOCS80211BSSID:
952 /* No use pretending that Lucent firmware supports
953 * 802.11 MLME-JOIN.request.
954 */
955 if (sc->sc_firmware_type == WI_LUCENT) {
956 error = ENODEV;
957 break;
958 }
959 /* fall through */
960 default:
961 error = ieee80211_ioctl(ifp, cmd, data);
962 if (error == ENETRESET) {
963 if (sc->sc_enabled)
964 error = wi_init(ifp);
965 else
966 error = 0;
967 }
968 break;
969 }
970 splx(s);
971 return error;
972 }
973
974 static int
975 wi_media_change(struct ifnet *ifp)
976 {
977 struct wi_softc *sc = ifp->if_softc;
978 struct ieee80211com *ic = &sc->sc_ic;
979 struct ifmedia_entry *ime;
980 enum ieee80211_opmode newmode;
981 int i, rate, error = 0;
982
983 ime = sc->sc_media.ifm_cur;
984 if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) {
985 i = -1;
986 } else {
987 rate = ieee80211_media2rate(ime->ifm_media, IEEE80211_T_DS);
988 if (rate == 0)
989 return EINVAL;
990 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
991 if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) == rate)
992 break;
993 }
994 if (i == IEEE80211_RATE_SIZE)
995 return EINVAL;
996 }
997 if (ic->ic_fixed_rate != i) {
998 ic->ic_fixed_rate = i;
999 error = ENETRESET;
1000 }
1001
1002 if ((ime->ifm_media & IFM_IEEE80211_ADHOC) &&
1003 (ime->ifm_media & IFM_FLAG0))
1004 newmode = IEEE80211_M_AHDEMO;
1005 else if (ime->ifm_media & IFM_IEEE80211_ADHOC)
1006 newmode = IEEE80211_M_IBSS;
1007 else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
1008 newmode = IEEE80211_M_HOSTAP;
1009 else
1010 newmode = IEEE80211_M_STA;
1011 if (ic->ic_opmode != newmode) {
1012 ic->ic_opmode = newmode;
1013 error = ENETRESET;
1014 }
1015 if (error == ENETRESET) {
1016 if (sc->sc_enabled)
1017 error = wi_init(ifp);
1018 else
1019 error = 0;
1020 }
1021 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
1022
1023 return error;
1024 }
1025
1026 static void
1027 wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1028 {
1029 struct wi_softc *sc = ifp->if_softc;
1030 struct ieee80211com *ic = &sc->sc_ic;
1031 u_int16_t val;
1032 int rate, len;
1033
1034 if (sc->sc_enabled == 0) {
1035 imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
1036 imr->ifm_status = 0;
1037 return;
1038 }
1039
1040 imr->ifm_status = IFM_AVALID;
1041 imr->ifm_active = IFM_IEEE80211;
1042 if (ic->ic_state == IEEE80211_S_RUN &&
1043 (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0)
1044 imr->ifm_status |= IFM_ACTIVE;
1045 len = sizeof(val);
1046 if (wi_read_rid(sc, WI_RID_CUR_TX_RATE, &val, &len) != 0)
1047 rate = 0;
1048 else {
1049 /* convert to 802.11 rate */
1050 rate = val * 2;
1051 if (sc->sc_firmware_type == WI_LUCENT) {
1052 if (rate == 10)
1053 rate = 11; /* 5.5Mbps */
1054 } else {
1055 if (rate == 4*2)
1056 rate = 11; /* 5.5Mbps */
1057 else if (rate == 8*2)
1058 rate = 22; /* 11Mbps */
1059 }
1060 }
1061 imr->ifm_active |= ieee80211_rate2media(rate, IEEE80211_T_DS);
1062 switch (ic->ic_opmode) {
1063 case IEEE80211_M_STA:
1064 break;
1065 case IEEE80211_M_IBSS:
1066 imr->ifm_active |= IFM_IEEE80211_ADHOC;
1067 break;
1068 case IEEE80211_M_AHDEMO:
1069 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
1070 break;
1071 case IEEE80211_M_HOSTAP:
1072 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
1073 break;
1074 }
1075 }
1076
1077 static void
1078 wi_rx_intr(struct wi_softc *sc)
1079 {
1080 struct ieee80211com *ic = &sc->sc_ic;
1081 struct ifnet *ifp = &ic->ic_if;
1082 struct wi_frame frmhdr;
1083 struct mbuf *m;
1084 struct ieee80211_frame *wh;
1085 int fid, len, off, rssi;
1086 u_int16_t status;
1087 u_int32_t rstamp;
1088
1089 fid = CSR_READ_2(sc, WI_RX_FID);
1090
1091 /* First read in the frame header */
1092 if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
1093 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1094 ifp->if_ierrors++;
1095 DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
1096 return;
1097 }
1098
1099 /*
1100 * Drop undecryptable or packets with receive errors here
1101 */
1102 status = le16toh(frmhdr.wi_status);
1103 if (status & WI_STAT_ERRSTAT) {
1104 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1105 ifp->if_ierrors++;
1106 DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
1107 return;
1108 }
1109 rssi = frmhdr.wi_rx_signal;
1110 rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
1111 le16toh(frmhdr.wi_rx_tstamp1);
1112
1113 len = le16toh(frmhdr.wi_dat_len);
1114 off = ALIGN(sizeof(struct ieee80211_frame));
1115
1116 MGETHDR(m, M_DONTWAIT, MT_DATA);
1117 if (m == NULL) {
1118 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1119 ifp->if_ierrors++;
1120 DPRINTF(("wi_rx_intr: MGET failed\n"));
1121 return;
1122 }
1123 if (off + len > MHLEN) {
1124 MCLGET(m, M_DONTWAIT);
1125 if ((m->m_flags & M_EXT) == 0) {
1126 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1127 m_freem(m);
1128 ifp->if_ierrors++;
1129 DPRINTF(("wi_rx_intr: MCLGET failed\n"));
1130 return;
1131 }
1132 }
1133
1134 m->m_data += off - sizeof(struct ieee80211_frame);
1135 memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame));
1136 wi_read_bap(sc, fid, sizeof(frmhdr),
1137 m->m_data + sizeof(struct ieee80211_frame), len);
1138 m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
1139 m->m_pkthdr.rcvif = ifp;
1140
1141 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1142
1143 #if NBPFILTER > 0
1144 if (sc->sc_drvbpf) {
1145 struct mbuf mb;
1146
1147 M_COPY_PKTHDR(&mb, m);
1148 mb.m_data = (caddr_t)&frmhdr;
1149 mb.m_len = sizeof(frmhdr);
1150 mb.m_next = m;
1151 mb.m_pkthdr.len += mb.m_len;
1152 bpf_mtap(sc->sc_drvbpf, &mb);
1153 }
1154 #endif
1155 wh = mtod(m, struct ieee80211_frame *);
1156 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1157 /*
1158 * WEP is decrypted by hardware. Clear WEP bit
1159 * header for ieee80211_input().
1160 */
1161 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
1162 }
1163 ieee80211_input(ifp, m, rssi, rstamp);
1164 }
1165
1166 static void
1167 wi_tx_intr(struct wi_softc *sc)
1168 {
1169 struct ieee80211com *ic = &sc->sc_ic;
1170 struct ifnet *ifp = &ic->ic_if;
1171 int fid, cur;
1172
1173 fid = CSR_READ_2(sc, WI_ALLOC_FID);
1174 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1175
1176 cur = sc->sc_txcur;
1177 if (sc->sc_txd[cur].d_fid != fid) {
1178 printf("%s: bad alloc %x != %x, cur %d nxt %d\n",
1179 sc->sc_dev.dv_xname, fid, sc->sc_txd[cur].d_fid, cur,
1180 sc->sc_txnext);
1181 return;
1182 }
1183 sc->sc_tx_timer = 0;
1184 sc->sc_txd[cur].d_len = 0;
1185 sc->sc_txcur = cur = (cur + 1) % WI_NTXBUF;
1186 if (sc->sc_txd[cur].d_len == 0)
1187 ifp->if_flags &= ~IFF_OACTIVE;
1188 else {
1189 if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
1190 0, 0)) {
1191 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
1192 sc->sc_txd[cur].d_len = 0;
1193 } else {
1194 sc->sc_tx_timer = 5;
1195 ifp->if_timer = 1;
1196 }
1197 }
1198 }
1199
1200 static void
1201 wi_info_intr(struct wi_softc *sc)
1202 {
1203 struct ieee80211com *ic = &sc->sc_ic;
1204 struct ifnet *ifp = &ic->ic_if;
1205 int i, fid, len, off;
1206 u_int16_t ltbuf[2];
1207 u_int16_t stat;
1208 u_int32_t *ptr;
1209
1210 fid = CSR_READ_2(sc, WI_INFO_FID);
1211 wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
1212
1213 switch (le16toh(ltbuf[1])) {
1214
1215 case WI_INFO_LINK_STAT:
1216 wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
1217 DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
1218 switch (le16toh(stat)) {
1219 case CONNECTED:
1220 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
1221 if (ic->ic_state == IEEE80211_S_RUN &&
1222 ic->ic_opmode != IEEE80211_M_IBSS)
1223 break;
1224 /* FALLTHROUGH */
1225 case AP_CHANGE:
1226 ieee80211_new_state(ifp, IEEE80211_S_RUN, -1);
1227 break;
1228 case AP_IN_RANGE:
1229 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
1230 break;
1231 case AP_OUT_OF_RANGE:
1232 if (sc->sc_firmware_type == WI_SYMBOL &&
1233 sc->sc_scan_timer > 0) {
1234 if (wi_cmd(sc, WI_CMD_INQUIRE,
1235 WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0)
1236 sc->sc_scan_timer = 0;
1237 break;
1238 }
1239 if (ic->ic_opmode == IEEE80211_M_STA)
1240 sc->sc_flags |= WI_FLAGS_OUTRANGE;
1241 break;
1242 case DISCONNECTED:
1243 case ASSOC_FAILED:
1244 if (ic->ic_opmode == IEEE80211_M_STA)
1245 ieee80211_new_state(ifp, IEEE80211_S_INIT, -1);
1246 break;
1247 }
1248 break;
1249
1250 case WI_INFO_COUNTERS:
1251 /* some card versions have a larger stats structure */
1252 len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
1253 ptr = (u_int32_t *)&sc->sc_stats;
1254 off = sizeof(ltbuf);
1255 for (i = 0; i < len; i++, off += 2, ptr++) {
1256 wi_read_bap(sc, fid, off, &stat, sizeof(stat));
1257 #ifdef WI_HERMES_STATS_WAR
1258 if (stat & 0xf000)
1259 stat = ~stat;
1260 #endif
1261 *ptr += stat;
1262 }
1263 ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
1264 sc->sc_stats.wi_tx_multi_retries +
1265 sc->sc_stats.wi_tx_retry_limit;
1266 break;
1267
1268 case WI_INFO_SCAN_RESULTS:
1269 case WI_INFO_HOST_SCAN_RESULTS:
1270 wi_scan_result(sc, fid, le16toh(ltbuf[0]));
1271 break;
1272
1273 default:
1274 DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
1275 le16toh(ltbuf[1]), le16toh(ltbuf[0])));
1276 break;
1277 }
1278 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
1279 }
1280
1281 /*
1282 * Allocate a region of memory inside the NIC and zero
1283 * it out.
1284 */
1285 static int
1286 wi_write_multi(struct wi_softc *sc)
1287 {
1288 struct ifnet *ifp = &sc->sc_ic.ic_if;
1289 int n = 0;
1290 struct wi_mcast mlist;
1291 struct ether_multi *enm;
1292 struct ether_multistep estep;
1293
1294 if ((ifp->if_flags & IFF_PROMISC) != 0) {
1295 allmulti:
1296 ifp->if_flags |= IFF_ALLMULTI;
1297 memset(&mlist, 0, sizeof(mlist));
1298 return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1299 sizeof(mlist));
1300 }
1301
1302 n = 0;
1303 ETHER_FIRST_MULTI(estep, &sc->sc_ic.ic_ec, enm);
1304 while (enm != NULL) {
1305 /* Punt on ranges or too many multicast addresses. */
1306 if (!IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi) ||
1307 n >= sizeof(mlist) / sizeof(mlist.wi_mcast[0]))
1308 goto allmulti;
1309
1310 IEEE80211_ADDR_COPY(&mlist.wi_mcast[n], enm->enm_addrlo);
1311 n++;
1312 ETHER_NEXT_MULTI(estep, enm);
1313 }
1314 ifp->if_flags &= ~IFF_ALLMULTI;
1315 return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1316 IEEE80211_ADDR_LEN * n);
1317 }
1318
1319
1320 static void
1321 wi_read_nicid(sc)
1322 struct wi_softc *sc;
1323 {
1324 struct wi_card_ident *id;
1325 char *p;
1326 int len;
1327 u_int16_t ver[4];
1328
1329 /* getting chip identity */
1330 memset(ver, 0, sizeof(ver));
1331 len = sizeof(ver);
1332 wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
1333 printf("%s: using ", sc->sc_dev.dv_xname);
1334 DPRINTF2(("wi_read_nicid: CARD_ID: %x %x %x %x\n", le16toh(ver[0]), le16toh(ver[1]), le16toh(ver[2]), le16toh(ver[3])));
1335
1336 sc->sc_firmware_type = WI_NOTYPE;
1337 for (id = wi_card_ident; id->card_name != NULL; id++) {
1338 if (le16toh(ver[0]) == id->card_id) {
1339 printf("%s", id->card_name);
1340 sc->sc_firmware_type = id->firm_type;
1341 break;
1342 }
1343 }
1344 if (sc->sc_firmware_type == WI_NOTYPE) {
1345 if (le16toh(ver[0]) & 0x8000) {
1346 printf("Unknown PRISM2 chip");
1347 sc->sc_firmware_type = WI_INTERSIL;
1348 } else {
1349 printf("Unknown Lucent chip");
1350 sc->sc_firmware_type = WI_LUCENT;
1351 }
1352 }
1353
1354 /* get primary firmware version (Only Prism chips) */
1355 if (sc->sc_firmware_type != WI_LUCENT) {
1356 memset(ver, 0, sizeof(ver));
1357 len = sizeof(ver);
1358 wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
1359 sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
1360 le16toh(ver[3]) * 100 + le16toh(ver[1]);
1361 DPRINTF2(("wi_read_nicid: PRI_ID: %x %x %x %x\n", le16toh(ver[0]), le16toh(ver[1]), le16toh(ver[2]), le16toh(ver[3])));
1362 }
1363
1364 /* get station firmware version */
1365 memset(ver, 0, sizeof(ver));
1366 len = sizeof(ver);
1367 wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
1368 sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
1369 le16toh(ver[3]) * 100 + le16toh(ver[1]);
1370 DPRINTF2(("wi_read_nicid: STA_ID: %x %x %x %x\n", le16toh(ver[0]), le16toh(ver[1]), le16toh(ver[2]), le16toh(ver[3])));
1371 if (sc->sc_firmware_type == WI_INTERSIL &&
1372 (sc->sc_sta_firmware_ver == 10102 ||
1373 sc->sc_sta_firmware_ver == 20102)) {
1374 char ident[12];
1375 memset(ident, 0, sizeof(ident));
1376 len = sizeof(ident);
1377 /* value should be the format like "V2.00-11" */
1378 if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
1379 *(p = (char *)ident) >= 'A' &&
1380 p[2] == '.' && p[5] == '-' && p[8] == '\0') {
1381 sc->sc_firmware_type = WI_SYMBOL;
1382 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
1383 (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
1384 (p[6] - '0') * 10 + (p[7] - '0');
1385 }
1386 DPRINTF2(("wi_read_nicid: SYMBOL_ID: %x %x %x %x\n", le16toh(ident[0]), le16toh(ident[1]), le16toh(ident[2]), le16toh(ident[3])));
1387 }
1388
1389 printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
1390 sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
1391 (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
1392 if (sc->sc_firmware_type != WI_LUCENT) /* XXX */
1393 printf("Primary (%u.%u.%u), ",
1394 sc->sc_pri_firmware_ver / 10000,
1395 (sc->sc_pri_firmware_ver % 10000) / 100,
1396 sc->sc_pri_firmware_ver % 100);
1397 printf("Station (%u.%u.%u)\n",
1398 sc->sc_sta_firmware_ver / 10000,
1399 (sc->sc_sta_firmware_ver % 10000) / 100,
1400 sc->sc_sta_firmware_ver % 100);
1401 }
1402
1403 static int
1404 wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
1405 {
1406 struct wi_ssid ssid;
1407
1408 if (buflen > IEEE80211_NWID_LEN)
1409 return ENOBUFS;
1410 memset(&ssid, 0, sizeof(ssid));
1411 ssid.wi_len = htole16(buflen);
1412 memcpy(ssid.wi_ssid, buf, buflen);
1413 return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
1414 }
1415
1416 static int
1417 wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
1418 {
1419 struct wi_softc *sc = ifp->if_softc;
1420 struct ieee80211com *ic = &sc->sc_ic;
1421 struct ifreq *ifr = (struct ifreq *)data;
1422 struct wi_req wreq;
1423 int len, n, error;
1424
1425 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1426 if (error)
1427 return error;
1428 len = (wreq.wi_len - 1) * 2;
1429 if (len < sizeof(u_int16_t))
1430 return ENOSPC;
1431 if (len > sizeof(wreq.wi_val))
1432 len = sizeof(wreq.wi_val);
1433
1434 switch (wreq.wi_type) {
1435
1436 case WI_RID_IFACE_STATS:
1437 memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
1438 if (len < sizeof(sc->sc_stats))
1439 error = ENOSPC;
1440 else
1441 len = sizeof(sc->sc_stats);
1442 break;
1443
1444 case WI_RID_ENCRYPTION:
1445 case WI_RID_TX_CRYPT_KEY:
1446 case WI_RID_DEFLT_CRYPT_KEYS:
1447 case WI_RID_TX_RATE:
1448 return ieee80211_cfgget(ifp, cmd, data);
1449
1450 case WI_RID_MICROWAVE_OVEN:
1451 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
1452 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1453 &len);
1454 break;
1455 }
1456 wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
1457 len = sizeof(u_int16_t);
1458 break;
1459
1460 case WI_RID_DBM_ADJUST:
1461 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
1462 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1463 &len);
1464 break;
1465 }
1466 wreq.wi_val[0] = htole16(sc->sc_dbm_adjust);
1467 len = sizeof(u_int16_t);
1468 break;
1469
1470 case WI_RID_ROAMING_MODE:
1471 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
1472 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1473 &len);
1474 break;
1475 }
1476 wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
1477 len = sizeof(u_int16_t);
1478 break;
1479
1480 case WI_RID_SYSTEM_SCALE:
1481 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
1482 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1483 &len);
1484 break;
1485 }
1486 wreq.wi_val[0] = htole16(sc->sc_system_scale);
1487 len = sizeof(u_int16_t);
1488 break;
1489
1490 case WI_RID_FRAG_THRESH:
1491 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
1492 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1493 &len);
1494 break;
1495 }
1496 wreq.wi_val[0] = htole16(sc->sc_frag_thresh);
1497 len = sizeof(u_int16_t);
1498 break;
1499
1500 case WI_RID_READ_APS:
1501 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1502 return ieee80211_cfgget(ifp, cmd, data);
1503 if (sc->sc_scan_timer > 0) {
1504 error = EINPROGRESS;
1505 break;
1506 }
1507 n = sc->sc_naps;
1508 if (len < sizeof(n)) {
1509 error = ENOSPC;
1510 break;
1511 }
1512 if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
1513 n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
1514 len = sizeof(n) + sizeof(struct wi_apinfo) * n;
1515 memcpy(wreq.wi_val, &n, sizeof(n));
1516 memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps,
1517 sizeof(struct wi_apinfo) * n);
1518 break;
1519
1520 default:
1521 if (sc->sc_enabled) {
1522 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1523 &len);
1524 break;
1525 }
1526 switch (wreq.wi_type) {
1527 case WI_RID_MAX_DATALEN:
1528 wreq.wi_val[0] = htole16(sc->sc_max_datalen);
1529 len = sizeof(u_int16_t);
1530 break;
1531 case WI_RID_RTS_THRESH:
1532 wreq.wi_val[0] = htole16(sc->sc_rts_thresh);
1533 len = sizeof(u_int16_t);
1534 break;
1535 case WI_RID_CNFAUTHMODE:
1536 wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
1537 len = sizeof(u_int16_t);
1538 break;
1539 case WI_RID_NODENAME:
1540 if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
1541 error = ENOSPC;
1542 break;
1543 }
1544 len = sc->sc_nodelen + sizeof(u_int16_t);
1545 wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
1546 memcpy(&wreq.wi_val[1], sc->sc_nodename,
1547 sc->sc_nodelen);
1548 break;
1549 default:
1550 return ieee80211_cfgget(ifp, cmd, data);
1551 }
1552 break;
1553 }
1554 if (error)
1555 return error;
1556 wreq.wi_len = (len + 1) / 2 + 1;
1557 return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
1558 }
1559
1560 static int
1561 wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
1562 {
1563 struct wi_softc *sc = ifp->if_softc;
1564 struct ieee80211com *ic = &sc->sc_ic;
1565 struct ifreq *ifr = (struct ifreq *)data;
1566 struct wi_req wreq;
1567 struct mbuf *m;
1568 int i, len, error;
1569
1570 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1571 if (error)
1572 return error;
1573 len = (wreq.wi_len - 1) * 2;
1574 switch (wreq.wi_type) {
1575 case WI_RID_DBM_ADJUST:
1576 return ENODEV;
1577
1578 case WI_RID_NODENAME:
1579 if (le16toh(wreq.wi_val[0]) * 2 > len ||
1580 le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
1581 error = ENOSPC;
1582 break;
1583 }
1584 if (sc->sc_enabled) {
1585 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
1586 len);
1587 if (error)
1588 break;
1589 }
1590 sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
1591 memcpy(sc->sc_nodename, &wreq.wi_val[1], sc->sc_nodelen);
1592 break;
1593
1594 case WI_RID_MICROWAVE_OVEN:
1595 case WI_RID_ROAMING_MODE:
1596 case WI_RID_SYSTEM_SCALE:
1597 case WI_RID_FRAG_THRESH:
1598 if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
1599 (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
1600 break;
1601 if (wreq.wi_type == WI_RID_ROAMING_MODE &&
1602 (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
1603 break;
1604 if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
1605 (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
1606 break;
1607 if (wreq.wi_type == WI_RID_FRAG_THRESH &&
1608 (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
1609 break;
1610 /* FALLTHROUGH */
1611 case WI_RID_RTS_THRESH:
1612 case WI_RID_CNFAUTHMODE:
1613 case WI_RID_MAX_DATALEN:
1614 if (sc->sc_enabled) {
1615 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
1616 sizeof(u_int16_t));
1617 if (error)
1618 break;
1619 }
1620 switch (wreq.wi_type) {
1621 case WI_RID_FRAG_THRESH:
1622 sc->sc_frag_thresh = le16toh(wreq.wi_val[0]);
1623 break;
1624 case WI_RID_RTS_THRESH:
1625 sc->sc_rts_thresh = le16toh(wreq.wi_val[0]);
1626 break;
1627 case WI_RID_MICROWAVE_OVEN:
1628 sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
1629 break;
1630 case WI_RID_ROAMING_MODE:
1631 sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
1632 break;
1633 case WI_RID_SYSTEM_SCALE:
1634 sc->sc_system_scale = le16toh(wreq.wi_val[0]);
1635 break;
1636 case WI_RID_CNFAUTHMODE:
1637 sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
1638 break;
1639 case WI_RID_MAX_DATALEN:
1640 sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
1641 break;
1642 }
1643 break;
1644
1645 case WI_RID_TX_RATE:
1646 switch (le16toh(wreq.wi_val[0])) {
1647 case 3:
1648 ic->ic_fixed_rate = -1;
1649 break;
1650 default:
1651 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
1652 if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL)
1653 / 2 == le16toh(wreq.wi_val[0]))
1654 break;
1655 }
1656 if (i == IEEE80211_RATE_SIZE)
1657 return EINVAL;
1658 ic->ic_fixed_rate = i;
1659 }
1660 if (sc->sc_enabled)
1661 error = wi_write_txrate(sc);
1662 break;
1663
1664 case WI_RID_SCAN_APS:
1665 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
1666 error = wi_scan_ap(sc);
1667 break;
1668
1669 case WI_RID_MGMT_XMIT:
1670 if (!sc->sc_enabled) {
1671 error = ENETDOWN;
1672 break;
1673 }
1674 if (ic->ic_mgtq.ifq_len > 5) {
1675 error = EAGAIN;
1676 break;
1677 }
1678 /* XXX wi_len looks in u_int8_t, not in u_int16_t */
1679 m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0, ifp, NULL);
1680 if (m == NULL) {
1681 error = ENOMEM;
1682 break;
1683 }
1684 IF_ENQUEUE(&ic->ic_mgtq, m);
1685 break;
1686
1687 default:
1688 if (sc->sc_enabled) {
1689 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
1690 len);
1691 if (error)
1692 break;
1693 }
1694 error = ieee80211_cfgset(ifp, cmd, data);
1695 break;
1696 }
1697 return error;
1698 }
1699
1700 static int
1701 wi_write_txrate(struct wi_softc *sc)
1702 {
1703 struct ieee80211com *ic = &sc->sc_ic;
1704 int i;
1705 u_int16_t rate;
1706
1707 if (ic->ic_fixed_rate < 0)
1708 rate = 0; /* auto */
1709 else
1710 rate = (ic->ic_sup_rates[ic->ic_fixed_rate] &
1711 IEEE80211_RATE_VAL) / 2;
1712
1713 /* rate: 0, 1, 2, 5, 11 */
1714
1715 switch (sc->sc_firmware_type) {
1716 case WI_LUCENT:
1717 if (rate == 0)
1718 rate = 3; /* auto */
1719 break;
1720 default:
1721 /* Choose a bit according to this table.
1722 *
1723 * bit | data rate
1724 * ----+-------------------
1725 * 0 | 1Mbps
1726 * 1 | 2Mbps
1727 * 2 | 5.5Mbps
1728 * 3 | 11Mbps
1729 */
1730 for (i = 8; i > 0; i >>= 1) {
1731 if (rate >= i)
1732 break;
1733 }
1734 if (i == 0)
1735 rate = 0xf; /* auto */
1736 else
1737 rate = i;
1738 break;
1739 }
1740 return wi_write_val(sc, WI_RID_TX_RATE, rate);
1741 }
1742
1743 static int
1744 wi_write_wep(struct wi_softc *sc)
1745 {
1746 struct ieee80211com *ic = &sc->sc_ic;
1747 int error = 0;
1748 int i, keylen;
1749 u_int16_t val;
1750 struct wi_key wkey[IEEE80211_WEP_NKID];
1751
1752 switch (sc->sc_firmware_type) {
1753 case WI_LUCENT:
1754 val = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0;
1755 error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
1756 if (error)
1757 break;
1758 error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_wep_txkey);
1759 if (error)
1760 break;
1761 memset(wkey, 0, sizeof(wkey));
1762 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1763 keylen = ic->ic_nw_keys[i].wk_len;
1764 wkey[i].wi_keylen = htole16(keylen);
1765 memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
1766 keylen);
1767 }
1768 error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
1769 wkey, sizeof(wkey));
1770 break;
1771
1772 case WI_INTERSIL:
1773 case WI_SYMBOL:
1774 if (ic->ic_flags & IEEE80211_F_WEPON) {
1775 /*
1776 * ONLY HWB3163 EVAL-CARD Firmware version
1777 * less than 0.8 variant2
1778 *
1779 * If promiscuous mode disable, Prism2 chip
1780 * does not work with WEP .
1781 * It is under investigation for details.
1782 * (ichiro (at) netbsd.org)
1783 */
1784 if (sc->sc_firmware_type == WI_INTERSIL &&
1785 sc->sc_sta_firmware_ver < 802 ) {
1786 /* firm ver < 0.8 variant 2 */
1787 wi_write_val(sc, WI_RID_PROMISC, 1);
1788 }
1789 wi_write_val(sc, WI_RID_CNFAUTHMODE,
1790 sc->sc_cnfauthmode);
1791 val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
1792 /*
1793 * Encryption firmware has a bug for HostAP mode.
1794 */
1795 if (sc->sc_firmware_type == WI_INTERSIL &&
1796 ic->ic_opmode == IEEE80211_M_HOSTAP)
1797 val |= HOST_ENCRYPT;
1798 } else {
1799 wi_write_val(sc, WI_RID_CNFAUTHMODE,
1800 IEEE80211_AUTH_OPEN);
1801 val = HOST_ENCRYPT | HOST_DECRYPT;
1802 }
1803 error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
1804 if (error)
1805 break;
1806 error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
1807 ic->ic_wep_txkey);
1808 if (error)
1809 break;
1810 /*
1811 * It seems that the firmware accept 104bit key only if
1812 * all the keys have 104bit length. We get the length of
1813 * the transmit key and use it for all other keys.
1814 * Perhaps we should use software WEP for such situation.
1815 */
1816 keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len;
1817 if (keylen > IEEE80211_WEP_KEYLEN)
1818 keylen = 13; /* 104bit keys */
1819 else
1820 keylen = IEEE80211_WEP_KEYLEN;
1821 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1822 error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
1823 ic->ic_nw_keys[i].wk_key, keylen);
1824 if (error)
1825 break;
1826 }
1827 break;
1828 }
1829 return error;
1830 }
1831
1832 /* Must be called at proper protection level! */
1833 static int
1834 wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
1835 {
1836 int i, status;
1837
1838 /* wait for the busy bit to clear */
1839 for (i = 0; ; i++) {
1840 if ((CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY) == 0)
1841 break;
1842 if (i == WI_TIMEOUT) {
1843 printf("%s: wi_cmd: BUSY did not clear, "
1844 "cmd=0x%x, prev=0x%x\n", sc->sc_dev.dv_xname,
1845 cmd, CSR_READ_2(sc, WI_COMMAND));
1846 return EIO;
1847 }
1848 DELAY(1);
1849 }
1850
1851 CSR_WRITE_2(sc, WI_PARAM0, val0);
1852 CSR_WRITE_2(sc, WI_PARAM1, val1);
1853 CSR_WRITE_2(sc, WI_PARAM2, val2);
1854 CSR_WRITE_2(sc, WI_COMMAND, cmd);
1855
1856 if (cmd == WI_CMD_INI) {
1857 /* XXX: should sleep here. */
1858 DELAY(100*1000);
1859 }
1860 /* wait for the cmd completed bit */
1861 for (i = 0; i < WI_TIMEOUT; i++) {
1862 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
1863 break;
1864 DELAY(1);
1865 }
1866
1867 status = CSR_READ_2(sc, WI_STATUS);
1868
1869 /* Ack the command */
1870 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
1871
1872 if (i == WI_TIMEOUT) {
1873 printf("%s: command timed out, cmd=0x%x, arg=0x%x\n",
1874 sc->sc_dev.dv_xname, cmd, val0);
1875 return ETIMEDOUT;
1876 }
1877
1878 if (status & WI_STAT_CMD_RESULT) {
1879 printf("%s: command failed, cmd=0x%x, arg=0x%x\n",
1880 sc->sc_dev.dv_xname, cmd, val0);
1881 return EIO;
1882 }
1883 return 0;
1884 }
1885
1886 static int
1887 wi_seek_bap(struct wi_softc *sc, int id, int off)
1888 {
1889 int i, status;
1890
1891 CSR_WRITE_2(sc, WI_SEL0, id);
1892 CSR_WRITE_2(sc, WI_OFF0, off);
1893
1894 for (i = 0; ; i++) {
1895 status = CSR_READ_2(sc, WI_OFF0);
1896 if ((status & WI_OFF_BUSY) == 0)
1897 break;
1898 if (i == WI_TIMEOUT) {
1899 printf("%s: timeout in wi_seek to %x/%x\n",
1900 sc->sc_dev.dv_xname, id, off);
1901 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
1902 return ETIMEDOUT;
1903 }
1904 DELAY(1);
1905 }
1906 if (status & WI_OFF_ERR) {
1907 printf("%s: failed in wi_seek to %x/%x\n",
1908 sc->sc_dev.dv_xname, id, off);
1909 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
1910 return EIO;
1911 }
1912 sc->sc_bap_id = id;
1913 sc->sc_bap_off = off;
1914 return 0;
1915 }
1916
1917 static int
1918 wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
1919 {
1920 int error, cnt;
1921
1922 if (buflen == 0)
1923 return 0;
1924 if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
1925 if ((error = wi_seek_bap(sc, id, off)) != 0)
1926 return error;
1927 }
1928 cnt = (buflen + 1) / 2;
1929 CSR_READ_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
1930 sc->sc_bap_off += cnt * 2;
1931 return 0;
1932 }
1933
1934 static int
1935 wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
1936 {
1937 int error, cnt;
1938
1939 if (buflen == 0)
1940 return 0;
1941
1942 #ifdef WI_HERMES_AUTOINC_WAR
1943 again:
1944 #endif
1945 if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
1946 if ((error = wi_seek_bap(sc, id, off)) != 0)
1947 return error;
1948 }
1949 cnt = (buflen + 1) / 2;
1950 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
1951 sc->sc_bap_off += cnt * 2;
1952
1953 #ifdef WI_HERMES_AUTOINC_WAR
1954 /*
1955 * According to the comments in the HCF Light code, there is a bug
1956 * in the Hermes (or possibly in certain Hermes firmware revisions)
1957 * where the chip's internal autoincrement counter gets thrown off
1958 * during data writes: the autoincrement is missed, causing one
1959 * data word to be overwritten and subsequent words to be written to
1960 * the wrong memory locations. The end result is that we could end
1961 * up transmitting bogus frames without realizing it. The workaround
1962 * for this is to write a couple of extra guard words after the end
1963 * of the transfer, then attempt to read then back. If we fail to
1964 * locate the guard words where we expect them, we preform the
1965 * transfer over again.
1966 */
1967 if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
1968 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1969 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1970 wi_seek_bap(sc, id, sc->sc_bap_off);
1971 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
1972 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1973 CSR_READ_2(sc, WI_DATA0) != 0x5678) {
1974 printf("%s: detect auto increment bug, try again\n",
1975 sc->sc_dev.dv_xname);
1976 goto again;
1977 }
1978 }
1979 #endif
1980 return 0;
1981 }
1982
1983 static int
1984 wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
1985 {
1986 int i;
1987
1988 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
1989 printf("%s: failed to allocate %d bytes on NIC\n",
1990 sc->sc_dev.dv_xname, len);
1991 return ENOMEM;
1992 }
1993
1994 for (i = 0; i < WI_TIMEOUT; i++) {
1995 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1996 break;
1997 if (i == WI_TIMEOUT) {
1998 printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname);
1999 return ETIMEDOUT;
2000 }
2001 DELAY(1);
2002 }
2003 *idp = CSR_READ_2(sc, WI_ALLOC_FID);
2004 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
2005 return 0;
2006 }
2007
2008 static int
2009 wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
2010 {
2011 int error, len;
2012 u_int16_t ltbuf[2];
2013
2014 /* Tell the NIC to enter record read mode. */
2015 error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
2016 if (error)
2017 return error;
2018
2019 error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2020 if (error)
2021 return error;
2022
2023 if (le16toh(ltbuf[1]) != rid) {
2024 printf("%s: record read mismatch, rid=%x, got=%x\n",
2025 sc->sc_dev.dv_xname, rid, le16toh(ltbuf[1]));
2026 return EIO;
2027 }
2028 len = (le16toh(ltbuf[0]) - 1) * 2; /* already got rid */
2029 if (*buflenp < len) {
2030 printf("%s: record buffer is too small, "
2031 "rid=%x, size=%d, len=%d\n",
2032 sc->sc_dev.dv_xname, rid, *buflenp, len);
2033 return ENOSPC;
2034 }
2035 *buflenp = len;
2036 return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
2037 }
2038
2039 static int
2040 wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
2041 {
2042 int error;
2043 u_int16_t ltbuf[2];
2044
2045 ltbuf[0] = htole16((buflen + 1) / 2 + 1); /* includes rid */
2046 ltbuf[1] = htole16(rid);
2047
2048 error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2049 if (error)
2050 return error;
2051 error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
2052 if (error)
2053 return error;
2054
2055 return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
2056 }
2057
2058 static int
2059 wi_newstate(void *arg, enum ieee80211_state nstate)
2060 {
2061 struct wi_softc *sc = arg;
2062 struct ieee80211com *ic = &sc->sc_ic;
2063 struct ieee80211_node *ni = &ic->ic_bss;
2064 int i, buflen;
2065 u_int16_t val;
2066 struct wi_ssid ssid;
2067 enum ieee80211_state ostate;
2068 #ifdef WI_DEBUG
2069 static const char *stname[] =
2070 { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
2071 #endif /* WI_DEBUG */
2072
2073 ostate = ic->ic_state;
2074 DPRINTF(("wi_newstate: %s -> %s\n", stname[ostate], stname[nstate]));
2075
2076 ic->ic_state = nstate;
2077 switch (nstate) {
2078 case IEEE80211_S_INIT:
2079 ic->ic_flags &= ~IEEE80211_F_SIBSS;
2080 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2081 return 0;
2082
2083 case IEEE80211_S_RUN:
2084 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2085 buflen = IEEE80211_ADDR_LEN;
2086 wi_read_rid(sc, WI_RID_CURRENT_BSSID, ni->ni_bssid, &buflen);
2087 IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid);
2088 buflen = sizeof(val);
2089 wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
2090 ni->ni_chan = le16toh(val);
2091
2092 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
2093 ni->ni_esslen = ic->ic_des_esslen;
2094 memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
2095 ni->ni_nrate = 0;
2096 for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
2097 if (ic->ic_sup_rates[i])
2098 ni->ni_rates[ni->ni_nrate++] =
2099 ic->ic_sup_rates[i];
2100 }
2101 ni->ni_intval = ic->ic_lintval;
2102 ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
2103 if (ic->ic_flags & IEEE80211_F_WEPON)
2104 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
2105 } else {
2106 buflen = sizeof(ssid);
2107 wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen);
2108 ni->ni_esslen = le16toh(ssid.wi_len);
2109 if (ni->ni_esslen > IEEE80211_NWID_LEN)
2110 ni->ni_esslen = IEEE80211_NWID_LEN; /*XXX*/
2111 memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
2112 }
2113 break;
2114
2115 case IEEE80211_S_SCAN:
2116 case IEEE80211_S_AUTH:
2117 case IEEE80211_S_ASSOC:
2118 break;
2119 }
2120
2121 /* skip standard ieee80211 handling */
2122 return EINPROGRESS;
2123 }
2124
2125 static int
2126 wi_scan_ap(struct wi_softc *sc)
2127 {
2128 int error = 0;
2129 u_int16_t val[2];
2130
2131 if (!sc->sc_enabled)
2132 return ENXIO;
2133 switch (sc->sc_firmware_type) {
2134 case WI_LUCENT:
2135 (void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
2136 break;
2137 case WI_INTERSIL:
2138 val[0] = 0x3fff; /* channel */
2139 val[1] = 0x000f; /* tx rate */
2140 error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
2141 break;
2142 case WI_SYMBOL:
2143 /*
2144 * XXX only supported on 3.x ?
2145 */
2146 val[0] = BSCAN_BCAST | BSCAN_ONETIME;
2147 error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
2148 val, sizeof(val[0]));
2149 break;
2150 }
2151 if (error == 0) {
2152 sc->sc_scan_timer = WI_SCAN_WAIT;
2153 sc->sc_ic.ic_if.if_timer = 1;
2154 DPRINTF(("wi_scan_ap: start scanning\n"));
2155 }
2156 return error;
2157 }
2158
2159 static void
2160 wi_scan_result(struct wi_softc *sc, int fid, int cnt)
2161 {
2162 int i, naps, off, szbuf;
2163 struct wi_scan_header ws_hdr; /* Prism2 header */
2164 struct wi_scan_data_p2 ws_dat; /* Prism2 scantable*/
2165 struct wi_apinfo *ap;
2166
2167 off = sizeof(u_int16_t) * 2;
2168 memset(&ws_hdr, 0, sizeof(ws_hdr));
2169 switch (sc->sc_firmware_type) {
2170 case WI_INTERSIL:
2171 wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
2172 off += sizeof(ws_hdr);
2173 szbuf = sizeof(struct wi_scan_data_p2);
2174 break;
2175 case WI_SYMBOL:
2176 szbuf = sizeof(struct wi_scan_data_p2) + 6;
2177 break;
2178 case WI_LUCENT:
2179 szbuf = sizeof(struct wi_scan_data);
2180 break;
2181 }
2182 naps = (cnt * 2 + 2 - off) / szbuf;
2183 if (naps > MAXAPINFO)
2184 naps = MAXAPINFO;
2185 sc->sc_naps = naps;
2186 /* Read Data */
2187 ap = sc->sc_aps;
2188 memset(&ws_dat, 0, sizeof(ws_dat));
2189 for (i = 0; i < naps; i++, ap++) {
2190 wi_read_bap(sc, fid, off, &ws_dat,
2191 (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
2192 DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
2193 ether_sprintf(ws_dat.wi_bssid)));
2194 off += szbuf;
2195 ap->scanreason = le16toh(ws_hdr.wi_reason);
2196 memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
2197 ap->channel = le16toh(ws_dat.wi_chid);
2198 ap->signal = le16toh(ws_dat.wi_signal);
2199 ap->noise = le16toh(ws_dat.wi_noise);
2200 ap->quality = ap->signal - ap->noise;
2201 ap->capinfo = le16toh(ws_dat.wi_capinfo);
2202 ap->interval = le16toh(ws_dat.wi_interval);
2203 ap->rate = le16toh(ws_dat.wi_rate);
2204 ap->namelen = le16toh(ws_dat.wi_namelen);
2205 if (ap->namelen > sizeof(ap->name))
2206 ap->namelen = sizeof(ap->name);
2207 memcpy(ap->name, ws_dat.wi_name, ap->namelen);
2208 }
2209 /* Done scanning */
2210 sc->sc_scan_timer = 0;
2211 DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps));
2212 }
2213