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