This source file includes following definitions.
- wi_attach
- wi_intr_enable
- wi_intr_ack
- wi_intr
- wi_get_fid_io
- wi_rxeof
- wi_txeof
- wi_inquire
- wi_update_stats
- wi_cmd_io
- wi_reset
- wi_cor_reset
- wi_read_record_io
- wi_write_record_io
- wi_seek
- wi_read_data_io
- wi_write_data_io
- wi_alloc_nicmem_io
- wi_setmulti
- wi_setdef
- wi_ioctl
- wi_scan_timeout
- wi_init_io
- wi_do_hostencrypt
- wi_do_hostdecrypt
- wi_start
- wi_mgmt_xmit
- wi_stop
- wi_watchdog
- wi_detach
- wi_shutdown
- wi_get_id
- wi_sync_media
- wi_media_change
- wi_media_status
- wi_set_nwkey
- wi_get_nwkey
- wi_set_pm
- wi_get_pm
- wi_set_txpower
- wi_get_txpower
- wi_set_ssid
- wi_get_debug
- wi_set_debug
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 #define WI_HERMES_AUTOINC_WAR
63 #define WI_HERMES_STATS_WAR
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 <net80211/ieee80211_var.h>
91 #include <net80211/ieee80211_ioctl.h>
92
93 #if NBPFILTER > 0
94 #include <net/bpf.h>
95 #endif
96
97 #include <machine/bus.h>
98
99 #include <dev/rndvar.h>
100
101 #include <dev/ic/if_wireg.h>
102 #include <dev/ic/if_wi_ieee.h>
103 #include <dev/ic/if_wivar.h>
104
105 #include <crypto/arc4.h>
106
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
124 #define DPRINTF(mask,args)
125 #endif
126
127 #if !defined(lint) && !defined(__OpenBSD__)
128 static const char rcsid[] =
129 "$OpenBSD: if_wi.c,v 1.137 2006/11/26 19:46:28 deraadt Exp $";
130 #endif
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 STATIC int wi_set_txpower(struct wi_softc *, struct ieee80211_txpower *);
170 STATIC int wi_get_txpower(struct wi_softc *, struct ieee80211_txpower *);
171
172 STATIC int wi_get_debug(struct wi_softc *, struct wi_req *);
173 STATIC int wi_set_debug(struct wi_softc *, struct wi_req *);
174
175 STATIC void wi_do_hostencrypt(struct wi_softc *, caddr_t, int);
176 STATIC int wi_do_hostdecrypt(struct wi_softc *, caddr_t, int);
177
178 STATIC int wi_alloc_nicmem_io(struct wi_softc *, int, int *);
179 STATIC int wi_get_fid_io(struct wi_softc *sc, int fid);
180 STATIC void wi_intr_enable(struct wi_softc *sc, int mode);
181 STATIC void wi_intr_ack(struct wi_softc *sc, int mode);
182 void wi_scan_timeout(void *);
183
184
185 struct cfdriver wi_cd = {
186 NULL, "wi", DV_IFNET
187 };
188
189 const struct wi_card_ident wi_card_ident[] = {
190 WI_CARD_IDS
191 };
192
193 struct wi_funcs wi_func_io = {
194 wi_cmd_io,
195 wi_read_record_io,
196 wi_write_record_io,
197 wi_alloc_nicmem_io,
198 wi_read_data_io,
199 wi_write_data_io,
200 wi_get_fid_io,
201 wi_init_io,
202
203 wi_start,
204 wi_ioctl,
205 wi_watchdog,
206 wi_inquire,
207 };
208
209 int
210 wi_attach(struct wi_softc *sc, struct wi_funcs *funcs)
211 {
212 struct ieee80211com *ic;
213 struct ifnet *ifp;
214 struct wi_ltv_macaddr mac;
215 struct wi_ltv_rates rates;
216 struct wi_ltv_gen gen;
217 int error;
218
219 ic = &sc->sc_ic;
220 ifp = &ic->ic_if;
221
222 sc->sc_funcs = funcs;
223 sc->wi_cmd_count = 500;
224
225 wi_reset(sc);
226
227
228 mac.wi_type = WI_RID_MAC_NODE;
229 mac.wi_len = 4;
230 error = wi_read_record(sc, (struct wi_ltv_gen *)&mac);
231 if (error) {
232 printf(": unable to read station address\n");
233 return (error);
234 }
235 bcopy((char *)&mac.wi_mac_addr, (char *)&ic->ic_myaddr,
236 IEEE80211_ADDR_LEN);
237
238 wi_get_id(sc);
239 printf("address %s", ether_sprintf(ic->ic_myaddr));
240
241 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
242 ifp->if_softc = sc;
243 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
244 ifp->if_ioctl = funcs->f_ioctl;
245 ifp->if_start = funcs->f_start;
246 ifp->if_watchdog = funcs->f_watchdog;
247 ifp->if_baudrate = 10000000;
248 IFQ_SET_READY(&ifp->if_snd);
249
250 (void)wi_set_ssid(&sc->wi_node_name, WI_DEFAULT_NODENAME,
251 sizeof(WI_DEFAULT_NODENAME) - 1);
252 (void)wi_set_ssid(&sc->wi_net_name, WI_DEFAULT_NETNAME,
253 sizeof(WI_DEFAULT_NETNAME) - 1);
254 (void)wi_set_ssid(&sc->wi_ibss_name, WI_DEFAULT_IBSS,
255 sizeof(WI_DEFAULT_IBSS) - 1);
256
257 sc->wi_portnum = WI_DEFAULT_PORT;
258 sc->wi_ptype = WI_PORTTYPE_BSS;
259 sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
260 sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
261 sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
262 sc->wi_max_data_len = WI_DEFAULT_DATALEN;
263 sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
264 sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
265 sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
266 sc->wi_roaming = WI_DEFAULT_ROAMING;
267 sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
268 sc->wi_diversity = WI_DEFAULT_DIVERSITY;
269 sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
270
271
272
273
274
275
276
277 gen.wi_type = WI_RID_OWN_CHNL;
278 gen.wi_len = 2;
279 if (wi_read_record(sc, &gen) == 0)
280 sc->wi_channel = letoh16(gen.wi_val);
281 else
282 sc->wi_channel = 3;
283
284
285
286
287 switch (sc->sc_firmware_type) {
288 case WI_LUCENT:
289 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
290 if (sc->sc_sta_firmware_ver >= 60000)
291 sc->wi_flags |= WI_FLAGS_HAS_MOR;
292 if (sc->sc_sta_firmware_ver >= 60006) {
293 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
294 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
295 }
296 sc->wi_ibss_port = htole16(1);
297 break;
298 case WI_INTERSIL:
299 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
300
301 if (sc->sc_sta_firmware_ver < 10000)
302 sc->wi_cmd_count = 5000;
303 else
304 sc->wi_cmd_count = 2000;
305 if (sc->sc_sta_firmware_ver >= 800) {
306 #ifndef SMALL_KERNEL
307
308
309
310
311 if ((sc->sc_sta_firmware_ver != 10402) &&
312 (!(sc->wi_flags & WI_FLAGS_BUS_USB)))
313 sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
314 #endif
315 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
316 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
317 }
318 if (sc->sc_sta_firmware_ver >= 10603)
319 sc->wi_flags |= WI_FLAGS_HAS_ENH_SECURITY;
320 sc->wi_ibss_port = htole16(0);
321 break;
322 case WI_SYMBOL:
323 sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
324 if (sc->sc_sta_firmware_ver >= 20000)
325 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
326 if (sc->sc_sta_firmware_ver >= 25000)
327 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
328 sc->wi_ibss_port = htole16(4);
329 break;
330 }
331
332
333
334
335 gen.wi_type = WI_RID_WEP_AVAIL;
336 gen.wi_len = 2;
337 if (wi_read_record(sc, &gen) == 0 && gen.wi_val != htole16(0))
338 sc->wi_flags |= WI_FLAGS_HAS_WEP;
339 timeout_set(&sc->sc_timo, funcs->f_inquire, sc);
340
341 bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
342
343
344 rates.wi_type = WI_RID_DATA_RATES;
345 rates.wi_len = sizeof(rates.wi_rates);
346 if (wi_read_record(sc, (struct wi_ltv_gen *)&rates) == 0) {
347 int i, nrates;
348
349 nrates = letoh16(*(u_int16_t *)rates.wi_rates);
350 if (nrates > sizeof(rates.wi_rates) - 2)
351 nrates = sizeof(rates.wi_rates) - 2;
352
353 sc->wi_supprates = 0;
354 for (i = 0; i < nrates; i++)
355 sc->wi_supprates |= rates.wi_rates[2 + i];
356 } else
357 sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
358 WI_SUPPRATES_5M | WI_SUPPRATES_11M;
359
360 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
361 #define ADD(m, c) ifmedia_add(&sc->sc_media, (m), (c), NULL)
362 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
363 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
364 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
365 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
366 0), 0);
367 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
368 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
369 IFM_IEEE80211_IBSSMASTER, 0), 0);
370 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
371 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
372 IFM_IEEE80211_HOSTAP, 0), 0);
373 if (sc->wi_supprates & WI_SUPPRATES_1M) {
374 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
375 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
376 IFM_IEEE80211_ADHOC, 0), 0);
377 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
378 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
379 IFM_IEEE80211_IBSS, 0), 0);
380 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
381 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
382 IFM_IEEE80211_IBSSMASTER, 0), 0);
383 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
384 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
385 IFM_IEEE80211_HOSTAP, 0), 0);
386 }
387 if (sc->wi_supprates & WI_SUPPRATES_2M) {
388 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
389 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
390 IFM_IEEE80211_ADHOC, 0), 0);
391 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
392 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
393 IFM_IEEE80211_IBSS, 0), 0);
394 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
395 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
396 IFM_IEEE80211_IBSSMASTER, 0), 0);
397 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
398 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
399 IFM_IEEE80211_HOSTAP, 0), 0);
400 }
401 if (sc->wi_supprates & WI_SUPPRATES_5M) {
402 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
403 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
404 IFM_IEEE80211_ADHOC, 0), 0);
405 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
406 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
407 IFM_IEEE80211_IBSS, 0), 0);
408 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
409 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
410 IFM_IEEE80211_IBSSMASTER, 0), 0);
411 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
412 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
413 IFM_IEEE80211_HOSTAP, 0), 0);
414 }
415 if (sc->wi_supprates & WI_SUPPRATES_11M) {
416 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
417 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
418 IFM_IEEE80211_ADHOC, 0), 0);
419 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
420 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
421 IFM_IEEE80211_IBSS, 0), 0);
422 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
423 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
424 IFM_IEEE80211_IBSSMASTER, 0), 0);
425 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
426 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
427 IFM_IEEE80211_HOSTAP, 0), 0);
428 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
429 }
430 #undef ADD
431 ifmedia_set(&sc->sc_media,
432 IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
433
434
435
436
437 if_attach(ifp);
438 memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
439 ETHER_ADDR_LEN);
440 ether_ifattach(ifp);
441 printf("\n");
442
443 sc->wi_flags |= WI_FLAGS_ATTACHED;
444
445 #if NBPFILTER > 0
446 BPFATTACH(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
447 #endif
448
449 sc->sc_sdhook = shutdownhook_establish(wi_shutdown, sc);
450
451 wi_init(sc);
452 wi_stop(sc);
453
454 return (0);
455 }
456
457 STATIC void
458 wi_intr_enable(struct wi_softc *sc, int mode)
459 {
460 if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
461 CSR_WRITE_2(sc, WI_INT_EN, mode);
462 }
463
464 STATIC void
465 wi_intr_ack(struct wi_softc *sc, int mode)
466 {
467 if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
468 CSR_WRITE_2(sc, WI_EVENT_ACK, mode);
469 }
470
471 int
472 wi_intr(void *vsc)
473 {
474 struct wi_softc *sc = vsc;
475 struct ifnet *ifp;
476 u_int16_t status;
477
478 DPRINTF(WID_INTR, ("wi_intr: sc %p\n", sc));
479
480 ifp = &sc->sc_ic.ic_if;
481
482 if (!(sc->wi_flags & WI_FLAGS_ATTACHED) || !(ifp->if_flags & IFF_UP)) {
483 CSR_WRITE_2(sc, WI_INT_EN, 0);
484 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xffff);
485 return (0);
486 }
487
488
489 CSR_WRITE_2(sc, WI_INT_EN, 0);
490
491 status = CSR_READ_2(sc, WI_EVENT_STAT);
492 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
493
494 if (status & WI_EV_RX) {
495 wi_rxeof(sc);
496 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
497 }
498
499 if (status & WI_EV_TX) {
500 wi_txeof(sc, status);
501 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
502 }
503
504 if (status & WI_EV_ALLOC) {
505 int id;
506 id = CSR_READ_2(sc, WI_ALLOC_FID);
507 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
508 if (id == sc->wi_tx_data_id)
509 wi_txeof(sc, status);
510 }
511
512 if (status & WI_EV_INFO) {
513 wi_update_stats(sc);
514 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
515 }
516
517 if (status & WI_EV_TX_EXC) {
518 wi_txeof(sc, status);
519 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
520 }
521
522 if (status & WI_EV_INFO_DROP) {
523 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
524 }
525
526
527 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
528
529 if (!IFQ_IS_EMPTY(&ifp->if_snd))
530 wi_start(ifp);
531
532 return (1);
533 }
534
535 STATIC int
536 wi_get_fid_io(struct wi_softc *sc, int fid)
537 {
538 return CSR_READ_2(sc, fid);
539 }
540
541
542 void
543 wi_rxeof(struct wi_softc *sc)
544 {
545 struct ifnet *ifp;
546 struct ether_header *eh;
547 struct mbuf *m;
548 caddr_t olddata;
549 u_int16_t ftype;
550 int maxlen;
551 int id;
552
553 ifp = &sc->sc_ic.ic_if;
554
555 id = wi_get_fid(sc, WI_RX_FID);
556
557 if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
558 struct wi_frame *rx_frame;
559 int datlen, hdrlen;
560
561 MGETHDR(m, M_DONTWAIT, MT_DATA);
562 if (m == NULL) {
563 ifp->if_ierrors++;
564 return;
565 }
566 MCLGET(m, M_DONTWAIT);
567 if (!(m->m_flags & M_EXT)) {
568 m_freem(m);
569 ifp->if_ierrors++;
570 return;
571 }
572
573 m->m_pkthdr.rcvif = ifp;
574
575 if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
576 sizeof(struct wi_frame))) {
577 m_freem(m);
578 ifp->if_ierrors++;
579 return;
580 }
581
582 rx_frame = mtod(m, struct wi_frame *);
583
584 if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)) {
585 m_freem(m);
586 ifp->if_ierrors++;
587 return;
588 }
589
590 switch ((letoh16(rx_frame->wi_status) & WI_STAT_MAC_PORT)
591 >> 8) {
592 case 7:
593 switch (letoh16(rx_frame->wi_frame_ctl) &
594 WI_FCTL_FTYPE) {
595 case WI_FTYPE_DATA:
596 hdrlen = WI_DATA_HDRLEN;
597 datlen = letoh16(rx_frame->wi_dat_len);
598 break;
599 case WI_FTYPE_MGMT:
600 hdrlen = WI_MGMT_HDRLEN;
601 datlen = letoh16(rx_frame->wi_dat_len);
602 break;
603 case WI_FTYPE_CTL:
604 hdrlen = WI_CTL_HDRLEN;
605 datlen = 0;
606 break;
607 default:
608 printf(WI_PRT_FMT ": received packet of "
609 "unknown type on port 7\n", WI_PRT_ARG(sc));
610 m_freem(m);
611 ifp->if_ierrors++;
612 return;
613 }
614 break;
615 case 0:
616 hdrlen = WI_DATA_HDRLEN;
617 datlen = letoh16(rx_frame->wi_dat_len);
618 break;
619 default:
620 printf(WI_PRT_FMT ": received packet on invalid port "
621 "(wi_status=0x%x)\n", WI_PRT_ARG(sc),
622 letoh16(rx_frame->wi_status));
623 m_freem(m);
624 ifp->if_ierrors++;
625 return;
626 }
627
628 if ((hdrlen + datlen + 2) > MCLBYTES) {
629 m_freem(m);
630 ifp->if_ierrors++;
631 return;
632 }
633
634 if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
635 datlen + 2)) {
636 m_freem(m);
637 ifp->if_ierrors++;
638 return;
639 }
640
641 m->m_pkthdr.len = m->m_len = hdrlen + datlen;
642 } else {
643 struct wi_frame rx_frame;
644
645
646 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
647 sizeof(rx_frame))) {
648 ifp->if_ierrors++;
649 return;
650 }
651
652
653 if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) {
654 ifp->if_ierrors++;
655 return;
656 }
657
658
659 ftype = letoh16(rx_frame.wi_frame_ctl) & WI_FCTL_FTYPE;
660
661 MGETHDR(m, M_DONTWAIT, MT_DATA);
662 if (m == NULL) {
663 ifp->if_ierrors++;
664 return;
665 }
666 MCLGET(m, M_DONTWAIT);
667 if (!(m->m_flags & M_EXT)) {
668 m_freem(m);
669 ifp->if_ierrors++;
670 return;
671 }
672
673 olddata = m->m_data;
674
675 m->m_data = (caddr_t)ALIGN(m->m_data +
676 sizeof(struct ether_header)) - sizeof(struct ether_header);
677
678 eh = mtod(m, struct ether_header *);
679 maxlen = MCLBYTES - (m->m_data - olddata);
680 m->m_pkthdr.rcvif = ifp;
681
682 if (ftype == WI_FTYPE_MGMT &&
683 sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
684
685 u_int16_t rxlen = letoh16(rx_frame.wi_dat_len);
686
687 if ((WI_802_11_OFFSET_RAW + rxlen + 2) > maxlen) {
688 printf("%s: oversized mgmt packet received in "
689 "hostap mode (wi_dat_len=%d, "
690 "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
691 rxlen, letoh16(rx_frame.wi_status));
692 m_freem(m);
693 ifp->if_ierrors++;
694 return;
695 }
696
697
698 bcopy(&rx_frame, mtod(m, void *),
699 sizeof(struct wi_frame));
700 if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
701 mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
702 rxlen + 2)) {
703 m_freem(m);
704 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
705 printf("wihap: failed to copy header\n");
706 ifp->if_ierrors++;
707 return;
708 }
709
710 m->m_pkthdr.len = m->m_len =
711 WI_802_11_OFFSET_RAW + rxlen;
712
713
714
715 wihap_mgmt_input(sc, &rx_frame, m);
716
717 return;
718 }
719
720 switch (letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) {
721 case WI_STAT_1042:
722 case WI_STAT_TUNNEL:
723 case WI_STAT_WMP_MSG:
724 if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) >
725 maxlen) {
726 printf(WI_PRT_FMT ": oversized packet received "
727 "(wi_dat_len=%d, wi_status=0x%x)\n",
728 WI_PRT_ARG(sc),
729 letoh16(rx_frame.wi_dat_len),
730 letoh16(rx_frame.wi_status));
731 m_freem(m);
732 ifp->if_ierrors++;
733 return;
734 }
735 m->m_pkthdr.len = m->m_len =
736 letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
737
738 bcopy((char *)&rx_frame.wi_dst_addr,
739 (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
740 bcopy((char *)&rx_frame.wi_src_addr,
741 (char *)&eh->ether_shost, ETHER_ADDR_LEN);
742 bcopy((char *)&rx_frame.wi_type,
743 (char *)&eh->ether_type, ETHER_TYPE_LEN);
744
745 if (wi_read_data(sc, id, WI_802_11_OFFSET,
746 mtod(m, caddr_t) + sizeof(struct ether_header),
747 m->m_len + 2)) {
748 ifp->if_ierrors++;
749 m_freem(m);
750 return;
751 }
752 break;
753 default:
754 if ((letoh16(rx_frame.wi_dat_len) +
755 sizeof(struct ether_header)) > maxlen) {
756 printf(WI_PRT_FMT ": oversized packet received "
757 "(wi_dat_len=%d, wi_status=0x%x)\n",
758 WI_PRT_ARG(sc),
759 letoh16(rx_frame.wi_dat_len),
760 letoh16(rx_frame.wi_status));
761 m_freem(m);
762 ifp->if_ierrors++;
763 return;
764 }
765 m->m_pkthdr.len = m->m_len =
766 letoh16(rx_frame.wi_dat_len) +
767 sizeof(struct ether_header);
768
769 if (wi_read_data(sc, id, WI_802_3_OFFSET,
770 mtod(m, caddr_t), m->m_len + 2)) {
771 m_freem(m);
772 ifp->if_ierrors++;
773 return;
774 }
775 break;
776 }
777
778 ifp->if_ipackets++;
779
780 if (sc->wi_use_wep &&
781 rx_frame.wi_frame_ctl & htole16(WI_FCTL_WEP)) {
782 int len;
783
784 switch (sc->wi_crypto_algorithm) {
785 case WI_CRYPTO_FIRMWARE_WEP:
786 break;
787 case WI_CRYPTO_SOFTWARE_WEP:
788 m_copydata(m, 0, m->m_pkthdr.len,
789 (caddr_t)sc->wi_rxbuf);
790 len = m->m_pkthdr.len -
791 sizeof(struct ether_header);
792 if (wi_do_hostdecrypt(sc, sc->wi_rxbuf +
793 sizeof(struct ether_header), len)) {
794 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
795 printf(WI_PRT_FMT ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc));
796 m_freem(m);
797 ifp->if_ierrors++;
798 return;
799 }
800 len -= IEEE80211_WEP_IVLEN +
801 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
802
803
804
805
806
807
808 m_copyback(m, sizeof(struct ether_header) -
809 WI_ETHERTYPE_LEN, WI_ETHERTYPE_LEN +
810 (len - WI_SNAPHDR_LEN),
811 sc->wi_rxbuf + sizeof(struct ether_header) +
812 IEEE80211_WEP_IVLEN +
813 IEEE80211_WEP_KIDLEN + WI_SNAPHDR_LEN);
814 m_adj(m, -(WI_ETHERTYPE_LEN +
815 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
816 WI_SNAPHDR_LEN));
817 break;
818 }
819 }
820
821 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
822
823
824
825
826
827
828 if (wihap_data_input(sc, &rx_frame, m))
829 return;
830 }
831 }
832
833 #if NBPFILTER > 0
834
835 if (ifp->if_bpf)
836 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
837 #endif
838
839
840 if (sc->wi_procframe || sc->wi_debug.wi_monitor)
841 m_freem(m);
842 else
843 ether_input_mbuf(ifp, m);
844
845 return;
846 }
847
848 void
849 wi_txeof(struct wi_softc *sc, int status)
850 {
851 struct ifnet *ifp;
852
853 ifp = &sc->sc_ic.ic_if;
854
855 ifp->if_timer = 0;
856 ifp->if_flags &= ~IFF_OACTIVE;
857
858 if (status & WI_EV_TX_EXC)
859 ifp->if_oerrors++;
860 else
861 ifp->if_opackets++;
862
863 return;
864 }
865
866 void
867 wi_inquire(void *xsc)
868 {
869 struct wi_softc *sc;
870 struct ifnet *ifp;
871 int s, rv;
872
873 sc = xsc;
874 ifp = &sc->sc_ic.ic_if;
875
876 timeout_add(&sc->sc_timo, hz * 60);
877
878
879 if (ifp->if_flags & IFF_OACTIVE)
880 return;
881
882 s = splnet();
883 rv = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
884 splx(s);
885 if (rv)
886 printf(WI_PRT_FMT ": wi_cmd failed with %d\n", WI_PRT_ARG(sc),
887 rv);
888
889 return;
890 }
891
892 void
893 wi_update_stats(struct wi_softc *sc)
894 {
895 struct wi_ltv_gen gen;
896 u_int16_t id;
897 struct ifnet *ifp;
898 u_int32_t *ptr;
899 int len, i;
900 u_int16_t t;
901
902 ifp = &sc->sc_ic.ic_if;
903
904 id = wi_get_fid(sc, WI_INFO_FID);
905
906 wi_read_data(sc, id, 0, (char *)&gen, 4);
907
908 if (gen.wi_type == htole16(WI_INFO_SCAN_RESULTS)) {
909 sc->wi_scanbuf_len = letoh16(gen.wi_len);
910 wi_read_data(sc, id, 4, (caddr_t)sc->wi_scanbuf,
911 sc->wi_scanbuf_len * 2);
912 return;
913 } else if (gen.wi_type != htole16(WI_INFO_COUNTERS))
914 return;
915
916
917 len = (letoh16(gen.wi_len) - 1 < sizeof(sc->wi_stats) / 4) ?
918 letoh16(gen.wi_len) - 1 : sizeof(sc->wi_stats) / 4;
919
920 ptr = (u_int32_t *)&sc->wi_stats;
921
922 for (i = 0; i < len; i++) {
923 if (sc->wi_flags & WI_FLAGS_BUS_USB) {
924 wi_read_data(sc, id, 4 + i*2, (char *)&t, 2);
925 t = letoh16(t);
926 } else
927 t = CSR_READ_2(sc, WI_DATA1);
928 #ifdef WI_HERMES_STATS_WAR
929 if (t > 0xF000)
930 t = ~t & 0xFFFF;
931 #endif
932 ptr[i] += t;
933 }
934
935 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
936 sc->wi_stats.wi_tx_multi_retries +
937 sc->wi_stats.wi_tx_retry_limit;
938
939 return;
940 }
941
942 STATIC int
943 wi_cmd_io(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
944 {
945 int i, s = 0;
946
947
948 for (i = sc->wi_cmd_count; i--; DELAY(1000)) {
949 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
950 break;
951 }
952 if (i < 0) {
953 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
954 printf(WI_PRT_FMT ": wi_cmd_io: busy bit won't clear\n",
955 WI_PRT_ARG(sc));
956 return(ETIMEDOUT);
957 }
958
959 CSR_WRITE_2(sc, WI_PARAM0, val0);
960 CSR_WRITE_2(sc, WI_PARAM1, val1);
961 CSR_WRITE_2(sc, WI_PARAM2, val2);
962 CSR_WRITE_2(sc, WI_COMMAND, cmd);
963
964 for (i = WI_TIMEOUT; i--; DELAY(WI_DELAY)) {
965
966
967
968
969 s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
970 if (s) {
971
972 s = CSR_READ_2(sc, WI_STATUS);
973 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
974 if (s & WI_STAT_CMD_RESULT)
975 return(EIO);
976 break;
977 }
978 }
979
980 if (i < 0) {
981 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
982 printf(WI_PRT_FMT
983 ": timeout in wi_cmd 0x%04x; event status 0x%04x\n",
984 WI_PRT_ARG(sc), cmd, s);
985 return(ETIMEDOUT);
986 }
987
988 return(0);
989 }
990
991 STATIC void
992 wi_reset(struct wi_softc *sc)
993 {
994 int error, tries = 3;
995
996 DPRINTF(WID_RESET, ("wi_reset: sc %p\n", sc));
997
998
999 if (sc->sc_firmware_type == WI_SYMBOL) {
1000 if (sc->wi_flags & WI_FLAGS_INITIALIZED)
1001 return;
1002 tries = 1;
1003 }
1004
1005 for (; tries--; DELAY(WI_DELAY * 1000)) {
1006 if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
1007 break;
1008 }
1009 if (tries < 0) {
1010 printf(WI_PRT_FMT ": init failed\n", WI_PRT_ARG(sc));
1011 return;
1012 }
1013 sc->wi_flags |= WI_FLAGS_INITIALIZED;
1014
1015 wi_intr_enable(sc, 0);
1016 wi_intr_ack(sc, 0xffff);
1017
1018
1019 WI_SETVAL(WI_RID_TICK_TIME, 8);
1020
1021 return;
1022 }
1023
1024 STATIC void
1025 wi_cor_reset(struct wi_softc *sc)
1026 {
1027 u_int8_t cor_value;
1028
1029 DPRINTF(WID_RESET, ("wi_cor_reset: sc %p\n", sc));
1030
1031
1032
1033
1034
1035
1036
1037 if (sc->sc_firmware_type != WI_LUCENT) {
1038 cor_value = bus_space_read_1(sc->wi_ltag, sc->wi_lhandle,
1039 sc->wi_cor_offset);
1040 bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
1041 sc->wi_cor_offset, (cor_value | WI_COR_SOFT_RESET));
1042 DELAY(1000);
1043 bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
1044 sc->wi_cor_offset, (cor_value & ~WI_COR_SOFT_RESET));
1045 DELAY(1000);
1046 }
1047
1048 return;
1049 }
1050
1051
1052
1053
1054 STATIC int
1055 wi_read_record_io(struct wi_softc *sc, struct wi_ltv_gen *ltv)
1056 {
1057 u_int8_t *ptr;
1058 int len, code;
1059 struct wi_ltv_gen *oltv, p2ltv;
1060
1061 if (sc->sc_firmware_type != WI_LUCENT) {
1062 oltv = ltv;
1063 switch (ltv->wi_type) {
1064 case WI_RID_ENCRYPTION:
1065 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1066 p2ltv.wi_len = 2;
1067 ltv = &p2ltv;
1068 break;
1069 case WI_RID_TX_CRYPT_KEY:
1070 if (ltv->wi_val > WI_NLTV_KEYS)
1071 return (EINVAL);
1072 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1073 p2ltv.wi_len = 2;
1074 ltv = &p2ltv;
1075 break;
1076 }
1077 }
1078
1079
1080 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
1081 return(EIO);
1082
1083
1084 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1085 return(EIO);
1086
1087
1088
1089
1090
1091
1092 len = CSR_READ_2(sc, WI_DATA1);
1093 if (len > ltv->wi_len)
1094 return(ENOSPC);
1095 code = CSR_READ_2(sc, WI_DATA1);
1096 if (code != ltv->wi_type)
1097 return(EIO);
1098
1099 ltv->wi_len = len;
1100 ltv->wi_type = code;
1101
1102
1103 ptr = (u_int8_t *)<v->wi_val;
1104 if (ltv->wi_len > 1)
1105 CSR_READ_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1)*2);
1106
1107 if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS
1108 && ltv->wi_val == sc->wi_ibss_port) {
1109
1110
1111
1112
1113
1114 ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
1115 } else if (sc->sc_firmware_type != WI_LUCENT) {
1116 int v;
1117
1118 switch (oltv->wi_type) {
1119 case WI_RID_TX_RATE:
1120 case WI_RID_CUR_TX_RATE:
1121 switch (letoh16(ltv->wi_val)) {
1122 case 1: v = 1; break;
1123 case 2: v = 2; break;
1124 case 3: v = 6; break;
1125 case 4: v = 5; break;
1126 case 7: v = 7; break;
1127 case 8: v = 11; break;
1128 case 15: v = 3; break;
1129 default: v = 0x100 + letoh16(ltv->wi_val); break;
1130 }
1131 oltv->wi_val = htole16(v);
1132 break;
1133 case WI_RID_ENCRYPTION:
1134 oltv->wi_len = 2;
1135 if (ltv->wi_val & htole16(0x01))
1136 oltv->wi_val = htole16(1);
1137 else
1138 oltv->wi_val = htole16(0);
1139 break;
1140 case WI_RID_TX_CRYPT_KEY:
1141 case WI_RID_CNFAUTHMODE:
1142 oltv->wi_len = 2;
1143 oltv->wi_val = ltv->wi_val;
1144 break;
1145 }
1146 }
1147
1148 return(0);
1149 }
1150
1151
1152
1153
1154 STATIC int
1155 wi_write_record_io(struct wi_softc *sc, struct wi_ltv_gen *ltv)
1156 {
1157 u_int8_t *ptr;
1158 u_int16_t val = 0;
1159 int i;
1160 struct wi_ltv_gen p2ltv;
1161
1162 if (ltv->wi_type == WI_RID_PORTTYPE &&
1163 letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) {
1164
1165 p2ltv.wi_type = WI_RID_PORTTYPE;
1166 p2ltv.wi_len = 2;
1167 p2ltv.wi_val = sc->wi_ibss_port;
1168 ltv = &p2ltv;
1169 } else if (sc->sc_firmware_type != WI_LUCENT) {
1170 int v;
1171
1172 switch (ltv->wi_type) {
1173 case WI_RID_TX_RATE:
1174 p2ltv.wi_type = WI_RID_TX_RATE;
1175 p2ltv.wi_len = 2;
1176 switch (letoh16(ltv->wi_val)) {
1177 case 1: v = 1; break;
1178 case 2: v = 2; break;
1179 case 3: v = 15; break;
1180 case 5: v = 4; break;
1181 case 6: v = 3; break;
1182 case 7: v = 7; break;
1183 case 11: v = 8; break;
1184 default: return EINVAL;
1185 }
1186 p2ltv.wi_val = htole16(v);
1187 ltv = &p2ltv;
1188 break;
1189 case WI_RID_ENCRYPTION:
1190 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1191 p2ltv.wi_len = 2;
1192 if (ltv->wi_val & htole16(0x01)) {
1193 val = PRIVACY_INVOKED;
1194
1195
1196
1197
1198
1199
1200
1201
1202 if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
1203 sc->sc_firmware_type == WI_SYMBOL)
1204 val |= EXCLUDE_UNENCRYPTED;
1205
1206 switch (sc->wi_crypto_algorithm) {
1207 case WI_CRYPTO_FIRMWARE_WEP:
1208
1209
1210
1211
1212 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
1213 val |= HOST_ENCRYPT;
1214 break;
1215 case WI_CRYPTO_SOFTWARE_WEP:
1216 val |= HOST_ENCRYPT|HOST_DECRYPT;
1217 break;
1218 }
1219 p2ltv.wi_val = htole16(val);
1220 } else
1221 p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT);
1222 ltv = &p2ltv;
1223 break;
1224 case WI_RID_TX_CRYPT_KEY:
1225 if (ltv->wi_val > WI_NLTV_KEYS)
1226 return (EINVAL);
1227 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1228 p2ltv.wi_len = 2;
1229 p2ltv.wi_val = ltv->wi_val;
1230 ltv = &p2ltv;
1231 break;
1232 case WI_RID_DEFLT_CRYPT_KEYS: {
1233 int error;
1234 int keylen;
1235 struct wi_ltv_str ws;
1236 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
1237
1238 keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1239 keylen = letoh16(keylen);
1240
1241 for (i = 0; i < 4; i++) {
1242 bzero(&ws, sizeof(ws));
1243 ws.wi_len = (keylen > 5) ? 8 : 4;
1244 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1245 bcopy(&wk->wi_keys[i].wi_keydat,
1246 ws.wi_str, keylen);
1247 error = wi_write_record(sc,
1248 (struct wi_ltv_gen *)&ws);
1249 if (error)
1250 return (error);
1251 }
1252 }
1253 return (0);
1254 }
1255 }
1256
1257 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1258 return(EIO);
1259
1260 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1261 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1262
1263 ptr = (u_int8_t *)<v->wi_val;
1264 if (ltv->wi_len > 1)
1265 CSR_WRITE_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1) *2);
1266
1267 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
1268 return(EIO);
1269
1270 return(0);
1271 }
1272
1273 STATIC int
1274 wi_seek(struct wi_softc *sc, int id, int off, int chan)
1275 {
1276 int i;
1277 int selreg, offreg;
1278
1279 switch (chan) {
1280 case WI_BAP0:
1281 selreg = WI_SEL0;
1282 offreg = WI_OFF0;
1283 break;
1284 case WI_BAP1:
1285 selreg = WI_SEL1;
1286 offreg = WI_OFF1;
1287 break;
1288 default:
1289 printf(WI_PRT_FMT ": invalid data path: %x\n", WI_PRT_ARG(sc),
1290 chan);
1291 return(EIO);
1292 }
1293
1294 CSR_WRITE_2(sc, selreg, id);
1295 CSR_WRITE_2(sc, offreg, off);
1296
1297 for (i = WI_TIMEOUT; i--; DELAY(1))
1298 if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
1299 break;
1300
1301 if (i < 0)
1302 return(ETIMEDOUT);
1303
1304 return(0);
1305 }
1306
1307 STATIC int
1308 wi_read_data_io(struct wi_softc *sc, int id, int off, caddr_t buf, int len)
1309 {
1310 u_int8_t *ptr;
1311
1312 if (wi_seek(sc, id, off, WI_BAP1))
1313 return(EIO);
1314
1315 ptr = (u_int8_t *)buf;
1316 CSR_READ_RAW_2(sc, WI_DATA1, ptr, len);
1317
1318 return(0);
1319 }
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333 STATIC int
1334 wi_write_data_io(struct wi_softc *sc, int id, int off, caddr_t buf, int len)
1335 {
1336 u_int8_t *ptr;
1337
1338 #ifdef WI_HERMES_AUTOINC_WAR
1339 again:
1340 #endif
1341
1342 if (wi_seek(sc, id, off, WI_BAP0))
1343 return(EIO);
1344
1345 ptr = (u_int8_t *)buf;
1346 CSR_WRITE_RAW_2(sc, WI_DATA0, ptr, len);
1347
1348 #ifdef WI_HERMES_AUTOINC_WAR
1349 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1350 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1351
1352 if (wi_seek(sc, id, off + len, WI_BAP0))
1353 return(EIO);
1354
1355 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1356 CSR_READ_2(sc, WI_DATA0) != 0x5678)
1357 goto again;
1358 #endif
1359
1360 return(0);
1361 }
1362
1363
1364
1365
1366
1367 STATIC int
1368 wi_alloc_nicmem_io(struct wi_softc *sc, int len, int *id)
1369 {
1370 int i;
1371
1372 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
1373 printf(WI_PRT_FMT ": failed to allocate %d bytes on NIC\n",
1374 WI_PRT_ARG(sc), len);
1375 return(ENOMEM);
1376 }
1377
1378 for (i = WI_TIMEOUT; i--; DELAY(1)) {
1379 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1380 break;
1381 }
1382
1383 if (i < 0)
1384 return(ETIMEDOUT);
1385
1386 *id = CSR_READ_2(sc, WI_ALLOC_FID);
1387 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1388
1389 if (wi_seek(sc, *id, 0, WI_BAP0))
1390 return(EIO);
1391
1392 for (i = 0; i < len / 2; i++)
1393 CSR_WRITE_2(sc, WI_DATA0, 0);
1394
1395 return(0);
1396 }
1397
1398 STATIC void
1399 wi_setmulti(struct wi_softc *sc)
1400 {
1401 struct ifnet *ifp;
1402 int i = 0;
1403 struct wi_ltv_mcast mcast;
1404 struct ether_multistep step;
1405 struct ether_multi *enm;
1406
1407 ifp = &sc->sc_ic.ic_if;
1408
1409 bzero((char *)&mcast, sizeof(mcast));
1410
1411 mcast.wi_type = WI_RID_MCAST_LIST;
1412 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
1413
1414 allmulti:
1415 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1416 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1417 return;
1418 }
1419
1420 ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ac, enm);
1421 while (enm != NULL) {
1422 if (i >= 16) {
1423 bzero((char *)&mcast, sizeof(mcast));
1424 break;
1425 }
1426
1427 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1428 ifp->if_flags |= IFF_ALLMULTI;
1429 goto allmulti;
1430 }
1431 bcopy(enm->enm_addrlo, (char *)&mcast.wi_mcast[i],
1432 ETHER_ADDR_LEN);
1433 i++;
1434 ETHER_NEXT_MULTI(step, enm);
1435 }
1436
1437 mcast.wi_len = (i * 3) + 1;
1438 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1439
1440 return;
1441 }
1442
1443 STATIC int
1444 wi_setdef(struct wi_softc *sc, struct wi_req *wreq)
1445 {
1446 struct ifnet *ifp;
1447 int error = 0;
1448
1449 ifp = &sc->sc_ic.ic_if;
1450
1451 switch(wreq->wi_type) {
1452 case WI_RID_MAC_NODE:
1453 bcopy((char *)&wreq->wi_val, LLADDR(ifp->if_sadl),
1454 ETHER_ADDR_LEN);
1455 bcopy((char *)&wreq->wi_val, (char *)&sc->sc_ic.ic_myaddr,
1456 ETHER_ADDR_LEN);
1457 break;
1458 case WI_RID_PORTTYPE:
1459 error = wi_sync_media(sc, letoh16(wreq->wi_val[0]),
1460 sc->wi_tx_rate);
1461 break;
1462 case WI_RID_TX_RATE:
1463 error = wi_sync_media(sc, sc->wi_ptype,
1464 letoh16(wreq->wi_val[0]));
1465 break;
1466 case WI_RID_MAX_DATALEN:
1467 sc->wi_max_data_len = letoh16(wreq->wi_val[0]);
1468 break;
1469 case WI_RID_RTS_THRESH:
1470 sc->wi_rts_thresh = letoh16(wreq->wi_val[0]);
1471 break;
1472 case WI_RID_SYSTEM_SCALE:
1473 sc->wi_ap_density = letoh16(wreq->wi_val[0]);
1474 break;
1475 case WI_RID_CREATE_IBSS:
1476 sc->wi_create_ibss = letoh16(wreq->wi_val[0]);
1477 error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
1478 break;
1479 case WI_RID_OWN_CHNL:
1480 sc->wi_channel = letoh16(wreq->wi_val[0]);
1481 break;
1482 case WI_RID_NODENAME:
1483 error = wi_set_ssid(&sc->wi_node_name,
1484 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1485 break;
1486 case WI_RID_DESIRED_SSID:
1487 error = wi_set_ssid(&sc->wi_net_name,
1488 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1489 break;
1490 case WI_RID_OWN_SSID:
1491 error = wi_set_ssid(&sc->wi_ibss_name,
1492 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1493 break;
1494 case WI_RID_PM_ENABLED:
1495 sc->wi_pm_enabled = letoh16(wreq->wi_val[0]);
1496 break;
1497 case WI_RID_MICROWAVE_OVEN:
1498 sc->wi_mor_enabled = letoh16(wreq->wi_val[0]);
1499 break;
1500 case WI_RID_MAX_SLEEP:
1501 sc->wi_max_sleep = letoh16(wreq->wi_val[0]);
1502 break;
1503 case WI_RID_CNFAUTHMODE:
1504 sc->wi_authtype = letoh16(wreq->wi_val[0]);
1505 break;
1506 case WI_RID_ROAMING_MODE:
1507 sc->wi_roaming = letoh16(wreq->wi_val[0]);
1508 break;
1509 case WI_RID_SYMBOL_DIVERSITY:
1510 sc->wi_diversity = letoh16(wreq->wi_val[0]);
1511 break;
1512 case WI_RID_ENH_SECURITY:
1513 sc->wi_enh_security = letoh16(wreq->wi_val[0]);
1514 break;
1515 case WI_RID_ENCRYPTION:
1516 sc->wi_use_wep = letoh16(wreq->wi_val[0]);
1517 break;
1518 case WI_RID_TX_CRYPT_KEY:
1519 sc->wi_tx_key = letoh16(wreq->wi_val[0]);
1520 break;
1521 case WI_RID_DEFLT_CRYPT_KEYS:
1522 bcopy((char *)wreq, (char *)&sc->wi_keys,
1523 sizeof(struct wi_ltv_keys));
1524 break;
1525 case WI_FRID_CRYPTO_ALG:
1526 switch (letoh16(wreq->wi_val[0])) {
1527 case WI_CRYPTO_FIRMWARE_WEP:
1528 sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
1529 break;
1530 case WI_CRYPTO_SOFTWARE_WEP:
1531 sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP;
1532 break;
1533 default:
1534 printf(WI_PRT_FMT ": unsupported crypto algorithm %d\n",
1535 WI_PRT_ARG(sc), letoh16(wreq->wi_val[0]));
1536 error = EINVAL;
1537 }
1538 break;
1539 default:
1540 error = EINVAL;
1541 break;
1542 }
1543
1544 return (error);
1545 }
1546
1547 STATIC int
1548 wi_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1549 {
1550 int s, error = 0, i, j, len;
1551 struct wi_softc *sc;
1552 struct ifreq *ifr;
1553 struct proc *p = curproc;
1554 struct ifaddr *ifa = (struct ifaddr *)data;
1555 struct wi_scan_res *res;
1556 struct wi_scan_p2_hdr *p2;
1557 struct wi_req *wreq = NULL;
1558 u_int32_t flags;
1559
1560 struct ieee80211_nwid *nwidp = NULL;
1561 struct ieee80211_nodereq_all *na;
1562 struct ieee80211_bssid *bssid;
1563
1564 s = splnet();
1565
1566 sc = ifp->if_softc;
1567 ifr = (struct ifreq *)data;
1568
1569 if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) {
1570 splx(s);
1571 return(ENODEV);
1572 }
1573
1574 DPRINTF (WID_IOCTL, ("wi_ioctl: command %lu data %p\n",
1575 command, data));
1576
1577 if ((error = ether_ioctl(ifp, &sc->sc_ic.ic_ac, command, data)) > 0) {
1578 splx(s);
1579 return error;
1580 }
1581
1582 switch(command) {
1583 case SIOCSIFADDR:
1584 ifp->if_flags |= IFF_UP;
1585 switch (ifa->ifa_addr->sa_family) {
1586 #ifdef INET
1587 case AF_INET:
1588 wi_init(sc);
1589 arp_ifinit(&sc->sc_ic.ic_ac, ifa);
1590 break;
1591 #endif
1592 default:
1593 wi_init(sc);
1594 break;
1595 }
1596 break;
1597
1598 case SIOCSIFMTU:
1599 if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
1600 error = EINVAL;
1601 } else if (ifp->if_mtu != ifr->ifr_mtu) {
1602 ifp->if_mtu = ifr->ifr_mtu;
1603 }
1604 break;
1605
1606 case SIOCSIFFLAGS:
1607 if (ifp->if_flags & IFF_UP) {
1608 if (ifp->if_flags & IFF_RUNNING &&
1609 ifp->if_flags & IFF_PROMISC &&
1610 !(sc->wi_if_flags & IFF_PROMISC)) {
1611 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1612 WI_SETVAL(WI_RID_PROMISC, 1);
1613 } else if (ifp->if_flags & IFF_RUNNING &&
1614 !(ifp->if_flags & IFF_PROMISC) &&
1615 sc->wi_if_flags & IFF_PROMISC) {
1616 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1617 WI_SETVAL(WI_RID_PROMISC, 0);
1618 } else
1619 wi_init(sc);
1620 } else if (ifp->if_flags & IFF_RUNNING)
1621 wi_stop(sc);
1622 sc->wi_if_flags = ifp->if_flags;
1623 error = 0;
1624 break;
1625 case SIOCADDMULTI:
1626 case SIOCDELMULTI:
1627
1628 error = (command == SIOCADDMULTI) ?
1629 ether_addmulti(ifr, &sc->sc_ic.ic_ac) :
1630 ether_delmulti(ifr, &sc->sc_ic.ic_ac);
1631
1632 if (error == ENETRESET) {
1633
1634
1635
1636
1637 if (ifp->if_flags & IFF_RUNNING)
1638 wi_setmulti(sc);
1639 error = 0;
1640 }
1641 break;
1642 case SIOCSIFMEDIA:
1643 case SIOCGIFMEDIA:
1644 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1645 break;
1646 case SIOCGWAVELAN:
1647 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1648 bzero(wreq, sizeof(*wreq));
1649 error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1650 if (error)
1651 break;
1652 if (wreq->wi_len > WI_MAX_DATALEN) {
1653 error = EINVAL;
1654 break;
1655 }
1656 switch (wreq->wi_type) {
1657 case WI_RID_IFACE_STATS:
1658
1659 bcopy((char *)&sc->wi_stats, (char *)&wreq->wi_val,
1660 sizeof(sc->wi_stats));
1661 wreq->wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1662 break;
1663 case WI_RID_DEFLT_CRYPT_KEYS:
1664
1665 if (suser(p, 0))
1666 bzero(wreq, sizeof(struct wi_ltv_keys));
1667 else
1668 bcopy((char *)&sc->wi_keys, wreq,
1669 sizeof(struct wi_ltv_keys));
1670 break;
1671 case WI_RID_PROCFRAME:
1672 wreq->wi_len = 2;
1673 wreq->wi_val[0] = htole16(sc->wi_procframe);
1674 break;
1675 case WI_RID_PRISM2:
1676 wreq->wi_len = 2;
1677 wreq->wi_val[0] = htole16(sc->sc_firmware_type ==
1678 WI_LUCENT ? 0 : 1);
1679 break;
1680 case WI_FRID_CRYPTO_ALG:
1681 wreq->wi_val[0] =
1682 htole16((u_int16_t)sc->wi_crypto_algorithm);
1683 wreq->wi_len = 1;
1684 break;
1685 case WI_RID_SCAN_RES:
1686 if (sc->sc_firmware_type == WI_LUCENT) {
1687 memcpy((char *)wreq->wi_val,
1688 (char *)sc->wi_scanbuf,
1689 sc->wi_scanbuf_len * 2);
1690 wreq->wi_len = sc->wi_scanbuf_len;
1691 break;
1692 }
1693
1694 default:
1695 if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1696 error = EINVAL;
1697 }
1698 break;
1699 }
1700 error = copyout(wreq, ifr->ifr_data, sizeof(*wreq));
1701 break;
1702 case SIOCSWAVELAN:
1703 if ((error = suser(curproc, 0)) != 0)
1704 break;
1705 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1706 bzero(wreq, sizeof(*wreq));
1707 error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1708 if (error)
1709 break;
1710 error = EINVAL;
1711 if (wreq->wi_len > WI_MAX_DATALEN)
1712 break;
1713 switch (wreq->wi_type) {
1714 case WI_RID_IFACE_STATS:
1715 break;
1716 case WI_RID_MGMT_XMIT:
1717 error = wi_mgmt_xmit(sc, (caddr_t)&wreq->wi_val,
1718 wreq->wi_len);
1719 break;
1720 case WI_RID_PROCFRAME:
1721 sc->wi_procframe = letoh16(wreq->wi_val[0]);
1722 error = 0;
1723 break;
1724 case WI_RID_SCAN_REQ:
1725 error = 0;
1726 if (sc->sc_firmware_type == WI_LUCENT)
1727 wi_cmd(sc, WI_CMD_INQUIRE,
1728 WI_INFO_SCAN_RESULTS, 0, 0);
1729 else
1730 error = wi_write_record(sc,
1731 (struct wi_ltv_gen *)wreq);
1732 break;
1733 case WI_FRID_CRYPTO_ALG:
1734 if (sc->sc_firmware_type != WI_LUCENT) {
1735 error = wi_setdef(sc, wreq);
1736 if (!error && (ifp->if_flags & IFF_UP))
1737 wi_init(sc);
1738 }
1739 break;
1740 case WI_RID_SYMBOL_DIVERSITY:
1741 case WI_RID_ROAMING_MODE:
1742 case WI_RID_CREATE_IBSS:
1743 case WI_RID_MICROWAVE_OVEN:
1744 case WI_RID_OWN_SSID:
1745 case WI_RID_ENH_SECURITY:
1746
1747
1748
1749
1750 if ((wreq->wi_type == WI_RID_SYMBOL_DIVERSITY &&
1751 !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)) ||
1752 (wreq->wi_type == WI_RID_ROAMING_MODE &&
1753 !(sc->wi_flags & WI_FLAGS_HAS_ROAMING)) ||
1754 (wreq->wi_type == WI_RID_CREATE_IBSS &&
1755 !(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) ||
1756 (wreq->wi_type == WI_RID_MICROWAVE_OVEN &&
1757 !(sc->wi_flags & WI_FLAGS_HAS_MOR)) ||
1758 (wreq->wi_type == WI_RID_ENH_SECURITY &&
1759 !(sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)) ||
1760 (wreq->wi_type == WI_RID_OWN_SSID &&
1761 wreq->wi_len != 0))
1762 break;
1763
1764 default:
1765 error = wi_write_record(sc, (struct wi_ltv_gen *)wreq);
1766 if (!error)
1767 error = wi_setdef(sc, wreq);
1768 if (!error && (ifp->if_flags & IFF_UP))
1769 wi_init(sc);
1770 }
1771 break;
1772 case SIOCGPRISM2DEBUG:
1773 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1774 bzero(wreq, sizeof(*wreq));
1775 error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1776 if (error)
1777 break;
1778 if (!(ifp->if_flags & IFF_RUNNING) ||
1779 sc->sc_firmware_type == WI_LUCENT) {
1780 error = EIO;
1781 break;
1782 }
1783 error = wi_get_debug(sc, wreq);
1784 if (error == 0)
1785 error = copyout(wreq, ifr->ifr_data, sizeof(*wreq));
1786 break;
1787 case SIOCSPRISM2DEBUG:
1788 if ((error = suser(curproc, 0)) != 0)
1789 break;
1790 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1791 bzero(wreq, sizeof(*wreq));
1792 error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1793 if (error)
1794 break;
1795 error = wi_set_debug(sc, wreq);
1796 break;
1797 case SIOCG80211NWID:
1798 if ((ifp->if_flags & IFF_UP) && sc->wi_net_name.i_len > 0) {
1799
1800 error = copyout(&sc->wi_net_name, ifr->ifr_data,
1801 sizeof(sc->wi_net_name));
1802 } else {
1803 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1804 bzero(wreq, sizeof(*wreq));
1805 wreq->wi_type = WI_RID_CURRENT_SSID;
1806 wreq->wi_len = WI_MAX_DATALEN;
1807 if (wi_read_record(sc, (struct wi_ltv_gen *)wreq) ||
1808 letoh16(wreq->wi_val[0]) > IEEE80211_NWID_LEN)
1809 error = EINVAL;
1810 else {
1811 nwidp = malloc(sizeof *nwidp, M_DEVBUF, M_WAITOK);
1812 bzero(nwidp, sizeof(*nwidp));
1813 wi_set_ssid(nwidp, (u_int8_t *)&wreq->wi_val[1],
1814 letoh16(wreq->wi_val[0]));
1815 error = copyout(nwidp, ifr->ifr_data,
1816 sizeof(*nwidp));
1817 }
1818 }
1819 break;
1820 case SIOCS80211NWID:
1821 if ((error = suser(curproc, 0)) != 0)
1822 break;
1823 nwidp = malloc(sizeof *nwidp, M_DEVBUF, M_WAITOK);
1824 error = copyin(ifr->ifr_data, nwidp, sizeof(*nwidp));
1825 if (error)
1826 break;
1827 if (nwidp->i_len > IEEE80211_NWID_LEN) {
1828 error = EINVAL;
1829 break;
1830 }
1831 if (sc->wi_net_name.i_len == nwidp->i_len &&
1832 memcmp(sc->wi_net_name.i_nwid, nwidp->i_nwid, nwidp->i_len) == 0)
1833 break;
1834 wi_set_ssid(&sc->wi_net_name, nwidp->i_nwid, nwidp->i_len);
1835 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1836 if (ifp->if_flags & IFF_UP)
1837
1838 wi_init(sc);
1839 break;
1840 case SIOCS80211NWKEY:
1841 if ((error = suser(curproc, 0)) != 0)
1842 break;
1843 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1844 break;
1845 case SIOCG80211NWKEY:
1846 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1847 break;
1848 case SIOCS80211POWER:
1849 if ((error = suser(curproc, 0)) != 0)
1850 break;
1851 error = wi_set_pm(sc, (struct ieee80211_power *)data);
1852 break;
1853 case SIOCG80211POWER:
1854 error = wi_get_pm(sc, (struct ieee80211_power *)data);
1855 break;
1856 case SIOCS80211TXPOWER:
1857 if ((error = suser(curproc, 0)) != 0)
1858 break;
1859 error = wi_set_txpower(sc, (struct ieee80211_txpower *)data);
1860 break;
1861 case SIOCG80211TXPOWER:
1862 error = wi_get_txpower(sc, (struct ieee80211_txpower *)data);
1863 break;
1864 case SIOCS80211CHANNEL:
1865 if ((error = suser(curproc, 0)) != 0)
1866 break;
1867 if (((struct ieee80211chanreq *)data)->i_channel > 14) {
1868 error = EINVAL;
1869 break;
1870 }
1871 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1872 bzero(wreq, sizeof(*wreq));
1873 wreq->wi_type = WI_RID_OWN_CHNL;
1874 wreq->wi_val[0] =
1875 htole16(((struct ieee80211chanreq *)data)->i_channel);
1876 error = wi_setdef(sc, wreq);
1877 if (!error && (ifp->if_flags & IFF_UP))
1878 wi_init(sc);
1879 break;
1880 case SIOCG80211CHANNEL:
1881 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1882 bzero(wreq, sizeof(*wreq));
1883 wreq->wi_type = WI_RID_CURRENT_CHAN;
1884 wreq->wi_len = WI_MAX_DATALEN;
1885 if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1886 error = EINVAL;
1887 break;
1888 }
1889 ((struct ieee80211chanreq *)data)->i_channel =
1890 letoh16(wreq->wi_val[0]);
1891 break;
1892 case SIOCG80211BSSID:
1893 bssid = (struct ieee80211_bssid *)data;
1894 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1895 bzero(wreq, sizeof(*wreq));
1896 wreq->wi_type = WI_RID_CURRENT_BSSID;
1897 wreq->wi_len = WI_MAX_DATALEN;
1898 if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1899 error = EINVAL;
1900 break;
1901 }
1902 IEEE80211_ADDR_COPY(bssid->i_bssid, wreq->wi_val);
1903 break;
1904 case SIOCS80211SCAN:
1905 if ((error = suser(curproc, 0)) != 0)
1906 break;
1907 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
1908 break;
1909 if ((ifp->if_flags & IFF_UP) == 0) {
1910 error = ENETDOWN;
1911 break;
1912 }
1913 if (sc->sc_firmware_type == WI_LUCENT) {
1914 wi_cmd(sc, WI_CMD_INQUIRE,
1915 WI_INFO_SCAN_RESULTS, 0, 0);
1916 } else {
1917 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1918 bzero(wreq, sizeof(*wreq));
1919 wreq->wi_len = 3;
1920 wreq->wi_type = WI_RID_SCAN_REQ;
1921 wreq->wi_val[0] = 0x3FFF;
1922 wreq->wi_val[1] = 0x000F;
1923
1924 error = wi_write_record(sc,
1925 (struct wi_ltv_gen *)wreq);
1926 if (error)
1927 break;
1928 }
1929 sc->wi_scan_lock = 0;
1930 timeout_set(&sc->wi_scan_timeout, wi_scan_timeout, sc);
1931 len = WI_WAVELAN_RES_TIMEOUT;
1932 if (sc->wi_flags & WI_FLAGS_BUS_USB) {
1933
1934 len = WI_WAVELAN_RES_TIMEOUT * 4;
1935 }
1936 timeout_add(&sc->wi_scan_timeout, len);
1937
1938
1939 error = tsleep(&sc->wi_scan_lock, PCATCH, "wiscan",
1940 hz * IEEE80211_SCAN_TIMEOUT);
1941 break;
1942 case SIOCG80211ALLNODES:
1943 {
1944 struct ieee80211_nodereq *nr = NULL;
1945
1946 if ((error = suser(curproc, 0)) != 0)
1947 break;
1948 na = (struct ieee80211_nodereq_all *)data;
1949 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
1950
1951 error = wihap_ioctl(sc, command, data);
1952 break;
1953 }
1954 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
1955 bzero(wreq, sizeof(*wreq));
1956 wreq->wi_len = WI_MAX_DATALEN;
1957 wreq->wi_type = WI_RID_SCAN_RES;
1958 if (sc->sc_firmware_type == WI_LUCENT) {
1959 bcopy(sc->wi_scanbuf, wreq->wi_val,
1960 sc->wi_scanbuf_len * 2);
1961 wreq->wi_len = sc->wi_scanbuf_len;
1962 i = 0;
1963 len = WI_WAVELAN_RES_SIZE;
1964 } else {
1965 if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1966 error = EINVAL;
1967 break;
1968 }
1969 p2 = (struct wi_scan_p2_hdr *)wreq->wi_val;
1970 if (p2->wi_reason == 0)
1971 break;
1972 i = sizeof(*p2);
1973 len = WI_PRISM2_RES_SIZE;
1974 }
1975
1976 for (na->na_nodes = j = 0; (i < (wreq->wi_len * 2) - len) &&
1977 (na->na_size >= j + sizeof(struct ieee80211_nodereq));
1978 i += len) {
1979
1980 if (nr == NULL)
1981 nr = malloc(sizeof *nr, M_DEVBUF, M_WAITOK);
1982 res = (struct wi_scan_res *)((char *)wreq->wi_val + i);
1983 if (res == NULL)
1984 break;
1985
1986 bzero(nr, sizeof(*nr));
1987 IEEE80211_ADDR_COPY(nr->nr_macaddr, res->wi_bssid);
1988 IEEE80211_ADDR_COPY(nr->nr_bssid, res->wi_bssid);
1989 nr->nr_channel = letoh16(res->wi_chan);
1990 nr->nr_chan_flags = IEEE80211_CHAN_B;
1991 nr->nr_rssi = letoh16(res->wi_signal);
1992 nr->nr_max_rssi = 0;
1993 nr->nr_nwid_len = letoh16(res->wi_ssid_len);
1994 bcopy(res->wi_ssid, nr->nr_nwid, nr->nr_nwid_len);
1995 nr->nr_intval = letoh16(res->wi_interval);
1996 nr->nr_capinfo = letoh16(res->wi_capinfo);
1997 nr->nr_txrate = res->wi_rate == WI_WAVELAN_RES_1M ? 2 :
1998 (res->wi_rate == WI_WAVELAN_RES_2M ? 4 :
1999 (res->wi_rate == WI_WAVELAN_RES_5M ? 11 :
2000 (res->wi_rate == WI_WAVELAN_RES_11M ? 22 : 0)));
2001 nr->nr_nrates = 0;
2002 while (res->wi_srates[nr->nr_nrates] != 0) {
2003 nr->nr_rates[nr->nr_nrates] =
2004 res->wi_srates[nr->nr_nrates] &
2005 WI_VAR_SRATES_MASK;
2006 nr->nr_nrates++;
2007 }
2008 nr->nr_flags = 0;
2009 if (bcmp(nr->nr_macaddr, nr->nr_bssid,
2010 IEEE80211_ADDR_LEN) == 0)
2011 nr->nr_flags |= IEEE80211_NODEREQ_AP;
2012
2013 error = copyout(nr, (caddr_t)na->na_node + j,
2014 sizeof(struct ieee80211_nodereq));
2015 if (error)
2016 break;
2017 j += sizeof(struct ieee80211_nodereq);
2018 na->na_nodes++;
2019 }
2020 if (nr)
2021 free(nr, M_DEVBUF);
2022 break;
2023 }
2024 case SIOCG80211FLAGS:
2025 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
2026 break;
2027 ifr->ifr_flags = 0;
2028 if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
2029 wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
2030 bzero(wreq, sizeof(*wreq));
2031 wreq->wi_len = WI_MAX_DATALEN;
2032 wreq->wi_type = WI_RID_ENH_SECURITY;
2033 if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
2034 error = EINVAL;
2035 break;
2036 }
2037 sc->wi_enh_security = letoh16(wreq->wi_val[0]);
2038 if (sc->wi_enh_security == WI_HIDESSID_IGNPROBES)
2039 ifr->ifr_flags |= IEEE80211_F_HIDENWID >>
2040 IEEE80211_F_USERSHIFT;
2041 }
2042 break;
2043 case SIOCS80211FLAGS:
2044 if ((error = suser(curproc, 0)) != 0)
2045 break;
2046 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP) {
2047 error = EINVAL;
2048 break;
2049 }
2050 flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
2051 if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
2052 sc->wi_enh_security = (flags & IEEE80211_F_HIDENWID) ?
2053 WI_HIDESSID_IGNPROBES : 0;
2054 WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security);
2055 }
2056 break;
2057 case SIOCHOSTAP_ADD:
2058 case SIOCHOSTAP_DEL:
2059 case SIOCHOSTAP_GET:
2060 case SIOCHOSTAP_GETALL:
2061 case SIOCHOSTAP_GFLAGS:
2062 case SIOCHOSTAP_SFLAGS:
2063
2064 error = wihap_ioctl(sc, command, data);
2065 break;
2066 default:
2067 error = EINVAL;
2068 break;
2069 }
2070
2071 if (wreq)
2072 free(wreq, M_DEVBUF);
2073 if (nwidp)
2074 free(nwidp, M_DEVBUF);
2075 splx(s);
2076 return(error);
2077 }
2078
2079 void
2080 wi_scan_timeout(void *arg)
2081 {
2082 struct wi_softc *sc = (struct wi_softc *)arg;
2083 struct wi_req wreq;
2084
2085 if (sc->wi_scan_lock++ < WI_WAVELAN_RES_TRIES &&
2086 sc->sc_firmware_type != WI_LUCENT &&
2087 (sc->wi_flags & WI_FLAGS_BUS_USB) == 0) {
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098 wreq.wi_len = WI_MAX_DATALEN;
2099 wreq.wi_type = WI_RID_SCAN_RES;
2100
2101 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2102 ((struct wi_scan_p2_hdr *)wreq.wi_val)->wi_reason == 0) {
2103
2104 timeout_add(&sc->wi_scan_timeout, WI_WAVELAN_RES_TIMEOUT);
2105 return;
2106 }
2107 }
2108
2109 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
2110 printf(WI_PRT_FMT ": wi_scan_timeout: %d tries\n",
2111 WI_PRT_ARG(sc), sc->wi_scan_lock);
2112
2113
2114 wakeup(&sc->wi_scan_lock);
2115 sc->wi_scan_lock = 0;
2116 }
2117
2118 STATIC void
2119 wi_init_io(struct wi_softc *sc)
2120 {
2121 struct ifnet *ifp = &sc->sc_ic.ic_ac.ac_if;
2122 int s;
2123 struct wi_ltv_macaddr mac;
2124 int id = 0;
2125
2126 if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2127 return;
2128
2129 DPRINTF(WID_INIT, ("wi_init: sc %p\n", sc));
2130
2131 s = splnet();
2132
2133 if (ifp->if_flags & IFF_RUNNING)
2134 wi_stop(sc);
2135
2136 wi_reset(sc);
2137
2138
2139 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
2140
2141
2142 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
2143
2144
2145 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
2146
2147
2148 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
2149
2150
2151 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
2152
2153
2154 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
2155
2156
2157 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
2158
2159
2160 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
2161
2162
2163 if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)
2164 WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security);
2165
2166
2167 if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
2168 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
2169
2170
2171 if (sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)
2172 WI_SETVAL(WI_RID_SYMBOL_DIVERSITY, sc->wi_diversity);
2173
2174
2175 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
2176
2177
2178 if (sc->wi_net_name.i_len != 0 && (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
2179 (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
2180 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_net_name);
2181 else
2182 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
2183
2184
2185 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
2186
2187
2188 WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
2189
2190
2191 mac.wi_len = 4;
2192 mac.wi_type = WI_RID_MAC_NODE;
2193 bcopy(LLADDR(ifp->if_sadl),
2194 (char *)&sc->sc_ic.ic_myaddr, ETHER_ADDR_LEN);
2195 bcopy((char *)&sc->sc_ic.ic_myaddr,
2196 (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
2197 wi_write_record(sc, (struct wi_ltv_gen *)&mac);
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP && ifp->if_flags & IFF_PROMISC)
2208 WI_SETVAL(WI_RID_PROMISC, 1);
2209 else
2210 WI_SETVAL(WI_RID_PROMISC, 0);
2211
2212
2213 if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
2214 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
2215 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
2216 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
2217 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2218 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
2219 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
2220
2221
2222
2223
2224
2225
2226
2227
2228 if (sc->sc_firmware_type == WI_INTERSIL &&
2229 sc->sc_sta_firmware_ver < 802 ) {
2230
2231 WI_SETVAL(WI_RID_PROMISC, 1);
2232 }
2233 WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
2234 }
2235 }
2236
2237
2238 wi_setmulti(sc);
2239
2240
2241 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
2242
2243 if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2244 printf(WI_PRT_FMT ": tx buffer allocation failed\n",
2245 WI_PRT_ARG(sc));
2246 sc->wi_tx_data_id = id;
2247
2248 if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2249 printf(WI_PRT_FMT ": mgmt. buffer allocation failed\n",
2250 WI_PRT_ARG(sc));
2251 sc->wi_tx_mgmt_id = id;
2252
2253
2254 if (sc->wi_flags & WI_FLAGS_TXPOWER)
2255 wi_set_txpower(sc, NULL);
2256
2257
2258 wi_intr_enable(sc, WI_INTRS);
2259
2260 wihap_init(sc);
2261
2262 splx(s);
2263
2264 ifp->if_flags |= IFF_RUNNING;
2265 ifp->if_flags &= ~IFF_OACTIVE;
2266
2267 timeout_add(&sc->sc_timo, hz * 60);
2268
2269 return;
2270 }
2271
2272 static const u_int32_t crc32tab[] = {
2273 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
2274 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
2275 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
2276 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
2277 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2278 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
2279 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
2280 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
2281 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
2282 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2283 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
2284 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
2285 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
2286 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
2287 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2288 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
2289 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
2290 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
2291 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
2292 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2293 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
2294 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
2295 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
2296 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
2297 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2298 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
2299 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
2300 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
2301 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
2302 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2303 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
2304 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
2305 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
2306 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
2307 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2308 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
2309 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
2310 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
2311 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
2312 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2313 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
2314 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
2315 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
2316 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
2317 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2318 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
2319 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
2320 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
2321 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
2322 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2323 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
2324 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
2325 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
2326 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
2327 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2328 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
2329 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
2330 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
2331 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
2332 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2333 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
2334 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
2335 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
2336 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
2337 };
2338
2339 STATIC void
2340 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2341 {
2342 u_int32_t i, crc, klen;
2343 u_int8_t key[RC4KEYLEN];
2344 u_int8_t *dat;
2345 struct rc4_ctx ctx;
2346
2347 if (!sc->wi_icv_flag) {
2348 sc->wi_icv = arc4random();
2349 sc->wi_icv_flag++;
2350 } else
2351 sc->wi_icv++;
2352
2353
2354
2355
2356 if (sc->wi_icv >= 0x03ff00 &&
2357 (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2358 sc->wi_icv += 0x000100;
2359
2360
2361 bzero(key, sizeof(key));
2362 key[0] = sc->wi_icv >> 16;
2363 key[1] = sc->wi_icv >> 8;
2364 key[2] = sc->wi_icv;
2365
2366 klen = letoh16(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen);
2367 bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2368 (char *)key + IEEE80211_WEP_IVLEN, klen);
2369 klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2370
2371
2372 rc4_keysetup(&ctx, key, klen);
2373
2374
2375 dat = buf;
2376 dat[0] = key[0];
2377 dat[1] = key[1];
2378 dat[2] = key[2];
2379 dat[3] = sc->wi_tx_key << 6;
2380 dat += 4;
2381
2382
2383 crc = ~0;
2384 for (i = 0; i < len; i++)
2385 crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2386 crc = ~crc;
2387 rc4_crypt(&ctx, dat, dat, len);
2388 dat += len;
2389
2390
2391 dat[0] = crc;
2392 dat[1] = crc >> 8;
2393 dat[2] = crc >> 16;
2394 dat[3] = crc >> 24;
2395 rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2396 }
2397
2398 STATIC int
2399 wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len)
2400 {
2401 u_int32_t i, crc, klen, kid;
2402 u_int8_t key[RC4KEYLEN];
2403 u_int8_t *dat;
2404 struct rc4_ctx ctx;
2405
2406 if (len < IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2407 IEEE80211_WEP_CRCLEN)
2408 return -1;
2409 len -= (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2410 IEEE80211_WEP_CRCLEN);
2411
2412 dat = buf;
2413
2414 bzero(key, sizeof(key));
2415 key[0] = dat[0];
2416 key[1] = dat[1];
2417 key[2] = dat[2];
2418 kid = (dat[3] >> 6) % 4;
2419 dat += 4;
2420
2421 klen = letoh16(sc->wi_keys.wi_keys[kid].wi_keylen);
2422 bcopy((char *)&sc->wi_keys.wi_keys[kid].wi_keydat,
2423 (char *)key + IEEE80211_WEP_IVLEN, klen);
2424 klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2425
2426
2427 rc4_keysetup(&ctx, key, klen);
2428
2429
2430 rc4_crypt(&ctx, dat, dat, len);
2431 crc = ~0;
2432 for (i = 0; i < len; i++)
2433 crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2434 crc = ~crc;
2435 dat += len;
2436
2437
2438 rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2439
2440 if ((dat[0] != crc) && (dat[1] != crc >> 8) &&
2441 (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) {
2442 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
2443 printf(WI_PRT_FMT ": wi_do_hostdecrypt: iv mismatch: "
2444 "0x%02x%02x%02x%02x vs. 0x%x\n", WI_PRT_ARG(sc),
2445 dat[3], dat[2], dat[1], dat[0], crc);
2446 return -1;
2447 }
2448
2449 return 0;
2450 }
2451
2452 void
2453 wi_start(struct ifnet *ifp)
2454 {
2455 struct wi_softc *sc;
2456 struct mbuf *m0;
2457 struct wi_frame tx_frame;
2458 struct ether_header *eh;
2459 int id, hostencrypt = 0;
2460
2461 sc = ifp->if_softc;
2462
2463 DPRINTF(WID_START, ("wi_start: ifp %p sc %p\n", ifp, sc));
2464
2465 if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2466 return;
2467
2468 if (ifp->if_flags & IFF_OACTIVE)
2469 return;
2470
2471 nextpkt:
2472 IFQ_DEQUEUE(&ifp->if_snd, m0);
2473 if (m0 == NULL)
2474 return;
2475
2476 bzero((char *)&tx_frame, sizeof(tx_frame));
2477 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA | WI_STYPE_DATA);
2478 id = sc->wi_tx_data_id;
2479 eh = mtod(m0, struct ether_header *);
2480
2481 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2482 if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
2483 &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC)) {
2484 if (ifp->if_flags & IFF_DEBUG)
2485 printf(WI_PRT_FMT
2486 ": wi_start: dropping unassoc dst %s\n",
2487 WI_PRT_ARG(sc),
2488 ether_sprintf(eh->ether_dhost));
2489 m_freem(m0);
2490 goto nextpkt;
2491 }
2492 }
2493
2494
2495
2496
2497
2498 if (eh->ether_type == htons(ETHERTYPE_IP) ||
2499 eh->ether_type == htons(ETHERTYPE_ARP) ||
2500 eh->ether_type == htons(ETHERTYPE_REVARP) ||
2501 eh->ether_type == htons(ETHERTYPE_IPV6)) {
2502 bcopy((char *)&eh->ether_dhost,
2503 (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
2504 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2505 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
2506 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
2507 bcopy((char *)&sc->sc_ic.ic_myaddr,
2508 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2509 bcopy((char *)&eh->ether_shost,
2510 (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
2511 if (sc->wi_use_wep)
2512 hostencrypt = 1;
2513 } else if (sc->wi_ptype == WI_PORTTYPE_BSS && sc->wi_use_wep &&
2514 sc->wi_crypto_algorithm != WI_CRYPTO_FIRMWARE_WEP) {
2515 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
2516 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_TODS);
2517 bcopy((char *)&sc->sc_ic.ic_myaddr,
2518 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2519 bcopy((char *)&eh->ether_dhost,
2520 (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
2521 hostencrypt = 1;
2522 } else
2523 bcopy((char *)&eh->ether_shost,
2524 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2525 bcopy((char *)&eh->ether_dhost,
2526 (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
2527 bcopy((char *)&eh->ether_shost,
2528 (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
2529
2530 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
2531 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
2532 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
2533 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
2534 tx_frame.wi_type = eh->ether_type;
2535
2536 if (hostencrypt) {
2537
2538
2539 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
2540 bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8);
2541
2542 m_copydata(m0, sizeof(struct ether_header),
2543 m0->m_pkthdr.len - sizeof(struct ether_header),
2544 (caddr_t)&sc->wi_txbuf[12]);
2545
2546 wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
2547 tx_frame.wi_dat_len);
2548
2549 tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
2550 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2551
2552 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2553 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2554 sizeof(struct wi_frame));
2555 wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
2556 (caddr_t)&sc->wi_txbuf,
2557 (m0->m_pkthdr.len -
2558 sizeof(struct ether_header)) + 18);
2559 } else {
2560 m_copydata(m0, sizeof(struct ether_header),
2561 m0->m_pkthdr.len - sizeof(struct ether_header),
2562 (caddr_t)&sc->wi_txbuf);
2563
2564 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2565 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2566 sizeof(struct wi_frame));
2567 wi_write_data(sc, id, WI_802_11_OFFSET,
2568 (caddr_t)&sc->wi_txbuf,
2569 (m0->m_pkthdr.len -
2570 sizeof(struct ether_header)) + 2);
2571 }
2572 } else {
2573 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
2574
2575 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
2576
2577
2578 printf(WI_PRT_FMT
2579 ": host encrypt not implemented for 802.3\n",
2580 WI_PRT_ARG(sc));
2581 } else {
2582 m_copydata(m0, 0, m0->m_pkthdr.len,
2583 (caddr_t)&sc->wi_txbuf);
2584
2585 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2586 sizeof(struct wi_frame));
2587 wi_write_data(sc, id, WI_802_3_OFFSET,
2588 (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
2589 }
2590 }
2591
2592 #if NBPFILTER > 0
2593
2594
2595
2596
2597 if (ifp->if_bpf)
2598 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
2599 #endif
2600
2601 m_freem(m0);
2602
2603 ifp->if_flags |= IFF_OACTIVE;
2604
2605
2606
2607
2608 ifp->if_timer = 5;
2609
2610 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
2611 printf(WI_PRT_FMT ": wi_start: xmit failed\n", WI_PRT_ARG(sc));
2612
2613 return;
2614 }
2615
2616 STATIC int
2617 wi_mgmt_xmit(struct wi_softc *sc, caddr_t data, int len)
2618 {
2619 struct wi_frame tx_frame;
2620 int id;
2621 struct wi_80211_hdr *hdr;
2622 caddr_t dptr;
2623
2624 if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2625 return(ENODEV);
2626
2627 hdr = (struct wi_80211_hdr *)data;
2628 dptr = data + sizeof(struct wi_80211_hdr);
2629
2630 bzero((char *)&tx_frame, sizeof(tx_frame));
2631 id = sc->wi_tx_mgmt_id;
2632
2633 bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
2634 sizeof(struct wi_80211_hdr));
2635
2636 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
2637 tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2638 tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
2639
2640 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2641 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2642 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2643 (len - sizeof(struct wi_80211_hdr)) + 2);
2644
2645 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
2646 printf(WI_PRT_FMT ": wi_mgmt_xmit: xmit failed\n",
2647 WI_PRT_ARG(sc));
2648
2649
2650
2651
2652
2653 wi_reset(sc);
2654 return(EIO);
2655 }
2656
2657 return(0);
2658 }
2659
2660 void
2661 wi_stop(struct wi_softc *sc)
2662 {
2663 struct ifnet *ifp;
2664
2665 wihap_shutdown(sc);
2666
2667 if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2668 return;
2669
2670 DPRINTF(WID_STOP, ("wi_stop: sc %p\n", sc));
2671
2672 timeout_del(&sc->sc_timo);
2673
2674 ifp = &sc->sc_ic.ic_if;
2675
2676 wi_intr_enable(sc, 0);
2677 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
2678
2679 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
2680 ifp->if_timer = 0;
2681
2682 return;
2683 }
2684
2685
2686 void
2687 wi_watchdog(struct ifnet *ifp)
2688 {
2689 struct wi_softc *sc;
2690
2691 sc = ifp->if_softc;
2692
2693 printf(WI_PRT_FMT ": device timeout\n", WI_PRT_ARG(sc));
2694
2695 wi_cor_reset(sc);
2696 wi_init(sc);
2697
2698 ifp->if_oerrors++;
2699
2700 return;
2701 }
2702
2703 void
2704 wi_detach(struct wi_softc *sc)
2705 {
2706 struct ifnet *ifp;
2707 ifp = &sc->sc_ic.ic_if;
2708
2709 if (ifp->if_flags & IFF_RUNNING)
2710 wi_stop(sc);
2711
2712 if (sc->wi_flags & WI_FLAGS_ATTACHED) {
2713 sc->wi_flags &= ~WI_FLAGS_ATTACHED;
2714 if (sc->sc_sdhook != NULL)
2715 shutdownhook_disestablish(sc->sc_sdhook);
2716 }
2717 }
2718
2719 STATIC void
2720 wi_shutdown(void *arg)
2721 {
2722 struct wi_softc *sc;
2723
2724 sc = arg;
2725 wi_stop(sc);
2726
2727 return;
2728 }
2729
2730 STATIC void
2731 wi_get_id(struct wi_softc *sc)
2732 {
2733 struct wi_ltv_ver ver;
2734 const struct wi_card_ident *id;
2735 u_int16_t pri_fw_ver[3];
2736 const char *card_name;
2737 u_int16_t card_id;
2738
2739
2740 bzero(&ver, sizeof(ver));
2741 ver.wi_type = WI_RID_CARD_ID;
2742 ver.wi_len = 5;
2743 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2744 card_id = letoh16(ver.wi_ver[0]);
2745 for (id = wi_card_ident; id->firm_type != WI_NOTYPE; id++) {
2746 if (card_id == id->card_id)
2747 break;
2748 }
2749 if (id->firm_type != WI_NOTYPE) {
2750 sc->sc_firmware_type = id->firm_type;
2751 card_name = id->card_name;
2752 } else if (ver.wi_ver[0] & htole16(0x8000)) {
2753 sc->sc_firmware_type = WI_INTERSIL;
2754 card_name = "Unknown PRISM2 chip";
2755 } else {
2756 sc->sc_firmware_type = WI_LUCENT;
2757 }
2758
2759
2760 if (sc->sc_firmware_type != WI_LUCENT) {
2761 bzero(&ver, sizeof(ver));
2762 ver.wi_type = WI_RID_PRI_IDENTITY;
2763 ver.wi_len = 5;
2764 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2765 pri_fw_ver[0] = letoh16(ver.wi_ver[2]);
2766 pri_fw_ver[1] = letoh16(ver.wi_ver[3]);
2767 pri_fw_ver[2] = letoh16(ver.wi_ver[1]);
2768 }
2769
2770
2771 bzero(&ver, sizeof(ver));
2772 ver.wi_type = WI_RID_STA_IDENTITY;
2773 ver.wi_len = 5;
2774 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2775 ver.wi_ver[1] = letoh16(ver.wi_ver[1]);
2776 ver.wi_ver[2] = letoh16(ver.wi_ver[2]);
2777 ver.wi_ver[3] = letoh16(ver.wi_ver[3]);
2778 sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2779 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2780
2781 if (sc->sc_firmware_type == WI_INTERSIL &&
2782 (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2783 struct wi_ltv_str sver;
2784 char *p;
2785
2786 bzero(&sver, sizeof(sver));
2787 sver.wi_type = WI_RID_SYMBOL_IDENTITY;
2788 sver.wi_len = 7;
2789
2790 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2791 *(p = (char *)sver.wi_str) >= 'A' &&
2792 p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2793 sc->sc_firmware_type = WI_SYMBOL;
2794 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2795 (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2796 (p[6] - '0') * 10 + (p[7] - '0');
2797 }
2798 }
2799
2800 if (sc->sc_firmware_type == WI_LUCENT) {
2801 printf("%s: Firmware %d.%02d variant %d, ", WI_PRT_ARG(sc),
2802 ver.wi_ver[2], ver.wi_ver[3], ver.wi_ver[1]);
2803 } else {
2804 printf("%s: %s%s (0x%04x), Firmware %d.%d.%d (primary), %d.%d.%d (station), ",
2805 WI_PRT_ARG(sc),
2806 sc->sc_firmware_type == WI_SYMBOL ? "Symbol " : "",
2807 card_name, card_id, pri_fw_ver[0], pri_fw_ver[1],
2808 pri_fw_ver[2], sc->sc_sta_firmware_ver / 10000,
2809 (sc->sc_sta_firmware_ver % 10000) / 100,
2810 sc->sc_sta_firmware_ver % 100);
2811 }
2812 }
2813
2814 STATIC int
2815 wi_sync_media(struct wi_softc *sc, int ptype, int txrate)
2816 {
2817 int media = sc->sc_media.ifm_cur->ifm_media;
2818 int options = IFM_OPTIONS(media);
2819 int subtype;
2820
2821 switch (txrate) {
2822 case 1:
2823 subtype = IFM_IEEE80211_DS1;
2824 break;
2825 case 2:
2826 subtype = IFM_IEEE80211_DS2;
2827 break;
2828 case 3:
2829 subtype = IFM_AUTO;
2830 break;
2831 case 5:
2832 subtype = IFM_IEEE80211_DS5;
2833 break;
2834 case 11:
2835 subtype = IFM_IEEE80211_DS11;
2836 break;
2837 default:
2838 subtype = IFM_MANUAL;
2839 break;
2840 }
2841
2842 options &= ~IFM_OMASK;
2843 switch (ptype) {
2844 case WI_PORTTYPE_BSS:
2845
2846 break;
2847 case WI_PORTTYPE_ADHOC:
2848 options |= IFM_IEEE80211_ADHOC;
2849 break;
2850 case WI_PORTTYPE_HOSTAP:
2851 options |= IFM_IEEE80211_HOSTAP;
2852 break;
2853 case WI_PORTTYPE_IBSS:
2854 if (sc->wi_create_ibss)
2855 options |= IFM_IEEE80211_IBSSMASTER;
2856 else
2857 options |= IFM_IEEE80211_IBSS;
2858 break;
2859 default:
2860 subtype = IFM_MANUAL;
2861 break;
2862 }
2863 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
2864 IFM_INST(media));
2865 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
2866 return (EINVAL);
2867 ifmedia_set(&sc->sc_media, media);
2868 sc->wi_ptype = ptype;
2869 sc->wi_tx_rate = txrate;
2870 return (0);
2871 }
2872
2873 STATIC int
2874 wi_media_change(struct ifnet *ifp)
2875 {
2876 struct wi_softc *sc = ifp->if_softc;
2877 int otype = sc->wi_ptype;
2878 int orate = sc->wi_tx_rate;
2879 int ocreate_ibss = sc->wi_create_ibss;
2880
2881 if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
2882 sc->sc_firmware_type != WI_INTERSIL)
2883 return (EINVAL);
2884
2885 sc->wi_create_ibss = 0;
2886
2887 switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
2888 case 0:
2889 sc->wi_ptype = WI_PORTTYPE_BSS;
2890 break;
2891 case IFM_IEEE80211_ADHOC:
2892 sc->wi_ptype = WI_PORTTYPE_ADHOC;
2893 break;
2894 case IFM_IEEE80211_HOSTAP:
2895 sc->wi_ptype = WI_PORTTYPE_HOSTAP;
2896 break;
2897 case IFM_IEEE80211_IBSSMASTER:
2898 case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
2899 if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
2900 return (EINVAL);
2901 sc->wi_create_ibss = 1;
2902
2903 case IFM_IEEE80211_IBSS:
2904 sc->wi_ptype = WI_PORTTYPE_IBSS;
2905 break;
2906 default:
2907
2908 return (EINVAL);
2909 }
2910
2911 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
2912 case IFM_IEEE80211_DS1:
2913 sc->wi_tx_rate = 1;
2914 break;
2915 case IFM_IEEE80211_DS2:
2916 sc->wi_tx_rate = 2;
2917 break;
2918 case IFM_AUTO:
2919 sc->wi_tx_rate = 3;
2920 break;
2921 case IFM_IEEE80211_DS5:
2922 sc->wi_tx_rate = 5;
2923 break;
2924 case IFM_IEEE80211_DS11:
2925 sc->wi_tx_rate = 11;
2926 break;
2927 }
2928
2929 if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2930 if (otype != sc->wi_ptype || orate != sc->wi_tx_rate ||
2931 ocreate_ibss != sc->wi_create_ibss)
2932 wi_init(sc);
2933 }
2934
2935 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2936
2937 return (0);
2938 }
2939
2940 STATIC void
2941 wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2942 {
2943 struct wi_softc *sc = ifp->if_softc;
2944 struct wi_req wreq;
2945
2946 if (!(sc->sc_ic.ic_if.if_flags & IFF_UP)) {
2947 imr->ifm_active = IFM_IEEE80211|IFM_NONE;
2948 imr->ifm_status = 0;
2949 return;
2950 }
2951
2952 if (sc->wi_tx_rate == 3) {
2953 imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
2954
2955 wreq.wi_type = WI_RID_CUR_TX_RATE;
2956 wreq.wi_len = WI_MAX_DATALEN;
2957 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
2958 switch (letoh16(wreq.wi_val[0])) {
2959 case 1:
2960 imr->ifm_active |= IFM_IEEE80211_DS1;
2961 break;
2962 case 2:
2963 imr->ifm_active |= IFM_IEEE80211_DS2;
2964 break;
2965 case 6:
2966 imr->ifm_active |= IFM_IEEE80211_DS5;
2967 break;
2968 case 11:
2969 imr->ifm_active |= IFM_IEEE80211_DS11;
2970 break;
2971 }
2972 }
2973 } else {
2974 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2975 }
2976
2977 imr->ifm_status = IFM_AVALID;
2978 switch (sc->wi_ptype) {
2979 case WI_PORTTYPE_ADHOC:
2980 case WI_PORTTYPE_IBSS:
2981
2982
2983
2984
2985
2986
2987 case WI_PORTTYPE_HOSTAP:
2988 imr->ifm_status |= IFM_ACTIVE;
2989 break;
2990 default:
2991 wreq.wi_type = WI_RID_COMMQUAL;
2992 wreq.wi_len = WI_MAX_DATALEN;
2993 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2994 letoh16(wreq.wi_val[0]) != 0)
2995 imr->ifm_status |= IFM_ACTIVE;
2996 }
2997 }
2998
2999 STATIC int
3000 wi_set_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
3001 {
3002 int i, len, error;
3003 struct wi_req wreq;
3004 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
3005
3006 if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
3007 return ENODEV;
3008 if (nwkey->i_defkid <= 0 || nwkey->i_defkid > IEEE80211_WEP_NKID)
3009 return EINVAL;
3010 memcpy(wk, &sc->wi_keys, sizeof(*wk));
3011 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
3012 if (nwkey->i_key[i].i_keydat == NULL)
3013 continue;
3014 len = nwkey->i_key[i].i_keylen;
3015 if (len > sizeof(wk->wi_keys[i].wi_keydat))
3016 return EINVAL;
3017 error = copyin(nwkey->i_key[i].i_keydat,
3018 wk->wi_keys[i].wi_keydat, len);
3019 if (error)
3020 return error;
3021 wk->wi_keys[i].wi_keylen = htole16(len);
3022 }
3023
3024 wk->wi_len = (sizeof(*wk) / 2) + 1;
3025 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
3026 if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
3027 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
3028 if (error)
3029 return error;
3030 }
3031 if ((error = wi_setdef(sc, &wreq)))
3032 return (error);
3033
3034 wreq.wi_len = 2;
3035 wreq.wi_type = WI_RID_TX_CRYPT_KEY;
3036 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
3037 if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
3038 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
3039 if (error)
3040 return error;
3041 }
3042 if ((error = wi_setdef(sc, &wreq)))
3043 return (error);
3044
3045 wreq.wi_type = WI_RID_ENCRYPTION;
3046 wreq.wi_val[0] = htole16(nwkey->i_wepon);
3047 if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
3048 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
3049 if (error)
3050 return error;
3051 }
3052 if ((error = wi_setdef(sc, &wreq)))
3053 return (error);
3054
3055 if (sc->sc_ic.ic_if.if_flags & IFF_UP)
3056 wi_init(sc);
3057 return 0;
3058 }
3059
3060 STATIC int
3061 wi_get_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
3062 {
3063 int i, len, error;
3064 struct wi_ltv_keys *wk = &sc->wi_keys;
3065
3066 if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
3067 return ENODEV;
3068 nwkey->i_wepon = sc->wi_use_wep;
3069 nwkey->i_defkid = sc->wi_tx_key + 1;
3070
3071
3072 error = suser(curproc, 0);
3073 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
3074 if (nwkey->i_key[i].i_keydat == NULL)
3075 continue;
3076
3077 if (error)
3078 return error;
3079 len = letoh16(wk->wi_keys[i].wi_keylen);
3080 if (nwkey->i_key[i].i_keylen < len)
3081 return ENOSPC;
3082 nwkey->i_key[i].i_keylen = len;
3083 error = copyout(wk->wi_keys[i].wi_keydat,
3084 nwkey->i_key[i].i_keydat, len);
3085 if (error)
3086 return error;
3087 }
3088 return 0;
3089 }
3090
3091 STATIC int
3092 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
3093 {
3094
3095 sc->wi_pm_enabled = power->i_enabled;
3096 sc->wi_max_sleep = power->i_maxsleep;
3097
3098 if (sc->sc_ic.ic_if.if_flags & IFF_UP)
3099 wi_init(sc);
3100
3101 return (0);
3102 }
3103
3104 STATIC int
3105 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
3106 {
3107
3108 power->i_enabled = sc->wi_pm_enabled;
3109 power->i_maxsleep = sc->wi_max_sleep;
3110
3111 return (0);
3112 }
3113
3114 STATIC int
3115 wi_set_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
3116 {
3117 u_int16_t cmd;
3118 u_int16_t power;
3119 int8_t tmp;
3120 int error;
3121 int alc;
3122
3123 if (txpower == NULL) {
3124 if (!(sc->wi_flags & WI_FLAGS_TXPOWER))
3125 return (EINVAL);
3126 alc = 0;
3127 } else {
3128 if (txpower->i_mode == IEEE80211_TXPOWER_MODE_AUTO) {
3129 alc = 1;
3130 sc->wi_flags &= ~WI_FLAGS_TXPOWER;
3131 } else {
3132 alc = 0;
3133 sc->wi_flags |= WI_FLAGS_TXPOWER;
3134 sc->wi_txpower = txpower->i_val;
3135 }
3136 }
3137
3138
3139 cmd = WI_CMD_DEBUG | (WI_DEBUG_CONFBITS << 8);
3140 if ((error = wi_cmd(sc, cmd, alc, 0x8, 0)) != 0)
3141 return (error);
3142
3143
3144 if (alc)
3145 return (0);
3146
3147
3148 if (sc->wi_txpower > 20)
3149 power = 128;
3150 else if (sc->wi_txpower < -43)
3151 power = 127;
3152 else {
3153 tmp = sc->wi_txpower;
3154 tmp = -12 - tmp;
3155 tmp <<= 2;
3156
3157 power = (u_int16_t)tmp;
3158 }
3159
3160
3161 cmd = WI_CMD_WRITE_MIF;
3162 if ((error = wi_cmd(sc, cmd,
3163 WI_HFA384X_CR_MANUAL_TX_POWER, power, 0)) != 0)
3164 return (error);
3165
3166 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
3167 printf("%s: %u (%d dBm)\n", sc->sc_dev.dv_xname, power,
3168 sc->wi_txpower);
3169
3170 return (0);
3171 }
3172
3173 STATIC int
3174 wi_get_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
3175 {
3176 u_int16_t cmd;
3177 u_int16_t power;
3178 int8_t tmp;
3179 int error;
3180
3181 if (sc->wi_flags & WI_FLAGS_BUS_USB)
3182 return (EOPNOTSUPP);
3183
3184
3185 cmd = WI_CMD_READ_MIF;
3186 if ((error = wi_cmd(sc, cmd,
3187 WI_HFA384X_CR_MANUAL_TX_POWER, 0, 0)) != 0)
3188 return (error);
3189
3190 power = CSR_READ_2(sc, WI_RESP0);
3191
3192
3193 if (power > 255)
3194 txpower->i_val = 255;
3195 else {
3196 tmp = power;
3197 tmp >>= 2;
3198 txpower->i_val = (u_int16_t)(-12 - tmp);
3199 }
3200
3201 if (sc->wi_flags & WI_FLAGS_TXPOWER)
3202 txpower->i_mode = IEEE80211_TXPOWER_MODE_FIXED;
3203 else
3204 txpower->i_mode = IEEE80211_TXPOWER_MODE_AUTO;
3205
3206 return (0);
3207 }
3208
3209 STATIC int
3210 wi_set_ssid(struct ieee80211_nwid *ws, u_int8_t *id, int len)
3211 {
3212
3213 if (len > IEEE80211_NWID_LEN)
3214 return (EINVAL);
3215 ws->i_len = len;
3216 memcpy(ws->i_nwid, id, len);
3217 return (0);
3218 }
3219
3220 STATIC int
3221 wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
3222 {
3223 int error = 0;
3224
3225 wreq->wi_len = 1;
3226
3227 switch (wreq->wi_type) {
3228 case WI_DEBUG_SLEEP:
3229 wreq->wi_len++;
3230 wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep);
3231 break;
3232 case WI_DEBUG_DELAYSUPP:
3233 wreq->wi_len++;
3234 wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp);
3235 break;
3236 case WI_DEBUG_TXSUPP:
3237 wreq->wi_len++;
3238 wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp);
3239 break;
3240 case WI_DEBUG_MONITOR:
3241 wreq->wi_len++;
3242 wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor);
3243 break;
3244 case WI_DEBUG_LEDTEST:
3245 wreq->wi_len += 3;
3246 wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest);
3247 wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0);
3248 wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1);
3249 break;
3250 case WI_DEBUG_CONTTX:
3251 wreq->wi_len += 2;
3252 wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx);
3253 wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0);
3254 break;
3255 case WI_DEBUG_CONTRX:
3256 wreq->wi_len++;
3257 wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx);
3258 break;
3259 case WI_DEBUG_SIGSTATE:
3260 wreq->wi_len += 2;
3261 wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate);
3262 wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0);
3263 break;
3264 case WI_DEBUG_CONFBITS:
3265 wreq->wi_len += 2;
3266 wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits);
3267 wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0);
3268 break;
3269 default:
3270 error = EIO;
3271 break;
3272 }
3273
3274 return (error);
3275 }
3276
3277 STATIC int
3278 wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
3279 {
3280 int error = 0;
3281 u_int16_t cmd, param0 = 0, param1 = 0;
3282
3283 switch (wreq->wi_type) {
3284 case WI_DEBUG_RESET:
3285 case WI_DEBUG_INIT:
3286 case WI_DEBUG_CALENABLE:
3287 break;
3288 case WI_DEBUG_SLEEP:
3289 sc->wi_debug.wi_sleep = 1;
3290 break;
3291 case WI_DEBUG_WAKE:
3292 sc->wi_debug.wi_sleep = 0;
3293 break;
3294 case WI_DEBUG_CHAN:
3295 param0 = letoh16(wreq->wi_val[0]);
3296 break;
3297 case WI_DEBUG_DELAYSUPP:
3298 sc->wi_debug.wi_delaysupp = 1;
3299 break;
3300 case WI_DEBUG_TXSUPP:
3301 sc->wi_debug.wi_txsupp = 1;
3302 break;
3303 case WI_DEBUG_MONITOR:
3304 sc->wi_debug.wi_monitor = 1;
3305 break;
3306 case WI_DEBUG_LEDTEST:
3307 param0 = letoh16(wreq->wi_val[0]);
3308 param1 = letoh16(wreq->wi_val[1]);
3309 sc->wi_debug.wi_ledtest = 1;
3310 sc->wi_debug.wi_ledtest_param0 = param0;
3311 sc->wi_debug.wi_ledtest_param1 = param1;
3312 break;
3313 case WI_DEBUG_CONTTX:
3314 param0 = letoh16(wreq->wi_val[0]);
3315 sc->wi_debug.wi_conttx = 1;
3316 sc->wi_debug.wi_conttx_param0 = param0;
3317 break;
3318 case WI_DEBUG_STOPTEST:
3319 sc->wi_debug.wi_delaysupp = 0;
3320 sc->wi_debug.wi_txsupp = 0;
3321 sc->wi_debug.wi_monitor = 0;
3322 sc->wi_debug.wi_ledtest = 0;
3323 sc->wi_debug.wi_ledtest_param0 = 0;
3324 sc->wi_debug.wi_ledtest_param1 = 0;
3325 sc->wi_debug.wi_conttx = 0;
3326 sc->wi_debug.wi_conttx_param0 = 0;
3327 sc->wi_debug.wi_contrx = 0;
3328 sc->wi_debug.wi_sigstate = 0;
3329 sc->wi_debug.wi_sigstate_param0 = 0;
3330 break;
3331 case WI_DEBUG_CONTRX:
3332 sc->wi_debug.wi_contrx = 1;
3333 break;
3334 case WI_DEBUG_SIGSTATE:
3335 param0 = letoh16(wreq->wi_val[0]);
3336 sc->wi_debug.wi_sigstate = 1;
3337 sc->wi_debug.wi_sigstate_param0 = param0;
3338 break;
3339 case WI_DEBUG_CONFBITS:
3340 param0 = letoh16(wreq->wi_val[0]);
3341 param1 = letoh16(wreq->wi_val[1]);
3342 sc->wi_debug.wi_confbits = param0;
3343 sc->wi_debug.wi_confbits_param0 = param1;
3344 break;
3345 default:
3346 error = EIO;
3347 break;
3348 }
3349
3350 if (error)
3351 return (error);
3352
3353 cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3354 error = wi_cmd(sc, cmd, param0, param1, 0);
3355
3356 return (error);
3357 }