1 /* $OpenBSD: if_wi.c,v 1.108 2004/03/18 16:16:10 millert Exp $ */
2
3 /*
4 * Copyright (c) 1997, 1998, 1999
5 * Bill Paul <wpaul@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 * From: if_wi.c,v 1.7 1999/07/04 14:40:22 wpaul Exp $
35 */
36
37 /*
38 * Lucent WaveLAN/IEEE 802.11 driver for OpenBSD.
39 *
40 * Originally written by Bill Paul <wpaul@ctr.columbia.edu>
41 * Electrical Engineering Department
42 * Columbia University, New York City
43 */
44
45 /*
46 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
47 * from Lucent. Unlike the older cards, the new ones are programmed
48 * entirely via a firmware-driven controller called the Hermes.
49 * Unfortunately, Lucent will not release the Hermes programming manual
50 * without an NDA (if at all). What they do release is an API library
51 * called the HCF (Hardware Control Functions) which is supposed to
52 * do the device-specific operations of a device driver for you. The
53 * publicly available version of the HCF library (the 'HCF Light') is
54 * a) extremely gross, b) lacks certain features, particularly support
55 * for 802.11 frames, and c) is contaminated by the GNU Public License.
56 *
57 * This driver does not use the HCF or HCF Light at all. Instead, it
58 * programs the Hermes controller directly, using information gleaned
59 * from the HCF Light code and corresponding documentation.
60 */
61
62 #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
63 #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
64
65 #include "bpfilter.h"
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/sockio.h>
70 #include <sys/mbuf.h>
71 #include <sys/malloc.h>
72 #include <sys/kernel.h>
73 #include <sys/proc.h>
74 #include <sys/socket.h>
75 #include <sys/device.h>
76
77 #include <net/if.h>
78 #include <net/if_dl.h>
79 #include <net/if_media.h>
80 #include <net/if_types.h>
81
82 #ifdef INET
83 #include <netinet/in.h>
84 #include <netinet/in_systm.h>
85 #include <netinet/in_var.h>
86 #include <netinet/ip.h>
87 #include <netinet/if_ether.h>
88 #endif
89
90 #include <net/if_ieee80211.h>
91
92 #if NBPFILTER > 0
93 #include <net/bpf.h>
94 #endif
95
96 #include <machine/bus.h>
97
98 #include <dev/rndvar.h>
99
100 #include <dev/ic/if_wireg.h>
101 #include <dev/ic/if_wi_ieee.h>
102 #include <dev/ic/if_wivar.h>
103
104 #include <crypto/arc4.h>
105
106 #define BPF_MTAP(if,mbuf) bpf_mtap((if)->if_bpf, (mbuf))
107 #define BPFATTACH(if_bpf,if,dlt,sz)
108 #define STATIC
109
110 #ifdef WIDEBUG
111
112 u_int32_t widebug = WIDEBUG;
113
114 #define WID_INTR 0x01
115 #define WID_START 0x02
116 #define WID_IOCTL 0x04
117 #define WID_INIT 0x08
118 #define WID_STOP 0x10
119 #define WID_RESET 0x20
120
121 #define DPRINTF(mask,args) if (widebug & (mask)) printf args;
122
123 #else /* !WIDEBUG */
124 #define DPRINTF(mask,args)
125 #endif /* WIDEBUG */
126
127 #if !defined(lint) && !defined(__OpenBSD__)
128 static const char rcsid[] =
129 "$OpenBSD: if_wi.c,v 1.108 2004/03/18 16:16:10 millert Exp $";
130 #endif /* lint */
131
132 #ifdef foo
133 static u_int8_t wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
134 #endif
135
136 STATIC void wi_reset(struct wi_softc *);
137 STATIC int wi_ioctl(struct ifnet *, u_long, caddr_t);
138 STATIC void wi_init_io(struct wi_softc *);
139 STATIC void wi_start(struct ifnet *);
140 STATIC void wi_watchdog(struct ifnet *);
141 STATIC void wi_shutdown(void *);
142 STATIC void wi_rxeof(struct wi_softc *);
143 STATIC void wi_txeof(struct wi_softc *, int);
144 STATIC void wi_update_stats(struct wi_softc *);
145 STATIC void wi_setmulti(struct wi_softc *);
146
147 STATIC int wi_cmd_io(struct wi_softc *, int, int, int, int);
148 STATIC int wi_read_record_io(struct wi_softc *, struct wi_ltv_gen *);
149 STATIC int wi_write_record_io(struct wi_softc *, struct wi_ltv_gen *);
150 STATIC int wi_read_data_io(struct wi_softc *, int,
151 int, caddr_t, int);
152 STATIC int wi_write_data_io(struct wi_softc *, int,
153 int, caddr_t, int);
154 STATIC int wi_seek(struct wi_softc *, int, int, int);
155
156 STATIC void wi_inquire(void *);
157 STATIC int wi_setdef(struct wi_softc *, struct wi_req *);
158 STATIC void wi_get_id(struct wi_softc *);
159
160 STATIC int wi_media_change(struct ifnet *);
161 STATIC void wi_media_status(struct ifnet *, struct ifmediareq *);
162
163 STATIC int wi_set_ssid(struct ieee80211_nwid *, u_int8_t *, int);
164 STATIC int wi_set_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
165 STATIC int wi_get_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
166 STATIC int wi_sync_media(struct wi_softc *, int, int);
167 STATIC int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
168 STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
169
170 STATIC int wi_get_debug(struct wi_softc *, struct wi_req *);
171 STATIC int wi_set_debug(struct wi_softc *, struct wi_req *);
172
173 STATIC void wi_do_hostencrypt(struct wi_softc *, caddr_t, int);
174 STATIC int wi_do_hostdecrypt(struct wi_softc *, caddr_t, int);
175
176 STATIC int wi_alloc_nicmem_io(struct wi_softc *, int, int *);
177 STATIC int wi_get_fid_io(struct wi_softc *sc, int fid);
178 STATIC void wi_intr_enable(struct wi_softc *sc, int mode);
179 STATIC void wi_intr_ack(struct wi_softc *sc, int mode);
180
181 /* Autoconfig definition of driver back-end */
182 struct cfdriver wi_cd = {
183 NULL, "wi", DV_IFNET
184 };
185
186 const struct wi_card_ident wi_card_ident[] = {
187 WI_CARD_IDS
188 };
189
190 struct wi_funcs wi_func_io = {
191 wi_cmd_io,
192 wi_read_record_io,
193 wi_write_record_io,
194 wi_alloc_nicmem_io,
195 wi_read_data_io,
196 wi_write_data_io,
197 wi_get_fid_io,
198 wi_init_io,
199
200 wi_start,
201 wi_ioctl,
202 wi_watchdog,
203 wi_inquire,
204 };
205
206 int
wi_attach(struct wi_softc * sc,struct wi_funcs * funcs)207 wi_attach(struct wi_softc *sc, struct wi_funcs *funcs)
208 {
209 struct wi_ltv_macaddr mac;
210 struct wi_ltv_gen gen;
211 struct ifnet *ifp;
212 int error;
213
214 sc->sc_funcs = funcs;
215 sc->wi_cmd_count = 500;
216
217 wi_reset(sc);
218
219 /* Read the station address. */
220 mac.wi_type = WI_RID_MAC_NODE;
221 mac.wi_len = 4;
222 error = wi_read_record(sc, (struct wi_ltv_gen *)&mac);
223 if (error) {
224 printf(": unable to read station address\n");
225 return (error);
226 }
227 bcopy((char *)&mac.wi_mac_addr, (char *)&sc->sc_arpcom.ac_enaddr,
228 ETHER_ADDR_LEN);
229
230 wi_get_id(sc);
231 printf("address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
232
233 ifp = &sc->sc_arpcom.ac_if;
234 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
235 ifp->if_softc = sc;
236 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
237 ifp->if_ioctl = funcs->f_ioctl;
238 ifp->if_start = funcs->f_start;
239 ifp->if_watchdog = funcs->f_watchdog;
240 ifp->if_baudrate = 10000000;
241 IFQ_SET_READY(&ifp->if_snd);
242
243 (void)wi_set_ssid(&sc->wi_node_name, WI_DEFAULT_NODENAME,
244 sizeof(WI_DEFAULT_NODENAME) - 1);
245 (void)wi_set_ssid(&sc->wi_net_name, WI_DEFAULT_NETNAME,
246 sizeof(WI_DEFAULT_NETNAME) - 1);
247 (void)wi_set_ssid(&sc->wi_ibss_name, WI_DEFAULT_IBSS,
248 sizeof(WI_DEFAULT_IBSS) - 1);
249
250 sc->wi_portnum = WI_DEFAULT_PORT;
251 sc->wi_ptype = WI_PORTTYPE_BSS;
252 sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
253 sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
254 sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
255 sc->wi_max_data_len = WI_DEFAULT_DATALEN;
256 sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
257 sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
258 sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
259 sc->wi_roaming = WI_DEFAULT_ROAMING;
260 sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
261 sc->wi_diversity = WI_DEFAULT_DIVERSITY;
262 sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
263
264 /*
265 * Read the default channel from the NIC. This may vary
266 * depending on the country where the NIC was purchased, so
267 * we can't hard-code a default and expect it to work for
268 * everyone.
269 */
270 gen.wi_type = WI_RID_OWN_CHNL;
271 gen.wi_len = 2;
272 if (wi_read_record(sc, &gen) == 0)
273 sc->wi_channel = letoh16(gen.wi_val);
274 else
275 sc->wi_channel = 3;
276
277 /*
278 * Set flags based on firmware version.
279 */
280 switch (sc->sc_firmware_type) {
281 case WI_LUCENT:
282 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
283 if (sc->sc_sta_firmware_ver >= 60000)
284 sc->wi_flags |= WI_FLAGS_HAS_MOR;
285 if (sc->sc_sta_firmware_ver >= 60006) {
286 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
287 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
288 }
289 sc->wi_ibss_port = htole16(1);
290 break;
291 case WI_INTERSIL:
292 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
293 /* older prism firmware is slow so crank the count */
294 if (sc->sc_sta_firmware_ver < 10000)
295 sc->wi_cmd_count = 5000;
296 else
297 sc->wi_cmd_count = 2000;
298 if (sc->sc_sta_firmware_ver >= 800) {
299 #ifndef SMALL_KERNEL
300 if (sc->sc_sta_firmware_ver != 10402)
301 sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
302 #endif
303 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
304 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
305 }
306 if (sc->sc_sta_firmware_ver >= 10603)
307 sc->wi_flags |= WI_FLAGS_HAS_ENH_SECURITY;
308 sc->wi_ibss_port = htole16(0);
309 break;
310 case WI_SYMBOL:
311 sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
312 if (sc->sc_sta_firmware_ver >= 20000)
313 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
314 if (sc->sc_sta_firmware_ver >= 25000)
315 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
316 sc->wi_ibss_port = htole16(4);
317 break;
318 }
319
320 /*
321 * Find out if we support WEP on this card.
322 */
323 gen.wi_type = WI_RID_WEP_AVAIL;
324 gen.wi_len = 2;
325 if (wi_read_record(sc, &gen) == 0 && gen.wi_val != htole16(0))
326 sc->wi_flags |= WI_FLAGS_HAS_WEP;
327 timeout_set(&sc->sc_timo, funcs->f_inquire, sc);
328
329 bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
330
331 /* Find supported rates. */
332 gen.wi_type = WI_RID_DATA_RATES;
333 gen.wi_len = 2;
334 if (wi_read_record(sc, &gen))
335 sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
336 WI_SUPPRATES_5M | WI_SUPPRATES_11M;
337 else
338 sc->wi_supprates = gen.wi_val;
339
340 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
341 #define ADD(m, c) ifmedia_add(&sc->sc_media, (m), (c), NULL)
342 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
343 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
344 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
345 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
346 0), 0);
347 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
348 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
349 IFM_IEEE80211_IBSSMASTER, 0), 0);
350 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
351 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
352 IFM_IEEE80211_HOSTAP, 0), 0);
353 if (sc->wi_supprates & WI_SUPPRATES_1M) {
354 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
355 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
356 IFM_IEEE80211_ADHOC, 0), 0);
357 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
358 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
359 IFM_IEEE80211_IBSS, 0), 0);
360 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
361 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
362 IFM_IEEE80211_IBSSMASTER, 0), 0);
363 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
364 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
365 IFM_IEEE80211_HOSTAP, 0), 0);
366 }
367 if (sc->wi_supprates & WI_SUPPRATES_2M) {
368 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
369 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
370 IFM_IEEE80211_ADHOC, 0), 0);
371 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
372 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
373 IFM_IEEE80211_IBSS, 0), 0);
374 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
375 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
376 IFM_IEEE80211_IBSSMASTER, 0), 0);
377 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
378 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
379 IFM_IEEE80211_HOSTAP, 0), 0);
380 }
381 if (sc->wi_supprates & WI_SUPPRATES_5M) {
382 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
383 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
384 IFM_IEEE80211_ADHOC, 0), 0);
385 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
386 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
387 IFM_IEEE80211_IBSS, 0), 0);
388 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
389 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
390 IFM_IEEE80211_IBSSMASTER, 0), 0);
391 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
392 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
393 IFM_IEEE80211_HOSTAP, 0), 0);
394 }
395 if (sc->wi_supprates & WI_SUPPRATES_11M) {
396 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
397 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
398 IFM_IEEE80211_ADHOC, 0), 0);
399 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
400 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
401 IFM_IEEE80211_IBSS, 0), 0);
402 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
403 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
404 IFM_IEEE80211_IBSSMASTER, 0), 0);
405 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
406 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
407 IFM_IEEE80211_HOSTAP, 0), 0);
408 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
409 }
410 #undef ADD
411 ifmedia_set(&sc->sc_media,
412 IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
413
414 /*
415 * Call MI attach routines.
416 */
417 if_attach(ifp);
418 ether_ifattach(ifp);
419 printf("\n");
420
421 sc->wi_flags |= WI_FLAGS_ATTACHED;
422
423 #if NBPFILTER > 0
424 BPFATTACH(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
425 sizeof(struct ether_header));
426 #endif
427
428 sc->sc_sdhook = shutdownhook_establish(wi_shutdown, sc);
429
430 wi_init(sc);
431 wi_stop(sc);
432
433 return (0);
434 }
435
436 STATIC void
wi_intr_enable(struct wi_softc * sc,int mode)437 wi_intr_enable(struct wi_softc *sc, int mode)
438 {
439 if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
440 CSR_WRITE_2(sc, WI_INT_EN, mode);
441 }
442
443 STATIC void
wi_intr_ack(struct wi_softc * sc,int mode)444 wi_intr_ack(struct wi_softc *sc, int mode)
445 {
446 if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
447 CSR_WRITE_2(sc, WI_EVENT_ACK, mode);
448 }
449
450 int
wi_intr(vsc)451 wi_intr(vsc)
452 void *vsc;
453 {
454 struct wi_softc *sc = vsc;
455 struct ifnet *ifp;
456 u_int16_t status;
457
458 DPRINTF(WID_INTR, ("wi_intr: sc %p\n", sc));
459
460 ifp = &sc->sc_arpcom.ac_if;
461
462 if (!(sc->wi_flags & WI_FLAGS_ATTACHED) || !(ifp->if_flags & IFF_UP)) {
463 CSR_WRITE_2(sc, WI_INT_EN, 0);
464 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xffff);
465 return (0);
466 }
467
468 /* Disable interrupts. */
469 CSR_WRITE_2(sc, WI_INT_EN, 0);
470
471 status = CSR_READ_2(sc, WI_EVENT_STAT);
472 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
473
474 if (status & WI_EV_RX) {
475 wi_rxeof(sc);
476 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
477 }
478
479 if (status & WI_EV_TX) {
480 wi_txeof(sc, status);
481 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
482 }
483
484 if (status & WI_EV_ALLOC) {
485 int id;
486 id = CSR_READ_2(sc, WI_ALLOC_FID);
487 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
488 if (id == sc->wi_tx_data_id)
489 wi_txeof(sc, status);
490 }
491
492 if (status & WI_EV_INFO) {
493 wi_update_stats(sc);
494 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
495 }
496
497 if (status & WI_EV_TX_EXC) {
498 wi_txeof(sc, status);
499 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
500 }
501
502 if (status & WI_EV_INFO_DROP) {
503 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
504 }
505
506 /* Re-enable interrupts. */
507 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
508
509 if (!IFQ_IS_EMPTY(&ifp->if_snd))
510 wi_start(ifp);
511
512 return (1);
513 }
514
515 STATIC int
wi_get_fid_io(struct wi_softc * sc,int fid)516 wi_get_fid_io(struct wi_softc *sc, int fid)
517 {
518 return CSR_READ_2(sc, fid);
519 }
520
521
522 void
wi_rxeof(sc)523 wi_rxeof(sc)
524 struct wi_softc *sc;
525 {
526 struct ifnet *ifp;
527 struct ether_header *eh;
528 struct mbuf *m;
529 caddr_t olddata;
530 u_int16_t ftype;
531 int maxlen;
532 int id;
533
534 ifp = &sc->sc_arpcom.ac_if;
535
536 id = wi_get_fid(sc, WI_RX_FID);
537
538 if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
539 struct wi_frame *rx_frame;
540 int datlen, hdrlen;
541
542 MGETHDR(m, M_DONTWAIT, MT_DATA);
543 if (m == NULL) {
544 ifp->if_ierrors++;
545 return;
546 }
547 MCLGET(m, M_DONTWAIT);
548 if (!(m->m_flags & M_EXT)) {
549 m_freem(m);
550 ifp->if_ierrors++;
551 return;
552 }
553
554 m->m_pkthdr.rcvif = ifp;
555
556 if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
557 sizeof(struct wi_frame))) {
558 m_freem(m);
559 ifp->if_ierrors++;
560 return;
561 }
562
563 rx_frame = mtod(m, struct wi_frame *);
564
565 if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)) {
566 m_freem(m);
567 ifp->if_ierrors++;
568 return;
569 }
570
571 switch ((letoh16(rx_frame->wi_status) & WI_STAT_MAC_PORT)
572 >> 8) {
573 case 7:
574 switch (letoh16(rx_frame->wi_frame_ctl) &
575 WI_FCTL_FTYPE) {
576 case WI_FTYPE_DATA:
577 hdrlen = WI_DATA_HDRLEN;
578 datlen = letoh16(rx_frame->wi_dat_len);
579 break;
580 case WI_FTYPE_MGMT:
581 hdrlen = WI_MGMT_HDRLEN;
582 datlen = letoh16(rx_frame->wi_dat_len);
583 break;
584 case WI_FTYPE_CTL:
585 hdrlen = WI_CTL_HDRLEN;
586 datlen = 0;
587 break;
588 default:
589 printf(WI_PRT_FMT ": received packet of "
590 "unknown type on port 7\n", WI_PRT_ARG(sc));
591 m_freem(m);
592 ifp->if_ierrors++;
593 return;
594 }
595 break;
596 case 0:
597 hdrlen = WI_DATA_HDRLEN;
598 datlen = letoh16(rx_frame->wi_dat_len);
599 break;
600 default:
601 printf(WI_PRT_FMT ": received packet on invalid port "
602 "(wi_status=0x%x)\n", WI_PRT_ARG(sc),
603 letoh16(rx_frame->wi_status));
604 m_freem(m);
605 ifp->if_ierrors++;
606 return;
607 }
608
609 if ((hdrlen + datlen + 2) > MCLBYTES) {
610 m_freem(m);
611 ifp->if_ierrors++;
612 return;
613 }
614
615 if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
616 datlen + 2)) {
617 m_freem(m);
618 ifp->if_ierrors++;
619 return;
620 }
621
622 m->m_pkthdr.len = m->m_len = hdrlen + datlen;
623 } else {
624 struct wi_frame rx_frame;
625
626 /* First read in the frame header */
627 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
628 sizeof(rx_frame))) {
629 ifp->if_ierrors++;
630 return;
631 }
632
633 /* Drop undecryptable or packets with receive errors here */
634 if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) {
635 ifp->if_ierrors++;
636 return;
637 }
638
639 /* Stash frame type in host byte order for later use */
640 ftype = letoh16(rx_frame.wi_frame_ctl) & WI_FCTL_FTYPE;
641
642 MGETHDR(m, M_DONTWAIT, MT_DATA);
643 if (m == NULL) {
644 ifp->if_ierrors++;
645 return;
646 }
647 MCLGET(m, M_DONTWAIT);
648 if (!(m->m_flags & M_EXT)) {
649 m_freem(m);
650 ifp->if_ierrors++;
651 return;
652 }
653
654 olddata = m->m_data;
655 /* Align the data after the ethernet header */
656 m->m_data = (caddr_t)ALIGN(m->m_data +
657 sizeof(struct ether_header)) - sizeof(struct ether_header);
658
659 eh = mtod(m, struct ether_header *);
660 maxlen = MCLBYTES - (m->m_data - olddata);
661 m->m_pkthdr.rcvif = ifp;
662
663 if (ftype == WI_FTYPE_MGMT &&
664 sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
665
666 u_int16_t rxlen = letoh16(rx_frame.wi_dat_len);
667
668 if ((WI_802_11_OFFSET_RAW + rxlen + 2) > maxlen) {
669 printf("%s: oversized mgmt packet received in "
670 "hostap mode (wi_dat_len=%d, "
671 "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
672 rxlen, letoh16(rx_frame.wi_status));
673 m_freem(m);
674 ifp->if_ierrors++;
675 return;
676 }
677
678 /* Put the whole header in there. */
679 bcopy(&rx_frame, mtod(m, void *),
680 sizeof(struct wi_frame));
681 if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
682 mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
683 rxlen + 2)) {
684 m_freem(m);
685 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
686 printf("wihap: failed to copy header\n");
687 ifp->if_ierrors++;
688 return;
689 }
690
691 m->m_pkthdr.len = m->m_len =
692 WI_802_11_OFFSET_RAW + rxlen;
693
694 /* XXX: consider giving packet to bhp? */
695
696 wihap_mgmt_input(sc, &rx_frame, m);
697
698 return;
699 }
700
701 switch (letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) {
702 case WI_STAT_1042:
703 case WI_STAT_TUNNEL:
704 case WI_STAT_WMP_MSG:
705 if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) >
706 maxlen) {
707 printf(WI_PRT_FMT ": oversized packet received "
708 "(wi_dat_len=%d, wi_status=0x%x)\n",
709 WI_PRT_ARG(sc),
710 letoh16(rx_frame.wi_dat_len),
711 letoh16(rx_frame.wi_status));
712 m_freem(m);
713 ifp->if_ierrors++;
714 return;
715 }
716 m->m_pkthdr.len = m->m_len =
717 letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
718
719 bcopy((char *)&rx_frame.wi_dst_addr,
720 (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
721 bcopy((char *)&rx_frame.wi_src_addr,
722 (char *)&eh->ether_shost, ETHER_ADDR_LEN);
723 bcopy((char *)&rx_frame.wi_type,
724 (char *)&eh->ether_type, ETHER_TYPE_LEN);
725
726 if (wi_read_data(sc, id, WI_802_11_OFFSET,
727 mtod(m, caddr_t) + sizeof(struct ether_header),
728 m->m_len + 2)) {
729 ifp->if_ierrors++;
730 m_freem(m);
731 return;
732 }
733 break;
734 default:
735 if ((letoh16(rx_frame.wi_dat_len) +
736 sizeof(struct ether_header)) > maxlen) {
737 printf(WI_PRT_FMT ": oversized packet received "
738 "(wi_dat_len=%d, wi_status=0x%x)\n",
739 WI_PRT_ARG(sc),
740 letoh16(rx_frame.wi_dat_len),
741 letoh16(rx_frame.wi_status));
742 m_freem(m);
743 ifp->if_ierrors++;
744 return;
745 }
746 m->m_pkthdr.len = m->m_len =
747 letoh16(rx_frame.wi_dat_len) +
748 sizeof(struct ether_header);
749
750 if (wi_read_data(sc, id, WI_802_3_OFFSET,
751 mtod(m, caddr_t), m->m_len + 2)) {
752 m_freem(m);
753 ifp->if_ierrors++;
754 return;
755 }
756 break;
757 }
758
759 ifp->if_ipackets++;
760
761 if (sc->wi_use_wep &&
762 rx_frame.wi_frame_ctl & htole16(WI_FCTL_WEP)) {
763 int len;
764 u_int8_t rx_buf[1596];
765
766 switch (sc->wi_crypto_algorithm) {
767 case WI_CRYPTO_FIRMWARE_WEP:
768 break;
769 case WI_CRYPTO_SOFTWARE_WEP:
770 m_copydata(m, 0, m->m_pkthdr.len,
771 (caddr_t)rx_buf);
772 len = m->m_pkthdr.len -
773 sizeof(struct ether_header);
774 if (wi_do_hostdecrypt(sc, rx_buf +
775 sizeof(struct ether_header), len)) {
776 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
777 printf(WI_PRT_FMT ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc));
778 m_freem(m);
779 ifp->if_ierrors++;
780 return;
781 }
782 len -= IEEE80211_WEP_IVLEN +
783 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
784 /*
785 * copy data back to mbufs:
786 * we need to ditch the IV & most LLC/SNAP stuff
787 * (except SNAP type, we're going use that to
788 * overwrite the ethertype in the ether_header)
789 */
790 m_copyback(m, sizeof(struct ether_header) -
791 WI_ETHERTYPE_LEN, WI_ETHERTYPE_LEN +
792 (len - WI_SNAPHDR_LEN),
793 rx_buf + sizeof(struct ether_header) +
794 IEEE80211_WEP_IVLEN +
795 IEEE80211_WEP_KIDLEN + WI_SNAPHDR_LEN);
796 m_adj(m, -(WI_ETHERTYPE_LEN +
797 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
798 WI_SNAPHDR_LEN));
799 break;
800 }
801 }
802
803 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
804 /*
805 * Give host AP code first crack at data packets.
806 * If it decides to handle it (or drop it), it will
807 * return a non-zero. Otherwise, it is destined for
808 * this host.
809 */
810 if (wihap_data_input(sc, &rx_frame, m))
811 return;
812 }
813 }
814
815 #if NBPFILTER > 0
816 /* Handle BPF listeners. */
817 if (ifp->if_bpf)
818 BPF_MTAP(ifp, m);
819 #endif
820
821 /* Receive packet unless in procframe or monitor mode. */
822 if (sc->wi_procframe || sc->wi_debug.wi_monitor)
823 m_freem(m);
824 else
825 ether_input_mbuf(ifp, m);
826
827 return;
828 }
829
830 void
wi_txeof(sc,status)831 wi_txeof(sc, status)
832 struct wi_softc *sc;
833 int status;
834 {
835 struct ifnet *ifp;
836
837 ifp = &sc->sc_arpcom.ac_if;
838
839 ifp->if_timer = 0;
840 ifp->if_flags &= ~IFF_OACTIVE;
841
842 if (status & WI_EV_TX_EXC)
843 ifp->if_oerrors++;
844 else
845 ifp->if_opackets++;
846
847 return;
848 }
849
850 void
wi_inquire(xsc)851 wi_inquire(xsc)
852 void *xsc;
853 {
854 struct wi_softc *sc;
855 struct ifnet *ifp;
856 int s, rv;
857
858 sc = xsc;
859 ifp = &sc->sc_arpcom.ac_if;
860
861 timeout_add(&sc->sc_timo, hz * 60);
862
863 /* Don't do this while we're transmitting */
864 if (ifp->if_flags & IFF_OACTIVE)
865 return;
866
867 s = splimp();
868 rv = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
869 splx(s);
870 if (rv)
871 printf(WI_PRT_FMT ": wi_cmd failed with %d\n", WI_PRT_ARG(sc),
872 rv);
873
874 return;
875 }
876
877 void
wi_update_stats(sc)878 wi_update_stats(sc)
879 struct wi_softc *sc;
880 {
881 struct wi_ltv_gen gen;
882 u_int16_t id;
883 struct ifnet *ifp;
884 u_int32_t *ptr;
885 int len, i;
886 u_int16_t t;
887
888 ifp = &sc->sc_arpcom.ac_if;
889
890 id = wi_get_fid(sc, WI_INFO_FID);
891
892 wi_read_data(sc, id, 0, (char *)&gen, 4);
893
894 if (gen.wi_type == htole16(WI_INFO_SCAN_RESULTS)) {
895 sc->wi_scanbuf_len = letoh16(gen.wi_len);
896 wi_read_data(sc, id, 4, (caddr_t)sc->wi_scanbuf,
897 sc->wi_scanbuf_len * 2);
898 return;
899 } else if (gen.wi_type != htole16(WI_INFO_COUNTERS))
900 return;
901
902 /* Some card versions have a larger stats structure */
903 len = (letoh16(gen.wi_len) - 1 < sizeof(sc->wi_stats) / 4) ?
904 letoh16(gen.wi_len) - 1 : sizeof(sc->wi_stats) / 4;
905
906 ptr = (u_int32_t *)&sc->wi_stats;
907
908 for (i = 0; i < len; i++) {
909 if (sc->wi_flags & WI_FLAGS_BUS_USB) {
910 wi_read_data(sc, id, 4 + i*2, (char *)&t, 2);
911 t = letoh16(t);
912 } else
913 t = CSR_READ_2(sc, WI_DATA1);
914 #ifdef WI_HERMES_STATS_WAR
915 if (t > 0xF000)
916 t = ~t & 0xFFFF;
917 #endif
918 ptr[i] += t;
919 }
920
921 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
922 sc->wi_stats.wi_tx_multi_retries +
923 sc->wi_stats.wi_tx_retry_limit;
924
925 return;
926 }
927
928 STATIC int
wi_cmd_io(sc,cmd,val0,val1,val2)929 wi_cmd_io(sc, cmd, val0, val1, val2)
930 struct wi_softc *sc;
931 int cmd;
932 int val0;
933 int val1;
934 int val2;
935 {
936 int i, s = 0;
937
938 /* Wait for the busy bit to clear. */
939 for (i = sc->wi_cmd_count; i--; DELAY(1000)) {
940 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
941 break;
942 }
943 if (i < 0) {
944 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
945 printf(WI_PRT_FMT ": wi_cmd_io: busy bit won't clear\n",
946 WI_PRT_ARG(sc));
947 return(ETIMEDOUT);
948 }
949
950 CSR_WRITE_2(sc, WI_PARAM0, val0);
951 CSR_WRITE_2(sc, WI_PARAM1, val1);
952 CSR_WRITE_2(sc, WI_PARAM2, val2);
953 CSR_WRITE_2(sc, WI_COMMAND, cmd);
954
955 for (i = WI_TIMEOUT; i--; DELAY(WI_DELAY)) {
956 /*
957 * Wait for 'command complete' bit to be
958 * set in the event status register.
959 */
960 s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
961 if (s) {
962 /* Ack the event and read result code. */
963 s = CSR_READ_2(sc, WI_STATUS);
964 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
965 if (s & WI_STAT_CMD_RESULT)
966 return(EIO);
967 break;
968 }
969 }
970
971 if (i < 0) {
972 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
973 printf(WI_PRT_FMT
974 ": timeout in wi_cmd 0x%04x; event status 0x%04x\n",
975 WI_PRT_ARG(sc), cmd, s);
976 return(ETIMEDOUT);
977 }
978
979 return(0);
980 }
981
982 STATIC void
wi_reset(sc)983 wi_reset(sc)
984 struct wi_softc *sc;
985 {
986 int error, tries = 3;
987
988 DPRINTF(WID_RESET, ("wi_reset: sc %p\n", sc));
989
990 /* Symbol firmware cannot be initialized more than once. */
991 if (sc->sc_firmware_type == WI_SYMBOL) {
992 if (sc->wi_flags & WI_FLAGS_INITIALIZED)
993 return;
994 tries = 1;
995 }
996
997 for (; tries--; DELAY(WI_DELAY * 1000)) {
998 if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
999 break;
1000 }
1001 if (tries < 0) {
1002 printf(WI_PRT_FMT ": init failed\n", WI_PRT_ARG(sc));
1003 return;
1004 }
1005 sc->wi_flags |= WI_FLAGS_INITIALIZED;
1006
1007 wi_intr_enable(sc, 0);
1008 wi_intr_ack(sc, 0xffff);
1009
1010 /* Calibrate timer. */
1011 WI_SETVAL(WI_RID_TICK_TIME, 8);
1012
1013 return;
1014 }
1015
1016 STATIC void
wi_cor_reset(sc)1017 wi_cor_reset(sc)
1018 struct wi_softc *sc;
1019 {
1020 u_int8_t cor_value;
1021
1022 DPRINTF(WID_RESET, ("wi_cor_reset: sc %p\n", sc));
1023
1024 /*
1025 * Do a soft reset of the card; this is required for Symbol cards.
1026 * This shouldn't hurt other cards but there have been reports
1027 * of the COR reset messing up old Lucent firmware revisions so
1028 * we avoid soft reset Lucent cards for now.
1029 */
1030 if (sc->sc_firmware_type != WI_LUCENT) {
1031 cor_value = bus_space_read_1(sc->wi_ltag, sc->wi_lhandle,
1032 sc->wi_cor_offset);
1033 bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
1034 sc->wi_cor_offset, (cor_value | WI_COR_SOFT_RESET));
1035 DELAY(1000);
1036 bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
1037 sc->wi_cor_offset, (cor_value & ~WI_COR_SOFT_RESET));
1038 DELAY(1000);
1039 }
1040
1041 return;
1042 }
1043
1044 /*
1045 * Read an LTV record from the NIC.
1046 */
1047 STATIC int
wi_read_record_io(sc,ltv)1048 wi_read_record_io(sc, ltv)
1049 struct wi_softc *sc;
1050 struct wi_ltv_gen *ltv;
1051 {
1052 u_int8_t *ptr;
1053 int len, code;
1054 struct wi_ltv_gen *oltv = NULL, p2ltv;
1055
1056 if (sc->sc_firmware_type != WI_LUCENT) {
1057 oltv = ltv;
1058 switch (ltv->wi_type) {
1059 case WI_RID_ENCRYPTION:
1060 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1061 p2ltv.wi_len = 2;
1062 ltv = &p2ltv;
1063 break;
1064 case WI_RID_TX_CRYPT_KEY:
1065 if (ltv->wi_val > WI_NLTV_KEYS)
1066 return (EINVAL);
1067 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1068 p2ltv.wi_len = 2;
1069 ltv = &p2ltv;
1070 break;
1071 }
1072 }
1073
1074 /* Tell the NIC to enter record read mode. */
1075 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
1076 return(EIO);
1077
1078 /* Seek to the record. */
1079 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1080 return(EIO);
1081
1082 /*
1083 * Read the length and record type and make sure they
1084 * match what we expect (this verifies that we have enough
1085 * room to hold all of the returned data).
1086 */
1087 len = CSR_READ_2(sc, WI_DATA1);
1088 if (len > ltv->wi_len)
1089 return(ENOSPC);
1090 code = CSR_READ_2(sc, WI_DATA1);
1091 if (code != ltv->wi_type)
1092 return(EIO);
1093
1094 ltv->wi_len = len;
1095 ltv->wi_type = code;
1096
1097 /* Now read the data. */
1098 ptr = (u_int8_t *)<v->wi_val;
1099 if (ltv->wi_len > 1)
1100 CSR_READ_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1)*2);
1101
1102 if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS
1103 && ltv->wi_val == sc->wi_ibss_port) {
1104 /*
1105 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
1106 * Since Lucent uses port type 1 for BSS *and* IBSS we
1107 * have to rely on wi_ptype to distinguish this for us.
1108 */
1109 ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
1110 } else if (sc->sc_firmware_type != WI_LUCENT) {
1111 int v;
1112
1113 switch (oltv->wi_type) {
1114 case WI_RID_TX_RATE:
1115 case WI_RID_CUR_TX_RATE:
1116 switch (letoh16(ltv->wi_val)) {
1117 case 1: v = 1; break;
1118 case 2: v = 2; break;
1119 case 3: v = 6; break;
1120 case 4: v = 5; break;
1121 case 7: v = 7; break;
1122 case 8: v = 11; break;
1123 case 15: v = 3; break;
1124 default: v = 0x100 + letoh16(ltv->wi_val); break;
1125 }
1126 oltv->wi_val = htole16(v);
1127 break;
1128 case WI_RID_ENCRYPTION:
1129 oltv->wi_len = 2;
1130 if (ltv->wi_val & htole16(0x01))
1131 oltv->wi_val = htole16(1);
1132 else
1133 oltv->wi_val = htole16(0);
1134 break;
1135 case WI_RID_TX_CRYPT_KEY:
1136 case WI_RID_CNFAUTHMODE:
1137 oltv->wi_len = 2;
1138 oltv->wi_val = ltv->wi_val;
1139 break;
1140 }
1141 }
1142
1143 return(0);
1144 }
1145
1146 /*
1147 * Same as read, except we inject data instead of reading it.
1148 */
1149 STATIC int
wi_write_record_io(sc,ltv)1150 wi_write_record_io(sc, ltv)
1151 struct wi_softc *sc;
1152 struct wi_ltv_gen *ltv;
1153 {
1154 u_int8_t *ptr;
1155 u_int16_t val = 0;
1156 int i;
1157 struct wi_ltv_gen p2ltv;
1158
1159 if (ltv->wi_type == WI_RID_PORTTYPE &&
1160 letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) {
1161 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
1162 p2ltv.wi_type = WI_RID_PORTTYPE;
1163 p2ltv.wi_len = 2;
1164 p2ltv.wi_val = sc->wi_ibss_port;
1165 ltv = &p2ltv;
1166 } else if (sc->sc_firmware_type != WI_LUCENT) {
1167 int v;
1168
1169 switch (ltv->wi_type) {
1170 case WI_RID_TX_RATE:
1171 p2ltv.wi_type = WI_RID_TX_RATE;
1172 p2ltv.wi_len = 2;
1173 switch (letoh16(ltv->wi_val)) {
1174 case 1: v = 1; break;
1175 case 2: v = 2; break;
1176 case 3: v = 15; break;
1177 case 5: v = 4; break;
1178 case 6: v = 3; break;
1179 case 7: v = 7; break;
1180 case 11: v = 8; break;
1181 default: return EINVAL;
1182 }
1183 p2ltv.wi_val = htole16(v);
1184 ltv = &p2ltv;
1185 break;
1186 case WI_RID_ENCRYPTION:
1187 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1188 p2ltv.wi_len = 2;
1189 if (ltv->wi_val & htole16(0x01)) {
1190 val = PRIVACY_INVOKED;
1191 /*
1192 * If using shared key WEP we must set the
1193 * EXCLUDE_UNENCRYPTED bit. Symbol cards
1194 * need this bit set even when not using
1195 * shared key. We can't just test for
1196 * IEEE80211_AUTH_SHARED since Symbol cards
1197 * have 2 shared key modes.
1198 */
1199 if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
1200 sc->sc_firmware_type == WI_SYMBOL)
1201 val |= EXCLUDE_UNENCRYPTED;
1202
1203 switch (sc->wi_crypto_algorithm) {
1204 case WI_CRYPTO_FIRMWARE_WEP:
1205 /*
1206 * TX encryption is broken in
1207 * Host AP mode.
1208 */
1209 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
1210 val |= HOST_ENCRYPT;
1211 break;
1212 case WI_CRYPTO_SOFTWARE_WEP:
1213 val |= HOST_ENCRYPT|HOST_DECRYPT;
1214 break;
1215 }
1216 p2ltv.wi_val = htole16(val);
1217 } else
1218 p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT);
1219 ltv = &p2ltv;
1220 break;
1221 case WI_RID_TX_CRYPT_KEY:
1222 if (ltv->wi_val > WI_NLTV_KEYS)
1223 return (EINVAL);
1224 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1225 p2ltv.wi_len = 2;
1226 p2ltv.wi_val = ltv->wi_val;
1227 ltv = &p2ltv;
1228 break;
1229 case WI_RID_DEFLT_CRYPT_KEYS: {
1230 int error;
1231 int keylen;
1232 struct wi_ltv_str ws;
1233 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
1234 keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1235 keylen = letoh16(keylen);
1236
1237 for (i = 0; i < 4; i++) {
1238 bzero(&ws, sizeof(ws));
1239 ws.wi_len = (keylen > 5) ? 8 : 4;
1240 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1241 bcopy(&wk->wi_keys[i].wi_keydat,
1242 ws.wi_str, keylen);
1243 error = wi_write_record(sc,
1244 (struct wi_ltv_gen *)&ws);
1245 if (error)
1246 return (error);
1247 }
1248 }
1249 return (0);
1250 }
1251 }
1252
1253 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1254 return(EIO);
1255
1256 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1257 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1258
1259 ptr = (u_int8_t *)<v->wi_val;
1260 if (ltv->wi_len > 1)
1261 CSR_WRITE_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1) *2);
1262
1263 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
1264 return(EIO);
1265
1266 return(0);
1267 }
1268
1269 STATIC int
wi_seek(sc,id,off,chan)1270 wi_seek(sc, id, off, chan)
1271 struct wi_softc *sc;
1272 int id, off, chan;
1273 {
1274 int i;
1275 int selreg, offreg;
1276
1277 switch (chan) {
1278 case WI_BAP0:
1279 selreg = WI_SEL0;
1280 offreg = WI_OFF0;
1281 break;
1282 case WI_BAP1:
1283 selreg = WI_SEL1;
1284 offreg = WI_OFF1;
1285 break;
1286 default:
1287 printf(WI_PRT_FMT ": invalid data path: %x\n", WI_PRT_ARG(sc),
1288 chan);
1289 return(EIO);
1290 }
1291
1292 CSR_WRITE_2(sc, selreg, id);
1293 CSR_WRITE_2(sc, offreg, off);
1294
1295 for (i = WI_TIMEOUT; i--; DELAY(1))
1296 if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
1297 break;
1298
1299 if (i < 0)
1300 return(ETIMEDOUT);
1301
1302 return(0);
1303 }
1304
1305 STATIC int
wi_read_data_io(sc,id,off,buf,len)1306 wi_read_data_io(sc, id, off, buf, len)
1307 struct wi_softc *sc;
1308 int id, off;
1309 caddr_t buf;
1310 int len;
1311 {
1312 u_int8_t *ptr;
1313
1314 if (wi_seek(sc, id, off, WI_BAP1))
1315 return(EIO);
1316
1317 ptr = (u_int8_t *)buf;
1318 CSR_READ_RAW_2(sc, WI_DATA1, ptr, len);
1319
1320 return(0);
1321 }
1322
1323 /*
1324 * According to the comments in the HCF Light code, there is a bug in
1325 * the Hermes (or possibly in certain Hermes firmware revisions) where
1326 * the chip's internal autoincrement counter gets thrown off during
1327 * data writes: the autoincrement is missed, causing one data word to
1328 * be overwritten and subsequent words to be written to the wrong memory
1329 * locations. The end result is that we could end up transmitting bogus
1330 * frames without realizing it. The workaround for this is to write a
1331 * couple of extra guard words after the end of the transfer, then
1332 * attempt to read then back. If we fail to locate the guard words where
1333 * we expect them, we preform the transfer over again.
1334 */
1335 STATIC int
wi_write_data_io(sc,id,off,buf,len)1336 wi_write_data_io(sc, id, off, buf, len)
1337 struct wi_softc *sc;
1338 int id, off;
1339 caddr_t buf;
1340 int len;
1341 {
1342 u_int8_t *ptr;
1343
1344 #ifdef WI_HERMES_AUTOINC_WAR
1345 again:
1346 #endif
1347
1348 if (wi_seek(sc, id, off, WI_BAP0))
1349 return(EIO);
1350
1351 ptr = (u_int8_t *)buf;
1352 CSR_WRITE_RAW_2(sc, WI_DATA0, ptr, len);
1353
1354 #ifdef WI_HERMES_AUTOINC_WAR
1355 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1356 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1357
1358 if (wi_seek(sc, id, off + len, WI_BAP0))
1359 return(EIO);
1360
1361 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1362 CSR_READ_2(sc, WI_DATA0) != 0x5678)
1363 goto again;
1364 #endif
1365
1366 return(0);
1367 }
1368
1369 /*
1370 * Allocate a region of memory inside the NIC and zero
1371 * it out.
1372 */
1373 STATIC int
wi_alloc_nicmem_io(sc,len,id)1374 wi_alloc_nicmem_io(sc, len, id)
1375 struct wi_softc *sc;
1376 int len;
1377 int *id;
1378 {
1379 int i;
1380
1381 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
1382 printf(WI_PRT_FMT ": failed to allocate %d bytes on NIC\n",
1383 WI_PRT_ARG(sc), len);
1384 return(ENOMEM);
1385 }
1386
1387 for (i = WI_TIMEOUT; i--; DELAY(1)) {
1388 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1389 break;
1390 }
1391
1392 if (i < 0)
1393 return(ETIMEDOUT);
1394
1395 *id = CSR_READ_2(sc, WI_ALLOC_FID);
1396 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1397
1398 if (wi_seek(sc, *id, 0, WI_BAP0))
1399 return(EIO);
1400
1401 for (i = 0; i < len / 2; i++)
1402 CSR_WRITE_2(sc, WI_DATA0, 0);
1403
1404 return(0);
1405 }
1406
1407 STATIC void
wi_setmulti(sc)1408 wi_setmulti(sc)
1409 struct wi_softc *sc;
1410 {
1411 struct ifnet *ifp;
1412 int i = 0;
1413 struct wi_ltv_mcast mcast;
1414 struct ether_multistep step;
1415 struct ether_multi *enm;
1416
1417 ifp = &sc->sc_arpcom.ac_if;
1418
1419 bzero((char *)&mcast, sizeof(mcast));
1420
1421 mcast.wi_type = WI_RID_MCAST_LIST;
1422 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
1423
1424 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1425 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1426 return;
1427 }
1428
1429 ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
1430 while (enm != NULL) {
1431 if (i >= 16) {
1432 bzero((char *)&mcast, sizeof(mcast));
1433 break;
1434 }
1435
1436 /* Punt on ranges. */
1437 if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
1438 sizeof(enm->enm_addrlo)) != 0)
1439 break;
1440 bcopy(enm->enm_addrlo, (char *)&mcast.wi_mcast[i],
1441 ETHER_ADDR_LEN);
1442 i++;
1443 ETHER_NEXT_MULTI(step, enm);
1444 }
1445
1446 mcast.wi_len = (i * 3) + 1;
1447 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1448
1449 return;
1450 }
1451
1452 STATIC int
wi_setdef(sc,wreq)1453 wi_setdef(sc, wreq)
1454 struct wi_softc *sc;
1455 struct wi_req *wreq;
1456 {
1457 struct ifnet *ifp;
1458 int error = 0;
1459
1460 ifp = &sc->sc_arpcom.ac_if;
1461
1462 switch(wreq->wi_type) {
1463 case WI_RID_MAC_NODE:
1464 bcopy((char *)&wreq->wi_val, LLADDR(ifp->if_sadl),
1465 ETHER_ADDR_LEN);
1466 bcopy((char *)&wreq->wi_val, (char *)&sc->sc_arpcom.ac_enaddr,
1467 ETHER_ADDR_LEN);
1468 break;
1469 case WI_RID_PORTTYPE:
1470 error = wi_sync_media(sc, letoh16(wreq->wi_val[0]),
1471 sc->wi_tx_rate);
1472 break;
1473 case WI_RID_TX_RATE:
1474 error = wi_sync_media(sc, sc->wi_ptype,
1475 letoh16(wreq->wi_val[0]));
1476 break;
1477 case WI_RID_MAX_DATALEN:
1478 sc->wi_max_data_len = letoh16(wreq->wi_val[0]);
1479 break;
1480 case WI_RID_RTS_THRESH:
1481 sc->wi_rts_thresh = letoh16(wreq->wi_val[0]);
1482 break;
1483 case WI_RID_SYSTEM_SCALE:
1484 sc->wi_ap_density = letoh16(wreq->wi_val[0]);
1485 break;
1486 case WI_RID_CREATE_IBSS:
1487 sc->wi_create_ibss = letoh16(wreq->wi_val[0]);
1488 error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
1489 break;
1490 case WI_RID_OWN_CHNL:
1491 sc->wi_channel = letoh16(wreq->wi_val[0]);
1492 break;
1493 case WI_RID_NODENAME:
1494 error = wi_set_ssid(&sc->wi_node_name,
1495 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1496 break;
1497 case WI_RID_DESIRED_SSID:
1498 error = wi_set_ssid(&sc->wi_net_name,
1499 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1500 break;
1501 case WI_RID_OWN_SSID:
1502 error = wi_set_ssid(&sc->wi_ibss_name,
1503 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1504 break;
1505 case WI_RID_PM_ENABLED:
1506 sc->wi_pm_enabled = letoh16(wreq->wi_val[0]);
1507 break;
1508 case WI_RID_MICROWAVE_OVEN:
1509 sc->wi_mor_enabled = letoh16(wreq->wi_val[0]);
1510 break;
1511 case WI_RID_MAX_SLEEP:
1512 sc->wi_max_sleep = letoh16(wreq->wi_val[0]);
1513 break;
1514 case WI_RID_CNFAUTHMODE:
1515 sc->wi_authtype = letoh16(wreq->wi_val[0]);
1516 break;
1517 case WI_RID_ROAMING_MODE:
1518 sc->wi_roaming = letoh16(wreq->wi_val[0]);
1519 break;
1520 case WI_RID_SYMBOL_DIVERSITY:
1521 sc->wi_diversity = letoh16(wreq->wi_val[0]);
1522 break;
1523 case WI_RID_CNF_ENH_SECURITY:
1524 sc->wi_enh_security = letoh16(wreq->wi_val[0]);
1525 break;
1526 case WI_RID_ENCRYPTION:
1527 sc->wi_use_wep = letoh16(wreq->wi_val[0]);
1528 break;
1529 case WI_RID_TX_CRYPT_KEY:
1530 sc->wi_tx_key = letoh16(wreq->wi_val[0]);
1531 break;
1532 case WI_RID_DEFLT_CRYPT_KEYS:
1533 bcopy((char *)wreq, (char *)&sc->wi_keys,
1534 sizeof(struct wi_ltv_keys));
1535 break;
1536 case WI_FRID_CRYPTO_ALG:
1537 switch (letoh16(wreq->wi_val[0])) {
1538 case WI_CRYPTO_FIRMWARE_WEP:
1539 sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
1540 break;
1541 case WI_CRYPTO_SOFTWARE_WEP:
1542 sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP;
1543 break;
1544 default:
1545 printf(WI_PRT_FMT ": unsupported crypto algorithm %d\n",
1546 WI_PRT_ARG(sc), letoh16(wreq->wi_val[0]));
1547 error = EINVAL;
1548 }
1549 break;
1550 default:
1551 error = EINVAL;
1552 break;
1553 }
1554
1555 return (error);
1556 }
1557
1558 STATIC int
wi_ioctl(ifp,command,data)1559 wi_ioctl(ifp, command, data)
1560 struct ifnet *ifp;
1561 u_long command;
1562 caddr_t data;
1563 {
1564 int s, error = 0;
1565 struct wi_softc *sc;
1566 struct wi_req wreq;
1567 struct ifreq *ifr;
1568 struct proc *p = curproc;
1569 struct ifaddr *ifa = (struct ifaddr *)data;
1570 struct ieee80211_nwid nwid;
1571
1572 s = splimp();
1573
1574 sc = ifp->if_softc;
1575 ifr = (struct ifreq *)data;
1576
1577 if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) {
1578 splx(s);
1579 return(ENODEV);
1580 }
1581
1582 DPRINTF (WID_IOCTL, ("wi_ioctl: command %lu data %p\n",
1583 command, data));
1584
1585 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
1586 splx(s);
1587 return error;
1588 }
1589
1590 switch(command) {
1591 case SIOCSWAVELAN:
1592 case SIOCSPRISM2DEBUG:
1593 case SIOCS80211NWID:
1594 case SIOCS80211NWKEY:
1595 case SIOCS80211POWER:
1596 error = suser(p, 0);
1597 if (error) {
1598 splx(s);
1599 return (error);
1600 }
1601 default:
1602 break;
1603 }
1604
1605 switch(command) {
1606 case SIOCSIFADDR:
1607 ifp->if_flags |= IFF_UP;
1608 switch (ifa->ifa_addr->sa_family) {
1609 #ifdef INET
1610 case AF_INET:
1611 wi_init(sc);
1612 arp_ifinit(&sc->sc_arpcom, ifa);
1613 break;
1614 #endif /* INET */
1615 default:
1616 wi_init(sc);
1617 break;
1618 }
1619 break;
1620
1621 case SIOCSIFMTU:
1622 if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
1623 error = EINVAL;
1624 } else if (ifp->if_mtu != ifr->ifr_mtu) {
1625 ifp->if_mtu = ifr->ifr_mtu;
1626 }
1627 break;
1628
1629 case SIOCSIFFLAGS:
1630 if (ifp->if_flags & IFF_UP) {
1631 if (ifp->if_flags & IFF_RUNNING &&
1632 ifp->if_flags & IFF_PROMISC &&
1633 !(sc->wi_if_flags & IFF_PROMISC)) {
1634 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1635 WI_SETVAL(WI_RID_PROMISC, 1);
1636 } else if (ifp->if_flags & IFF_RUNNING &&
1637 !(ifp->if_flags & IFF_PROMISC) &&
1638 sc->wi_if_flags & IFF_PROMISC) {
1639 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1640 WI_SETVAL(WI_RID_PROMISC, 0);
1641 } else
1642 wi_init(sc);
1643 } else if (ifp->if_flags & IFF_RUNNING)
1644 wi_stop(sc);
1645 sc->wi_if_flags = ifp->if_flags;
1646 error = 0;
1647 break;
1648 case SIOCADDMULTI:
1649 case SIOCDELMULTI:
1650 /* Update our multicast list. */
1651 error = (command == SIOCADDMULTI) ?
1652 ether_addmulti(ifr, &sc->sc_arpcom) :
1653 ether_delmulti(ifr, &sc->sc_arpcom);
1654 if (error == ENETRESET) {
1655 /*
1656 * Multicast list has changed; set the hardware filter
1657 * accordingly.
1658 */
1659 wi_setmulti(sc);
1660 error = 0;
1661 }
1662 break;
1663 case SIOCSIFMEDIA:
1664 case SIOCGIFMEDIA:
1665 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1666 break;
1667 case SIOCGWAVELAN:
1668 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1669 if (error)
1670 break;
1671 if (wreq.wi_len > WI_MAX_DATALEN) {
1672 error = EINVAL;
1673 break;
1674 }
1675 switch (wreq.wi_type) {
1676 case WI_RID_IFACE_STATS:
1677 /* XXX native byte order */
1678 bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1679 sizeof(sc->wi_stats));
1680 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1681 break;
1682 case WI_RID_DEFLT_CRYPT_KEYS:
1683 /* For non-root user, return all-zeroes keys */
1684 if (suser(p, 0))
1685 bzero((char *)&wreq,
1686 sizeof(struct wi_ltv_keys));
1687 else
1688 bcopy((char *)&sc->wi_keys, (char *)&wreq,
1689 sizeof(struct wi_ltv_keys));
1690 break;
1691 case WI_RID_PROCFRAME:
1692 wreq.wi_len = 2;
1693 wreq.wi_val[0] = htole16(sc->wi_procframe);
1694 break;
1695 case WI_RID_PRISM2:
1696 wreq.wi_len = 2;
1697 wreq.wi_val[0] = htole16(sc->sc_firmware_type ==
1698 WI_LUCENT ? 0 : 1);
1699 break;
1700 case WI_FRID_CRYPTO_ALG:
1701 wreq.wi_val[0] =
1702 htole16((u_int16_t)sc->wi_crypto_algorithm);
1703 wreq.wi_len = 1;
1704 break;
1705 case WI_RID_SCAN_RES:
1706 if (sc->sc_firmware_type == WI_LUCENT) {
1707 memcpy((char *)wreq.wi_val,
1708 (char *)sc->wi_scanbuf,
1709 sc->wi_scanbuf_len * 2);
1710 wreq.wi_len = sc->wi_scanbuf_len;
1711 break;
1712 }
1713 /* FALLTHROUGH */
1714 default:
1715 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1716 error = EINVAL;
1717 }
1718 break;
1719 }
1720 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1721 break;
1722 case SIOCSWAVELAN:
1723 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1724 if (error)
1725 break;
1726 error = EINVAL;
1727 if (wreq.wi_len > WI_MAX_DATALEN)
1728 break;
1729 switch (wreq.wi_type) {
1730 case WI_RID_IFACE_STATS:
1731 break;
1732 case WI_RID_MGMT_XMIT:
1733 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1734 wreq.wi_len);
1735 break;
1736 case WI_RID_PROCFRAME:
1737 sc->wi_procframe = letoh16(wreq.wi_val[0]);
1738 error = 0;
1739 break;
1740 case WI_RID_SCAN_REQ:
1741 error = 0;
1742 if (sc->sc_firmware_type == WI_LUCENT)
1743 wi_cmd(sc, WI_CMD_INQUIRE,
1744 WI_INFO_SCAN_RESULTS, 0, 0);
1745 else
1746 error = wi_write_record(sc,
1747 (struct wi_ltv_gen *)&wreq);
1748 break;
1749 case WI_FRID_CRYPTO_ALG:
1750 if (sc->sc_firmware_type != WI_LUCENT) {
1751 error = wi_setdef(sc, &wreq);
1752 if (!error && (ifp->if_flags & IFF_UP))
1753 wi_init(sc);
1754 }
1755 break;
1756 case WI_RID_SYMBOL_DIVERSITY:
1757 case WI_RID_ROAMING_MODE:
1758 case WI_RID_CREATE_IBSS:
1759 case WI_RID_MICROWAVE_OVEN:
1760 case WI_RID_OWN_SSID:
1761 case WI_RID_CNF_ENH_SECURITY:
1762 /*
1763 * Check for features that may not be supported
1764 * (must be just before default case).
1765 */
1766 if ((wreq.wi_type == WI_RID_SYMBOL_DIVERSITY &&
1767 !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)) ||
1768 (wreq.wi_type == WI_RID_ROAMING_MODE &&
1769 !(sc->wi_flags & WI_FLAGS_HAS_ROAMING)) ||
1770 (wreq.wi_type == WI_RID_CREATE_IBSS &&
1771 !(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) ||
1772 (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
1773 !(sc->wi_flags & WI_FLAGS_HAS_MOR)) ||
1774 (wreq.wi_type == WI_RID_CNF_ENH_SECURITY &&
1775 !(sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)) ||
1776 (wreq.wi_type == WI_RID_OWN_SSID &&
1777 wreq.wi_len != 0))
1778 break;
1779 /* FALLTHROUGH */
1780 default:
1781 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1782 if (!error)
1783 error = wi_setdef(sc, &wreq);
1784 if (!error && (ifp->if_flags & IFF_UP))
1785 wi_init(sc);
1786 }
1787 break;
1788 case SIOCGPRISM2DEBUG:
1789 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1790 if (error)
1791 break;
1792 if (!(ifp->if_flags & IFF_RUNNING) ||
1793 sc->sc_firmware_type == WI_LUCENT) {
1794 error = EIO;
1795 break;
1796 }
1797 error = wi_get_debug(sc, &wreq);
1798 if (error == 0)
1799 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1800 break;
1801 case SIOCSPRISM2DEBUG:
1802 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1803 if (error)
1804 break;
1805 error = wi_set_debug(sc, &wreq);
1806 break;
1807 case SIOCG80211NWID:
1808 if ((ifp->if_flags & IFF_UP) && sc->wi_net_name.i_len > 0) {
1809 /* Return the desired ID */
1810 error = copyout(&sc->wi_net_name, ifr->ifr_data,
1811 sizeof(sc->wi_net_name));
1812 } else {
1813 wreq.wi_type = WI_RID_CURRENT_SSID;
1814 wreq.wi_len = WI_MAX_DATALEN;
1815 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
1816 letoh16(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
1817 error = EINVAL;
1818 else {
1819 wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
1820 letoh16(wreq.wi_val[0]));
1821 error = copyout(&nwid, ifr->ifr_data,
1822 sizeof(nwid));
1823 }
1824 }
1825 break;
1826 case SIOCS80211NWID:
1827 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
1828 if (error)
1829 break;
1830 if (nwid.i_len > IEEE80211_NWID_LEN) {
1831 error = EINVAL;
1832 break;
1833 }
1834 if (sc->wi_net_name.i_len == nwid.i_len &&
1835 memcmp(sc->wi_net_name.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
1836 break;
1837 wi_set_ssid(&sc->wi_net_name, nwid.i_nwid, nwid.i_len);
1838 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1839 if (ifp->if_flags & IFF_UP)
1840 /* Reinitialize WaveLAN. */
1841 wi_init(sc);
1842 break;
1843 case SIOCS80211NWKEY:
1844 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1845 break;
1846 case SIOCG80211NWKEY:
1847 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1848 break;
1849 case SIOCS80211POWER:
1850 error = wi_set_pm(sc, (struct ieee80211_power *)data);
1851 break;
1852 case SIOCG80211POWER:
1853 error = wi_get_pm(sc, (struct ieee80211_power *)data);
1854 break;
1855 case SIOCHOSTAP_ADD:
1856 case SIOCHOSTAP_DEL:
1857 case SIOCHOSTAP_GET:
1858 case SIOCHOSTAP_GETALL:
1859 case SIOCHOSTAP_GFLAGS:
1860 case SIOCHOSTAP_SFLAGS:
1861 /* Send all Host AP specific ioctl's to Host AP code. */
1862 error = wihap_ioctl(sc, command, data);
1863 break;
1864 default:
1865 error = EINVAL;
1866 break;
1867 }
1868
1869 splx(s);
1870 return(error);
1871 }
1872
1873 STATIC void
wi_init_io(sc)1874 wi_init_io(sc)
1875 struct wi_softc *sc;
1876 {
1877 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1878 int s;
1879 struct wi_ltv_macaddr mac;
1880 int id = 0;
1881
1882 if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
1883 return;
1884
1885 DPRINTF(WID_INIT, ("wi_init: sc %p\n", sc));
1886
1887 s = splimp();
1888
1889 if (ifp->if_flags & IFF_RUNNING)
1890 wi_stop(sc);
1891
1892 wi_reset(sc);
1893
1894 /* Program max data length. */
1895 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1896
1897 /* Set the port type. */
1898 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1899
1900 /* Enable/disable IBSS creation. */
1901 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1902
1903 /* Program the RTS/CTS threshold. */
1904 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1905
1906 /* Program the TX rate */
1907 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1908
1909 /* Access point density */
1910 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1911
1912 /* Power Management Enabled */
1913 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1914
1915 /* Power Management Max Sleep */
1916 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1917
1918 /* Set Enhanced Security if supported. */
1919 if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)
1920 WI_SETVAL(WI_RID_CNF_ENH_SECURITY, sc->wi_enh_security);
1921
1922 /* Set Roaming Mode unless this is a Symbol card. */
1923 if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
1924 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
1925
1926 /* Set Antenna Diversity if this is a Symbol card. */
1927 if (sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)
1928 WI_SETVAL(WI_RID_SYMBOL_DIVERSITY, sc->wi_diversity);
1929
1930 /* Specify the network name */
1931 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1932
1933 /* Specify the IBSS name */
1934 if (sc->wi_net_name.i_len != 0 && (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
1935 (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
1936 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_net_name);
1937 else
1938 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
1939
1940 /* Specify the frequency to use */
1941 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1942
1943 /* Program the nodename. */
1944 WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
1945
1946 /* Set our MAC address. */
1947 mac.wi_len = 4;
1948 mac.wi_type = WI_RID_MAC_NODE;
1949 bcopy((char *)&sc->sc_arpcom.ac_enaddr,
1950 (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
1951 wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1952
1953 /*
1954 * Initialize promisc mode.
1955 * Being in the Host-AP mode causes
1956 * great deal of pain if promisc mode is set.
1957 * Therefore we avoid confusing the firmware
1958 * and always reset promisc mode in Host-AP regime,
1959 * it shows us all the packets anyway.
1960 */
1961 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP && ifp->if_flags & IFF_PROMISC)
1962 WI_SETVAL(WI_RID_PROMISC, 1);
1963 else
1964 WI_SETVAL(WI_RID_PROMISC, 0);
1965
1966 /* Configure WEP. */
1967 if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
1968 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1969 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1970 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1971 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1972 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1973 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
1974 /*
1975 * HWB3163 EVAL-CARD Firmware version less than 0.8.2.
1976 *
1977 * If promiscuous mode is disabled, the Prism2 chip
1978 * does not work with WEP .
1979 * I'm currently investigating the details of this.
1980 * (ichiro@netbsd.org)
1981 */
1982 if (sc->sc_firmware_type == WI_INTERSIL &&
1983 sc->sc_sta_firmware_ver < 802 ) {
1984 /* firm ver < 0.8.2 */
1985 WI_SETVAL(WI_RID_PROMISC, 1);
1986 }
1987 WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
1988 }
1989 }
1990
1991 /* Set multicast filter. */
1992 wi_setmulti(sc);
1993
1994 /* Enable desired port */
1995 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
1996
1997 if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
1998 printf(WI_PRT_FMT ": tx buffer allocation failed\n",
1999 WI_PRT_ARG(sc));
2000 sc->wi_tx_data_id = id;
2001
2002 if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2003 printf(WI_PRT_FMT ": mgmt. buffer allocation failed\n",
2004 WI_PRT_ARG(sc));
2005 sc->wi_tx_mgmt_id = id;
2006
2007 /* enable interrupts */
2008 wi_intr_enable(sc, WI_INTRS);
2009
2010 wihap_init(sc);
2011
2012 splx(s);
2013
2014 ifp->if_flags |= IFF_RUNNING;
2015 ifp->if_flags &= ~IFF_OACTIVE;
2016
2017 timeout_add(&sc->sc_timo, hz * 60);
2018
2019 return;
2020 }
2021
2022 static const u_int32_t crc32tab[] = {
2023 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
2024 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
2025 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
2026 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
2027 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2028 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
2029 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
2030 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
2031 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
2032 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2033 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
2034 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
2035 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
2036 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
2037 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2038 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
2039 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
2040 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
2041 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
2042 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2043 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
2044 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
2045 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
2046 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
2047 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2048 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
2049 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
2050 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
2051 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
2052 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2053 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
2054 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
2055 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
2056 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
2057 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2058 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
2059 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
2060 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
2061 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
2062 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2063 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
2064 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
2065 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
2066 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
2067 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2068 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
2069 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
2070 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
2071 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
2072 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2073 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
2074 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
2075 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
2076 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
2077 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2078 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
2079 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
2080 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
2081 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
2082 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2083 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
2084 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
2085 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
2086 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
2087 };
2088
2089 STATIC void
wi_do_hostencrypt(struct wi_softc * sc,caddr_t buf,int len)2090 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2091 {
2092 u_int32_t i, crc, klen;
2093 u_int8_t key[RC4KEYLEN];
2094 u_int8_t *dat;
2095 struct rc4_ctx ctx;
2096
2097 if (!sc->wi_icv_flag) {
2098 sc->wi_icv = arc4random();
2099 sc->wi_icv_flag++;
2100 } else
2101 sc->wi_icv++;
2102 /*
2103 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2104 * (B, 255, N) with 3 <= B < 8
2105 */
2106 if (sc->wi_icv >= 0x03ff00 &&
2107 (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2108 sc->wi_icv += 0x000100;
2109
2110 /* prepend 24bit IV to tx key, byte order does not matter */
2111 bzero(key, sizeof(key));
2112 key[0] = sc->wi_icv >> 16;
2113 key[1] = sc->wi_icv >> 8;
2114 key[2] = sc->wi_icv;
2115
2116 klen = letoh16(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen);
2117 bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2118 (char *)key + IEEE80211_WEP_IVLEN, klen);
2119 klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2120
2121 /* rc4 keysetup */
2122 rc4_keysetup(&ctx, key, klen);
2123
2124 /* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
2125 dat = buf;
2126 dat[0] = key[0];
2127 dat[1] = key[1];
2128 dat[2] = key[2];
2129 dat[3] = sc->wi_tx_key << 6; /* pad and keyid */
2130 dat += 4;
2131
2132 /* compute crc32 over data and encrypt */
2133 crc = ~0;
2134 for (i = 0; i < len; i++)
2135 crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2136 crc = ~crc;
2137 rc4_crypt(&ctx, dat, dat, len);
2138 dat += len;
2139
2140 /* append little-endian crc32 and encrypt */
2141 dat[0] = crc;
2142 dat[1] = crc >> 8;
2143 dat[2] = crc >> 16;
2144 dat[3] = crc >> 24;
2145 rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2146 }
2147
2148 STATIC int
wi_do_hostdecrypt(struct wi_softc * sc,caddr_t buf,int len)2149 wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len)
2150 {
2151 u_int32_t i, crc, klen, kid;
2152 u_int8_t key[RC4KEYLEN];
2153 u_int8_t *dat;
2154 struct rc4_ctx ctx;
2155
2156 if (len < IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2157 IEEE80211_WEP_CRCLEN)
2158 return -1;
2159 len -= (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2160 IEEE80211_WEP_CRCLEN);
2161
2162 dat = buf;
2163
2164 bzero(key, sizeof(key));
2165 key[0] = dat[0];
2166 key[1] = dat[1];
2167 key[2] = dat[2];
2168 kid = (dat[3] >> 6) % 4;
2169 dat += 4;
2170
2171 klen = letoh16(sc->wi_keys.wi_keys[kid].wi_keylen);
2172 bcopy((char *)&sc->wi_keys.wi_keys[kid].wi_keydat,
2173 (char *)key + IEEE80211_WEP_IVLEN, klen);
2174 klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2175
2176 /* rc4 keysetup */
2177 rc4_keysetup(&ctx, key, klen);
2178
2179 /* decrypt and compute crc32 over data */
2180 rc4_crypt(&ctx, dat, dat, len);
2181 crc = ~0;
2182 for (i = 0; i < len; i++)
2183 crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2184 crc = ~crc;
2185 dat += len;
2186
2187 /* decrypt little-endian crc32 and verify */
2188 rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2189
2190 if ((dat[0] != crc) && (dat[1] != crc >> 8) &&
2191 (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) {
2192 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
2193 printf(WI_PRT_FMT ": wi_do_hostdecrypt: iv mismatch: "
2194 "0x%02x%02x%02x%02x vs. 0x%x\n", WI_PRT_ARG(sc),
2195 dat[3], dat[2], dat[1], dat[0], crc);
2196 return -1;
2197 }
2198
2199 return 0;
2200 }
2201
2202 void
wi_start(ifp)2203 wi_start(ifp)
2204 struct ifnet *ifp;
2205 {
2206 struct wi_softc *sc;
2207 struct mbuf *m0;
2208 struct wi_frame tx_frame;
2209 struct ether_header *eh;
2210 int id, hostencrypt = 0;
2211
2212 sc = ifp->if_softc;
2213
2214 DPRINTF(WID_START, ("wi_start: ifp %p sc %p\n", ifp, sc));
2215
2216 if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2217 return;
2218
2219 if (ifp->if_flags & IFF_OACTIVE)
2220 return;
2221
2222 nextpkt:
2223 IFQ_DEQUEUE(&ifp->if_snd, m0);
2224 if (m0 == NULL)
2225 return;
2226
2227 bzero((char *)&tx_frame, sizeof(tx_frame));
2228 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA | WI_STYPE_DATA);
2229 id = sc->wi_tx_data_id;
2230 eh = mtod(m0, struct ether_header *);
2231
2232 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2233 if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
2234 &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC)) {
2235 if (ifp->if_flags & IFF_DEBUG)
2236 printf(WI_PRT_FMT
2237 ": wi_start: dropping unassoc dst %s\n",
2238 WI_PRT_ARG(sc),
2239 ether_sprintf(eh->ether_dhost));
2240 m_freem(m0);
2241 goto nextpkt;
2242 }
2243 }
2244
2245 /*
2246 * Use RFC1042 encoding for IP and ARP datagrams,
2247 * 802.3 for anything else.
2248 */
2249 if (eh->ether_type == htons(ETHERTYPE_IP) ||
2250 eh->ether_type == htons(ETHERTYPE_ARP) ||
2251 eh->ether_type == htons(ETHERTYPE_REVARP) ||
2252 eh->ether_type == htons(ETHERTYPE_IPV6)) {
2253 bcopy((char *)&eh->ether_dhost,
2254 (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
2255 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2256 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
2257 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
2258 bcopy((char *)&sc->sc_arpcom.ac_enaddr,
2259 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2260 bcopy((char *)&eh->ether_shost,
2261 (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
2262 if (sc->wi_use_wep)
2263 hostencrypt = 1;
2264 } else if (sc->wi_ptype == WI_PORTTYPE_BSS && sc->wi_use_wep &&
2265 sc->wi_crypto_algorithm != WI_CRYPTO_FIRMWARE_WEP) {
2266 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
2267 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_TODS);
2268 bcopy((char *)&sc->sc_arpcom.ac_enaddr,
2269 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2270 bcopy((char *)&eh->ether_dhost,
2271 (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
2272 hostencrypt = 1;
2273 } else
2274 bcopy((char *)&eh->ether_shost,
2275 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2276 bcopy((char *)&eh->ether_dhost,
2277 (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
2278 bcopy((char *)&eh->ether_shost,
2279 (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
2280
2281 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
2282 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
2283 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
2284 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
2285 tx_frame.wi_type = eh->ether_type;
2286
2287 if (hostencrypt) {
2288
2289 /* Do host encryption. */
2290 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
2291 bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8);
2292
2293 m_copydata(m0, sizeof(struct ether_header),
2294 m0->m_pkthdr.len - sizeof(struct ether_header),
2295 (caddr_t)&sc->wi_txbuf[12]);
2296
2297 wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
2298 tx_frame.wi_dat_len);
2299
2300 tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
2301 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2302
2303 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2304 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2305 sizeof(struct wi_frame));
2306 wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
2307 (caddr_t)&sc->wi_txbuf,
2308 (m0->m_pkthdr.len -
2309 sizeof(struct ether_header)) + 18);
2310 } else {
2311 m_copydata(m0, sizeof(struct ether_header),
2312 m0->m_pkthdr.len - sizeof(struct ether_header),
2313 (caddr_t)&sc->wi_txbuf);
2314
2315 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2316 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2317 sizeof(struct wi_frame));
2318 wi_write_data(sc, id, WI_802_11_OFFSET,
2319 (caddr_t)&sc->wi_txbuf,
2320 (m0->m_pkthdr.len -
2321 sizeof(struct ether_header)) + 2);
2322 }
2323 } else {
2324 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
2325
2326 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
2327
2328 /* Do host encryption. (XXX - not implemented) */
2329 printf(WI_PRT_FMT
2330 ": host encrypt not implemented for 802.3\n",
2331 WI_PRT_ARG(sc));
2332 } else {
2333 m_copydata(m0, 0, m0->m_pkthdr.len,
2334 (caddr_t)&sc->wi_txbuf);
2335
2336 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2337 sizeof(struct wi_frame));
2338 wi_write_data(sc, id, WI_802_3_OFFSET,
2339 (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
2340 }
2341 }
2342
2343 #if NBPFILTER > 0
2344 /*
2345 * If there's a BPF listener, bounce a copy of
2346 * this frame to him.
2347 */
2348 if (ifp->if_bpf)
2349 BPF_MTAP(ifp, m0);
2350 #endif
2351
2352 m_freem(m0);
2353
2354 ifp->if_flags |= IFF_OACTIVE;
2355
2356 /*
2357 * Set a timeout in case the chip goes out to lunch.
2358 */
2359 ifp->if_timer = 5;
2360
2361 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
2362 printf(WI_PRT_FMT ": wi_start: xmit failed\n", WI_PRT_ARG(sc));
2363
2364 return;
2365 }
2366
2367 STATIC int
wi_mgmt_xmit(sc,data,len)2368 wi_mgmt_xmit(sc, data, len)
2369 struct wi_softc *sc;
2370 caddr_t data;
2371 int len;
2372 {
2373 struct wi_frame tx_frame;
2374 int id;
2375 struct wi_80211_hdr *hdr;
2376 caddr_t dptr;
2377
2378 if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2379 return(ENODEV);
2380
2381 hdr = (struct wi_80211_hdr *)data;
2382 dptr = data + sizeof(struct wi_80211_hdr);
2383
2384 bzero((char *)&tx_frame, sizeof(tx_frame));
2385 id = sc->wi_tx_mgmt_id;
2386
2387 bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
2388 sizeof(struct wi_80211_hdr));
2389
2390 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
2391 tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2392 tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
2393
2394 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2395 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2396 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2397 (len - sizeof(struct wi_80211_hdr)) + 2);
2398
2399 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
2400 printf(WI_PRT_FMT ": wi_mgmt_xmit: xmit failed\n",
2401 WI_PRT_ARG(sc));
2402 return(EIO);
2403 }
2404
2405 return(0);
2406 }
2407
2408 void
wi_stop(sc)2409 wi_stop(sc)
2410 struct wi_softc *sc;
2411 {
2412 struct ifnet *ifp;
2413
2414 wihap_shutdown(sc);
2415
2416 if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2417 return;
2418
2419 DPRINTF(WID_STOP, ("wi_stop: sc %p\n", sc));
2420
2421 timeout_del(&sc->sc_timo);
2422
2423 ifp = &sc->sc_arpcom.ac_if;
2424
2425 wi_intr_enable(sc, 0);
2426 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
2427
2428 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
2429 ifp->if_timer = 0;
2430
2431 return;
2432 }
2433
2434
2435 void
wi_watchdog(ifp)2436 wi_watchdog(ifp)
2437 struct ifnet *ifp;
2438 {
2439 struct wi_softc *sc;
2440
2441 sc = ifp->if_softc;
2442
2443 printf(WI_PRT_FMT ": device timeout\n", WI_PRT_ARG(sc));
2444
2445 wi_cor_reset(sc);
2446 wi_init(sc);
2447
2448 ifp->if_oerrors++;
2449
2450 return;
2451 }
2452
2453 void
wi_detach(sc)2454 wi_detach(sc)
2455 struct wi_softc *sc;
2456 {
2457 struct ifnet *ifp;
2458 ifp = &sc->sc_arpcom.ac_if;
2459
2460 if (ifp->if_flags & IFF_RUNNING)
2461 wi_stop(sc);
2462
2463 if (sc->wi_flags & WI_FLAGS_ATTACHED) {
2464 sc->wi_flags &= ~WI_FLAGS_ATTACHED;
2465 shutdownhook_disestablish(sc->sc_sdhook);
2466 }
2467 }
2468
2469 STATIC void
wi_shutdown(arg)2470 wi_shutdown(arg)
2471 void *arg;
2472 {
2473 struct wi_softc *sc;
2474
2475 sc = arg;
2476 wi_stop(sc);
2477
2478 return;
2479 }
2480
2481 STATIC void
wi_get_id(sc)2482 wi_get_id(sc)
2483 struct wi_softc *sc;
2484 {
2485 struct wi_ltv_ver ver;
2486 const struct wi_card_ident *id;
2487 u_int16_t pri_fw_ver[3];
2488 const char *card_name;
2489 u_int16_t card_id;
2490
2491 /* get chip identity */
2492 bzero(&ver, sizeof(ver));
2493 ver.wi_type = WI_RID_CARD_ID;
2494 ver.wi_len = 5;
2495 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2496 card_id = letoh16(ver.wi_ver[0]);
2497 for (id = wi_card_ident; id->firm_type != WI_NOTYPE; id++) {
2498 if (card_id == id->card_id)
2499 break;
2500 }
2501 if (id->firm_type != WI_NOTYPE) {
2502 sc->sc_firmware_type = id->firm_type;
2503 card_name = id->card_name;
2504 } else if (ver.wi_ver[0] & htole16(0x8000)) {
2505 sc->sc_firmware_type = WI_INTERSIL;
2506 card_name = "Unknown PRISM2 chip";
2507 } else {
2508 sc->sc_firmware_type = WI_LUCENT;
2509 }
2510
2511 /* get primary firmware version (XXX - how to do Lucent?) */
2512 if (sc->sc_firmware_type != WI_LUCENT) {
2513 bzero(&ver, sizeof(ver));
2514 ver.wi_type = WI_RID_PRI_IDENTITY;
2515 ver.wi_len = 5;
2516 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2517 pri_fw_ver[0] = letoh16(ver.wi_ver[2]);
2518 pri_fw_ver[1] = letoh16(ver.wi_ver[3]);
2519 pri_fw_ver[2] = letoh16(ver.wi_ver[1]);
2520 }
2521
2522 /* get station firmware version */
2523 bzero(&ver, sizeof(ver));
2524 ver.wi_type = WI_RID_STA_IDENTITY;
2525 ver.wi_len = 5;
2526 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2527 ver.wi_ver[1] = letoh16(ver.wi_ver[1]);
2528 ver.wi_ver[2] = letoh16(ver.wi_ver[2]);
2529 ver.wi_ver[3] = letoh16(ver.wi_ver[3]);
2530 sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2531 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2532
2533 if (sc->sc_firmware_type == WI_INTERSIL &&
2534 (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2535 struct wi_ltv_str sver;
2536 char *p;
2537
2538 bzero(&sver, sizeof(sver));
2539 sver.wi_type = WI_RID_SYMBOL_IDENTITY;
2540 sver.wi_len = 7;
2541 /* value should be something like "V2.00-11" */
2542 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2543 *(p = (char *)sver.wi_str) >= 'A' &&
2544 p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2545 sc->sc_firmware_type = WI_SYMBOL;
2546 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2547 (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2548 (p[6] - '0') * 10 + (p[7] - '0');
2549 }
2550 }
2551
2552 if (sc->sc_firmware_type == WI_LUCENT) {
2553 printf("\n%s: Firmware %d.%02d variant %d, ", WI_PRT_ARG(sc),
2554 ver.wi_ver[2], ver.wi_ver[3], ver.wi_ver[1]);
2555 } else {
2556 printf("\n%s: %s%s, Firmware %d.%d.%d (primary), %d.%d.%d (station), ",
2557 WI_PRT_ARG(sc),
2558 sc->sc_firmware_type == WI_SYMBOL ? "Symbol " : "",
2559 card_name, pri_fw_ver[0], pri_fw_ver[1], pri_fw_ver[2],
2560 sc->sc_sta_firmware_ver / 10000,
2561 (sc->sc_sta_firmware_ver % 10000) / 100,
2562 sc->sc_sta_firmware_ver % 100);
2563 }
2564 }
2565
2566 STATIC int
wi_sync_media(sc,ptype,txrate)2567 wi_sync_media(sc, ptype, txrate)
2568 struct wi_softc *sc;
2569 int ptype;
2570 int txrate;
2571 {
2572 int media = sc->sc_media.ifm_cur->ifm_media;
2573 int options = IFM_OPTIONS(media);
2574 int subtype;
2575
2576 switch (txrate) {
2577 case 1:
2578 subtype = IFM_IEEE80211_DS1;
2579 break;
2580 case 2:
2581 subtype = IFM_IEEE80211_DS2;
2582 break;
2583 case 3:
2584 subtype = IFM_AUTO;
2585 break;
2586 case 5:
2587 subtype = IFM_IEEE80211_DS5;
2588 break;
2589 case 11:
2590 subtype = IFM_IEEE80211_DS11;
2591 break;
2592 default:
2593 subtype = IFM_MANUAL; /* Unable to represent */
2594 break;
2595 }
2596
2597 options &= ~IFM_OMASK;
2598 switch (ptype) {
2599 case WI_PORTTYPE_BSS:
2600 /* default port type */
2601 break;
2602 case WI_PORTTYPE_ADHOC:
2603 options |= IFM_IEEE80211_ADHOC;
2604 break;
2605 case WI_PORTTYPE_HOSTAP:
2606 options |= IFM_IEEE80211_HOSTAP;
2607 break;
2608 case WI_PORTTYPE_IBSS:
2609 if (sc->wi_create_ibss)
2610 options |= IFM_IEEE80211_IBSSMASTER;
2611 else
2612 options |= IFM_IEEE80211_IBSS;
2613 break;
2614 default:
2615 subtype = IFM_MANUAL; /* Unable to represent */
2616 break;
2617 }
2618 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
2619 IFM_INST(media));
2620 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
2621 return (EINVAL);
2622 ifmedia_set(&sc->sc_media, media);
2623 sc->wi_ptype = ptype;
2624 sc->wi_tx_rate = txrate;
2625 return (0);
2626 }
2627
2628 STATIC int
wi_media_change(ifp)2629 wi_media_change(ifp)
2630 struct ifnet *ifp;
2631 {
2632 struct wi_softc *sc = ifp->if_softc;
2633 int otype = sc->wi_ptype;
2634 int orate = sc->wi_tx_rate;
2635 int ocreate_ibss = sc->wi_create_ibss;
2636
2637 if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
2638 sc->sc_firmware_type != WI_INTERSIL)
2639 return (EINVAL);
2640
2641 sc->wi_create_ibss = 0;
2642
2643 switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
2644 case 0:
2645 sc->wi_ptype = WI_PORTTYPE_BSS;
2646 break;
2647 case IFM_IEEE80211_ADHOC:
2648 sc->wi_ptype = WI_PORTTYPE_ADHOC;
2649 break;
2650 case IFM_IEEE80211_HOSTAP:
2651 sc->wi_ptype = WI_PORTTYPE_HOSTAP;
2652 break;
2653 case IFM_IEEE80211_IBSSMASTER:
2654 case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
2655 if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
2656 return (EINVAL);
2657 sc->wi_create_ibss = 1;
2658 /* FALLTHROUGH */
2659 case IFM_IEEE80211_IBSS:
2660 sc->wi_ptype = WI_PORTTYPE_IBSS;
2661 break;
2662 default:
2663 /* Invalid combination. */
2664 return (EINVAL);
2665 }
2666
2667 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
2668 case IFM_IEEE80211_DS1:
2669 sc->wi_tx_rate = 1;
2670 break;
2671 case IFM_IEEE80211_DS2:
2672 sc->wi_tx_rate = 2;
2673 break;
2674 case IFM_AUTO:
2675 sc->wi_tx_rate = 3;
2676 break;
2677 case IFM_IEEE80211_DS5:
2678 sc->wi_tx_rate = 5;
2679 break;
2680 case IFM_IEEE80211_DS11:
2681 sc->wi_tx_rate = 11;
2682 break;
2683 }
2684
2685 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
2686 if (otype != sc->wi_ptype || orate != sc->wi_tx_rate ||
2687 ocreate_ibss != sc->wi_create_ibss)
2688 wi_init(sc);
2689 }
2690
2691 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2692
2693 return (0);
2694 }
2695
2696 STATIC void
wi_media_status(ifp,imr)2697 wi_media_status(ifp, imr)
2698 struct ifnet *ifp;
2699 struct ifmediareq *imr;
2700 {
2701 struct wi_softc *sc = ifp->if_softc;
2702 struct wi_req wreq;
2703
2704 if (!(sc->sc_arpcom.ac_if.if_flags & IFF_UP)) {
2705 imr->ifm_active = IFM_IEEE80211|IFM_NONE;
2706 imr->ifm_status = 0;
2707 return;
2708 }
2709
2710 if (sc->wi_tx_rate == 3) {
2711 imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
2712
2713 wreq.wi_type = WI_RID_CUR_TX_RATE;
2714 wreq.wi_len = WI_MAX_DATALEN;
2715 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
2716 switch (letoh16(wreq.wi_val[0])) {
2717 case 1:
2718 imr->ifm_active |= IFM_IEEE80211_DS1;
2719 break;
2720 case 2:
2721 imr->ifm_active |= IFM_IEEE80211_DS2;
2722 break;
2723 case 6:
2724 imr->ifm_active |= IFM_IEEE80211_DS5;
2725 break;
2726 case 11:
2727 imr->ifm_active |= IFM_IEEE80211_DS11;
2728 break;
2729 }
2730 }
2731 } else {
2732 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2733 }
2734
2735 imr->ifm_status = IFM_AVALID;
2736 switch (sc->wi_ptype) {
2737 case WI_PORTTYPE_ADHOC:
2738 case WI_PORTTYPE_IBSS:
2739 /*
2740 * XXX: It would be nice if we could give some actually
2741 * useful status like whether we joined another IBSS or
2742 * created one ourselves.
2743 */
2744 /* FALLTHROUGH */
2745 case WI_PORTTYPE_HOSTAP:
2746 imr->ifm_status |= IFM_ACTIVE;
2747 break;
2748 default:
2749 wreq.wi_type = WI_RID_COMMQUAL;
2750 wreq.wi_len = WI_MAX_DATALEN;
2751 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2752 letoh16(wreq.wi_val[0]) != 0)
2753 imr->ifm_status |= IFM_ACTIVE;
2754 }
2755 }
2756
2757 STATIC int
wi_set_nwkey(sc,nwkey)2758 wi_set_nwkey(sc, nwkey)
2759 struct wi_softc *sc;
2760 struct ieee80211_nwkey *nwkey;
2761 {
2762 int i, len, error;
2763 struct wi_req wreq;
2764 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
2765
2766 if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
2767 return ENODEV;
2768 if (nwkey->i_defkid <= 0 || nwkey->i_defkid > IEEE80211_WEP_NKID)
2769 return EINVAL;
2770 memcpy(wk, &sc->wi_keys, sizeof(*wk));
2771 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2772 if (nwkey->i_key[i].i_keydat == NULL)
2773 continue;
2774 len = nwkey->i_key[i].i_keylen;
2775 if (len > sizeof(wk->wi_keys[i].wi_keydat))
2776 return EINVAL;
2777 error = copyin(nwkey->i_key[i].i_keydat,
2778 wk->wi_keys[i].wi_keydat, len);
2779 if (error)
2780 return error;
2781 wk->wi_keys[i].wi_keylen = htole16(len);
2782 }
2783
2784 wk->wi_len = (sizeof(*wk) / 2) + 1;
2785 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2786 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
2787 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2788 if (error)
2789 return error;
2790 }
2791 if ((error = wi_setdef(sc, &wreq)))
2792 return (error);
2793
2794 wreq.wi_len = 2;
2795 wreq.wi_type = WI_RID_TX_CRYPT_KEY;
2796 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
2797 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
2798 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2799 if (error)
2800 return error;
2801 }
2802 if ((error = wi_setdef(sc, &wreq)))
2803 return (error);
2804
2805 wreq.wi_type = WI_RID_ENCRYPTION;
2806 wreq.wi_val[0] = htole16(nwkey->i_wepon);
2807 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
2808 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2809 if (error)
2810 return error;
2811 }
2812 if ((error = wi_setdef(sc, &wreq)))
2813 return (error);
2814
2815 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP)
2816 wi_init(sc);
2817 return 0;
2818 }
2819
2820 STATIC int
wi_get_nwkey(sc,nwkey)2821 wi_get_nwkey(sc, nwkey)
2822 struct wi_softc *sc;
2823 struct ieee80211_nwkey *nwkey;
2824 {
2825 int i, len, error;
2826 struct wi_ltv_keys *wk = &sc->wi_keys;
2827
2828 if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
2829 return ENODEV;
2830 nwkey->i_wepon = sc->wi_use_wep;
2831 nwkey->i_defkid = sc->wi_tx_key + 1;
2832
2833 /* do not show any keys to non-root user */
2834 error = suser(curproc, 0);
2835 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2836 if (nwkey->i_key[i].i_keydat == NULL)
2837 continue;
2838 /* error holds results of suser() for the first time */
2839 if (error)
2840 return error;
2841 len = letoh16(wk->wi_keys[i].wi_keylen);
2842 if (nwkey->i_key[i].i_keylen < len)
2843 return ENOSPC;
2844 nwkey->i_key[i].i_keylen = len;
2845 error = copyout(wk->wi_keys[i].wi_keydat,
2846 nwkey->i_key[i].i_keydat, len);
2847 if (error)
2848 return error;
2849 }
2850 return 0;
2851 }
2852
2853 STATIC int
wi_set_pm(struct wi_softc * sc,struct ieee80211_power * power)2854 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2855 {
2856
2857 sc->wi_pm_enabled = power->i_enabled;
2858 sc->wi_max_sleep = power->i_maxsleep;
2859
2860 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP)
2861 wi_init(sc);
2862
2863 return (0);
2864 }
2865
2866 STATIC int
wi_get_pm(struct wi_softc * sc,struct ieee80211_power * power)2867 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2868 {
2869
2870 power->i_enabled = sc->wi_pm_enabled;
2871 power->i_maxsleep = sc->wi_max_sleep;
2872
2873 return (0);
2874 }
2875
2876 STATIC int
wi_set_ssid(ws,id,len)2877 wi_set_ssid(ws, id, len)
2878 struct ieee80211_nwid *ws;
2879 u_int8_t *id;
2880 int len;
2881 {
2882
2883 if (len > IEEE80211_NWID_LEN)
2884 return (EINVAL);
2885 ws->i_len = len;
2886 memcpy(ws->i_nwid, id, len);
2887 return (0);
2888 }
2889
2890 STATIC int
wi_get_debug(sc,wreq)2891 wi_get_debug(sc, wreq)
2892 struct wi_softc *sc;
2893 struct wi_req *wreq;
2894 {
2895 int error = 0;
2896
2897 wreq->wi_len = 1;
2898
2899 switch (wreq->wi_type) {
2900 case WI_DEBUG_SLEEP:
2901 wreq->wi_len++;
2902 wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep);
2903 break;
2904 case WI_DEBUG_DELAYSUPP:
2905 wreq->wi_len++;
2906 wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp);
2907 break;
2908 case WI_DEBUG_TXSUPP:
2909 wreq->wi_len++;
2910 wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp);
2911 break;
2912 case WI_DEBUG_MONITOR:
2913 wreq->wi_len++;
2914 wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor);
2915 break;
2916 case WI_DEBUG_LEDTEST:
2917 wreq->wi_len += 3;
2918 wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest);
2919 wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0);
2920 wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1);
2921 break;
2922 case WI_DEBUG_CONTTX:
2923 wreq->wi_len += 2;
2924 wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx);
2925 wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0);
2926 break;
2927 case WI_DEBUG_CONTRX:
2928 wreq->wi_len++;
2929 wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx);
2930 break;
2931 case WI_DEBUG_SIGSTATE:
2932 wreq->wi_len += 2;
2933 wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate);
2934 wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0);
2935 break;
2936 case WI_DEBUG_CONFBITS:
2937 wreq->wi_len += 2;
2938 wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits);
2939 wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0);
2940 break;
2941 default:
2942 error = EIO;
2943 break;
2944 }
2945
2946 return (error);
2947 }
2948
2949 STATIC int
wi_set_debug(sc,wreq)2950 wi_set_debug(sc, wreq)
2951 struct wi_softc *sc;
2952 struct wi_req *wreq;
2953 {
2954 int error = 0;
2955 u_int16_t cmd, param0 = 0, param1 = 0;
2956
2957 switch (wreq->wi_type) {
2958 case WI_DEBUG_RESET:
2959 case WI_DEBUG_INIT:
2960 case WI_DEBUG_CALENABLE:
2961 break;
2962 case WI_DEBUG_SLEEP:
2963 sc->wi_debug.wi_sleep = 1;
2964 break;
2965 case WI_DEBUG_WAKE:
2966 sc->wi_debug.wi_sleep = 0;
2967 break;
2968 case WI_DEBUG_CHAN:
2969 param0 = letoh16(wreq->wi_val[0]);
2970 break;
2971 case WI_DEBUG_DELAYSUPP:
2972 sc->wi_debug.wi_delaysupp = 1;
2973 break;
2974 case WI_DEBUG_TXSUPP:
2975 sc->wi_debug.wi_txsupp = 1;
2976 break;
2977 case WI_DEBUG_MONITOR:
2978 sc->wi_debug.wi_monitor = 1;
2979 break;
2980 case WI_DEBUG_LEDTEST:
2981 param0 = letoh16(wreq->wi_val[0]);
2982 param1 = letoh16(wreq->wi_val[1]);
2983 sc->wi_debug.wi_ledtest = 1;
2984 sc->wi_debug.wi_ledtest_param0 = param0;
2985 sc->wi_debug.wi_ledtest_param1 = param1;
2986 break;
2987 case WI_DEBUG_CONTTX:
2988 param0 = letoh16(wreq->wi_val[0]);
2989 sc->wi_debug.wi_conttx = 1;
2990 sc->wi_debug.wi_conttx_param0 = param0;
2991 break;
2992 case WI_DEBUG_STOPTEST:
2993 sc->wi_debug.wi_delaysupp = 0;
2994 sc->wi_debug.wi_txsupp = 0;
2995 sc->wi_debug.wi_monitor = 0;
2996 sc->wi_debug.wi_ledtest = 0;
2997 sc->wi_debug.wi_ledtest_param0 = 0;
2998 sc->wi_debug.wi_ledtest_param1 = 0;
2999 sc->wi_debug.wi_conttx = 0;
3000 sc->wi_debug.wi_conttx_param0 = 0;
3001 sc->wi_debug.wi_contrx = 0;
3002 sc->wi_debug.wi_sigstate = 0;
3003 sc->wi_debug.wi_sigstate_param0 = 0;
3004 break;
3005 case WI_DEBUG_CONTRX:
3006 sc->wi_debug.wi_contrx = 1;
3007 break;
3008 case WI_DEBUG_SIGSTATE:
3009 param0 = letoh16(wreq->wi_val[0]);
3010 sc->wi_debug.wi_sigstate = 1;
3011 sc->wi_debug.wi_sigstate_param0 = param0;
3012 break;
3013 case WI_DEBUG_CONFBITS:
3014 param0 = letoh16(wreq->wi_val[0]);
3015 param1 = letoh16(wreq->wi_val[1]);
3016 sc->wi_debug.wi_confbits = param0;
3017 sc->wi_debug.wi_confbits_param0 = param1;
3018 break;
3019 default:
3020 error = EIO;
3021 break;
3022 }
3023
3024 if (error)
3025 return (error);
3026
3027 cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3028 error = wi_cmd(sc, cmd, param0, param1, 0);
3029
3030 return (error);
3031 }
3032