wi.c revision 1.82 1 /* $NetBSD: wi.c,v 1.82 2002/08/12 16:56:39 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.82 2002/08/12 16:56:39 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, 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, 0, 0);
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, 0, 0);
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 0, 0);
817 break;
818 }
819 /*
820 * Some cards issue streams of "connected" messages while
821 * trying to find a peer. Don't bother the user with this
822 * unless he is debugging.
823 */
824 if (ifp->if_flags & IFF_DEBUG)
825 printf("%s: %s\n", sc->sc_dev.dv_xname, msg[t - 1]);
826 break;
827 }
828
829 case WI_INFO_ASSOC_STAT: {
830 static char *msg[] = {
831 "STA Associated",
832 "STA Reassociated",
833 "STA Disassociated",
834 "Association Failure",
835 "Authentication Failed"
836 };
837 if (gen.wi_len != 10)
838 break;
839 for (i=0; i < gen.wi_len - 1; i++)
840 ((u_int16_t *)&assoc)[i] = CSR_READ_2(sc, WI_DATA1);
841 /* unswap 8 bit data fields: */
842 for(j=0;j<sizeof(assoc.wi_assoc_sta)/2;j++)
843 HTOLE16(((u_int16_t *)&assoc.wi_assoc_sta[0])[j]);
844 for(j=0;j<sizeof(assoc.wi_assoc_osta)/2;j++)
845 HTOLE16(((u_int16_t *)&assoc.wi_assoc_osta[0])[j]);
846 switch (assoc.wi_assoc_stat) {
847 case ASSOC:
848 case DISASSOC:
849 case ASSOCFAIL:
850 case AUTHFAIL:
851 printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x\n",
852 sc->sc_dev.dv_xname,
853 msg[assoc.wi_assoc_stat - 1],
854 assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
855 assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
856 assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff);
857 break;
858 case REASSOC:
859 printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x, "
860 "OldAP = %02x:%02x:%02x:%02x:%02x:%02x\n",
861 sc->sc_dev.dv_xname, msg[assoc.wi_assoc_stat - 1],
862 assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
863 assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
864 assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff,
865 assoc.wi_assoc_osta[0]&0xff, assoc.wi_assoc_osta[1]&0xff,
866 assoc.wi_assoc_osta[2]&0xff, assoc.wi_assoc_osta[3]&0xff,
867 assoc.wi_assoc_osta[4]&0xff, assoc.wi_assoc_osta[5]&0xff);
868 break;
869 }
870 }
871
872 default:
873 #ifdef WI_DEBUG
874 printf("%s: got info type: 0x%04x len=0x%04x\n",
875 sc->sc_dev.dv_xname, gen.wi_type,gen.wi_len);
876 #endif
877 #if 0
878 for (i = 0; i < gen.wi_len; i++) {
879 t = CSR_READ_2(sc, WI_DATA1);
880 printf("[0x%02x] = 0x%04x\n", i, t);
881 }
882 #endif
883 break;
884 }
885 }
886
887 int wi_intr(arg)
888 void *arg;
889 {
890 struct wi_softc *sc = arg;
891 struct ifnet *ifp;
892 u_int16_t status;
893
894 if (sc->sc_enabled == 0 ||
895 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
896 (sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0)
897 return (0);
898
899 ifp = &sc->sc_ethercom.ec_if;
900
901 if (!(ifp->if_flags & IFF_UP)) {
902 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
903 CSR_WRITE_2(sc, WI_INT_EN, 0);
904 return 1;
905 }
906
907 /* Disable interrupts. */
908 CSR_WRITE_2(sc, WI_INT_EN, 0);
909
910 status = CSR_READ_2(sc, WI_EVENT_STAT);
911 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
912
913 if (status & WI_EV_RX) {
914 wi_rxeof(sc);
915 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
916 }
917
918 if (status & WI_EV_TX) {
919 wi_txeof(sc, status);
920 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
921 }
922
923 if (status & WI_EV_ALLOC) {
924 int id;
925 id = CSR_READ_2(sc, WI_ALLOC_FID);
926 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
927 if (id == sc->wi_tx_data_id)
928 wi_txeof(sc, status);
929 }
930
931 if (status & WI_EV_INFO) {
932 wi_update_stats(sc);
933 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
934 }
935
936 if (status & WI_EV_TX_EXC) {
937 wi_txeof(sc, status);
938 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
939 }
940
941 if (status & WI_EV_INFO_DROP) {
942 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
943 }
944
945 /* Re-enable interrupts. */
946 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
947
948 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
949 wi_start(ifp);
950
951 return 1;
952 }
953
954 /* Must be called at proper protection level! */
955 static int
956 wi_cmd(sc, cmd, val0, val1, val2)
957 struct wi_softc *sc;
958 int cmd;
959 int val0;
960 int val1;
961 int val2;
962 {
963 int i, s = 0;
964
965 /* wait for the busy bit to clear */
966 for (i = 0; i < WI_TIMEOUT; i++) {
967 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
968 break;
969 }
970
971 if (i == WI_TIMEOUT) {
972 printf("%s: wi_cmd: BUSY did not clear, cmd=0x%x\n",
973 sc->sc_dev.dv_xname, cmd);
974 return EIO;
975 }
976
977 CSR_WRITE_2(sc, WI_PARAM0, val0);
978 CSR_WRITE_2(sc, WI_PARAM1, val1);
979 CSR_WRITE_2(sc, WI_PARAM2, val2);
980 CSR_WRITE_2(sc, WI_COMMAND, cmd);
981
982 /* wait for the cmd completed bit */
983 for (i = 0; i < WI_TIMEOUT; i++) {
984 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
985 break;
986 DELAY(1);
987 }
988
989 /* Ack the command */
990 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
991
992 s = CSR_READ_2(sc, WI_STATUS);
993 if (s & WI_STAT_CMD_RESULT)
994 return(EIO);
995
996 if (i == WI_TIMEOUT) {
997 if (!sc->wi_scanning)
998 printf("%s: command timed out, cmd=0x%x\n",
999 sc->sc_dev.dv_xname, cmd);
1000 return(ETIMEDOUT);
1001 }
1002
1003 return(0);
1004 }
1005
1006 static void
1007 wi_reset(sc)
1008 struct wi_softc *sc;
1009 {
1010
1011 DELAY(100*1000); /* 100 m sec */
1012 if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0))
1013 printf("%s: init failed\n", sc->sc_dev.dv_xname);
1014 CSR_WRITE_2(sc, WI_INT_EN, 0);
1015 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
1016
1017 /* Calibrate timer. */
1018 WI_SETVAL(WI_RID_TICK_TIME, 8);
1019
1020 return;
1021 }
1022
1023 /*
1024 * Read an LTV record from the NIC.
1025 */
1026 static int wi_read_record(sc, ltv)
1027 struct wi_softc *sc;
1028 struct wi_ltv_gen *ltv;
1029 {
1030 u_int16_t *ptr;
1031 int len, code;
1032 struct wi_ltv_gen *oltv, p2ltv;
1033
1034 if (sc->sc_firmware_type != WI_LUCENT) {
1035 oltv = ltv;
1036 switch (ltv->wi_type) {
1037 case WI_RID_ENCRYPTION:
1038 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1039 p2ltv.wi_len = 2;
1040 ltv = &p2ltv;
1041 break;
1042 case WI_RID_TX_CRYPT_KEY:
1043 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1044 p2ltv.wi_len = 2;
1045 ltv = &p2ltv;
1046 break;
1047 case WI_RID_ROAMING_MODE:
1048 if (sc->sc_firmware_type == WI_INTERSIL)
1049 break;
1050 /* not supported */
1051 ltv->wi_len = 1;
1052 return 0;
1053 case WI_RID_MICROWAVE_OVEN:
1054 /* not supported */
1055 ltv->wi_len = 1;
1056 return 0;
1057 }
1058 }
1059
1060 /* Tell the NIC to enter record read mode. */
1061 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
1062 return(EIO);
1063
1064 /* Seek to the record. */
1065 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1066 return(EIO);
1067
1068 /*
1069 * Read the length and record type and make sure they
1070 * match what we expect (this verifies that we have enough
1071 * room to hold all of the returned data).
1072 */
1073 len = CSR_READ_2(sc, WI_DATA1);
1074 if (len > ltv->wi_len)
1075 return(ENOSPC);
1076 code = CSR_READ_2(sc, WI_DATA1);
1077 if (code != ltv->wi_type)
1078 return(EIO);
1079
1080 ltv->wi_len = len;
1081 ltv->wi_type = code;
1082
1083 /* Now read the data. */
1084 ptr = <v->wi_val;
1085 if (ltv->wi_len > 1)
1086 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
1087
1088 if (ltv->wi_type == WI_RID_PORTTYPE &&
1089 sc->wi_ptype == WI_PORTTYPE_IBSS &&
1090 ltv->wi_val == sc->wi_ibss_port) {
1091 /*
1092 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
1093 * Since Lucent uses port type 1 for BSS *and* IBSS we
1094 * have to rely on wi_ptype to distinguish this for us.
1095 */
1096 ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
1097 } else if (sc->sc_firmware_type != WI_LUCENT) {
1098 int v;
1099
1100 switch (oltv->wi_type) {
1101 case WI_RID_TX_RATE:
1102 case WI_RID_CUR_TX_RATE:
1103 switch (le16toh(ltv->wi_val)) {
1104 case 1: v = 1; break;
1105 case 2: v = 2; break;
1106 case 3: v = 6; break;
1107 case 4: v = 5; break;
1108 case 7: v = 7; break;
1109 case 8: v = 11; break;
1110 case 15: v = 3; break;
1111 default: v = 0x100 + le16toh(ltv->wi_val); break;
1112 }
1113 oltv->wi_val = htole16(v);
1114 break;
1115 case WI_RID_ENCRYPTION:
1116 oltv->wi_len = 2;
1117 if (le16toh(ltv->wi_val) & 0x01)
1118 oltv->wi_val = htole16(1);
1119 else
1120 oltv->wi_val = htole16(0);
1121 break;
1122 case WI_RID_TX_CRYPT_KEY:
1123 oltv->wi_len = 2;
1124 oltv->wi_val = ltv->wi_val;
1125 break;
1126 case WI_RID_CNFAUTHMODE:
1127 oltv->wi_len = 2;
1128 if (le16toh(ltv->wi_val) & 0x01)
1129 oltv->wi_val = htole16(1);
1130 else if (le16toh(ltv->wi_val) & 0x02)
1131 oltv->wi_val = htole16(2);
1132 break;
1133 }
1134 }
1135
1136 return(0);
1137 }
1138
1139 /*
1140 * Same as read, except we inject data instead of reading it.
1141 */
1142 static int wi_write_record(sc, ltv)
1143 struct wi_softc *sc;
1144 struct wi_ltv_gen *ltv;
1145 {
1146 u_int16_t *ptr;
1147 int i;
1148 struct wi_ltv_gen p2ltv;
1149
1150 if (ltv->wi_type == WI_RID_PORTTYPE &&
1151 ltv->wi_val == le16toh(WI_PORTTYPE_IBSS)) {
1152 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
1153 p2ltv.wi_type = WI_RID_PORTTYPE;
1154 p2ltv.wi_len = 2;
1155 p2ltv.wi_val = sc->wi_ibss_port;
1156 ltv = &p2ltv;
1157 } else if (sc->sc_firmware_type != WI_LUCENT) {
1158 int v;
1159
1160 switch (ltv->wi_type) {
1161 case WI_RID_TX_RATE:
1162 p2ltv.wi_type = WI_RID_TX_RATE;
1163 p2ltv.wi_len = 2;
1164 switch (le16toh(ltv->wi_val)) {
1165 case 1: v = 1; break;
1166 case 2: v = 2; break;
1167 case 3: v = 15; break;
1168 case 5: v = 4; break;
1169 case 6: v = 3; break;
1170 case 7: v = 7; break;
1171 case 11: v = 8; break;
1172 default: return EINVAL;
1173 }
1174 p2ltv.wi_val = htole16(v);
1175 ltv = &p2ltv;
1176 break;
1177 case WI_RID_ENCRYPTION:
1178 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1179 p2ltv.wi_len = 2;
1180 if (le16toh(ltv->wi_val)) {
1181 uint16_t val = PRIVACY_INVOKED;
1182 /*
1183 * If using shared key WEP we must set the
1184 * EXCLUDE_UNENCRYPTED bit. Symbol cards
1185 * need this bit even when not using shared
1186 * key. We can't just test for
1187 * IEEE80211_AUTH_SHARED since Symbol cards
1188 * have 2 shared key modes.
1189 */
1190 if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
1191 sc->sc_firmware_type == WI_SYMBOL)
1192 val |= EXCLUDE_UNENCRYPTED;
1193 /* Tx encryption is broken in Host-AP mode. */
1194 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
1195 val |= HOST_ENCRYPT;
1196 p2ltv.wi_val = htole16(val);
1197 } else
1198 p2ltv.wi_val =
1199 htole16(HOST_ENCRYPT | HOST_DECRYPT);
1200 ltv = &p2ltv;
1201 break;
1202 case WI_RID_TX_CRYPT_KEY:
1203 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1204 p2ltv.wi_len = 2;
1205 p2ltv.wi_val = ltv->wi_val;
1206 ltv = &p2ltv;
1207 break;
1208 case WI_RID_DEFLT_CRYPT_KEYS:
1209 {
1210 int error;
1211 int keylen;
1212 struct wi_ltv_str ws;
1213 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
1214
1215 keylen = le16toh(wk->wi_keys[sc->wi_tx_key].wi_keylen);
1216
1217 for (i = 0; i < 4; i++) {
1218 memset(&ws, 0, sizeof(ws));
1219 ws.wi_len = (keylen > 5) ? 8 : 4;
1220 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1221 memcpy(ws.wi_str,
1222 &wk->wi_keys[i].wi_keydat, keylen);
1223 error = wi_write_record(sc,
1224 (struct wi_ltv_gen *)&ws);
1225 if (error)
1226 return error;
1227 }
1228 return 0;
1229 }
1230 case WI_RID_CNFAUTHMODE:
1231 p2ltv.wi_type = WI_RID_CNFAUTHMODE;
1232 p2ltv.wi_len = 2;
1233 if (le16toh(ltv->wi_val) == 1)
1234 p2ltv.wi_val = htole16(0x01);
1235 else if (le16toh(ltv->wi_val) == 2)
1236 p2ltv.wi_val = htole16(0x02);
1237 ltv = &p2ltv;
1238 break;
1239
1240 case WI_RID_ROAMING_MODE:
1241 if (sc->sc_firmware_type == WI_INTERSIL)
1242 break;
1243 /* not supported */
1244 return 0;
1245
1246 case WI_RID_MICROWAVE_OVEN:
1247 /* not supported */
1248 return 0;
1249 }
1250 }
1251
1252 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1253 return(EIO);
1254
1255 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1256 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1257
1258 /* Write data */
1259 ptr = <v->wi_val;
1260 if (ltv->wi_len > 1)
1261 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
1262
1263 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
1264 return(EIO);
1265
1266 return(0);
1267 }
1268
1269 static int wi_seek(sc, id, off, chan)
1270 struct wi_softc *sc;
1271 int id, off, chan;
1272 {
1273 int i;
1274 int selreg, offreg;
1275 int status;
1276
1277 switch (chan) {
1278 case WI_BAP0:
1279 selreg = WI_SEL0;
1280 offreg = WI_OFF0;
1281 break;
1282 case WI_BAP1:
1283 selreg = WI_SEL1;
1284 offreg = WI_OFF1;
1285 break;
1286 default:
1287 printf("%s: invalid data path: %x\n",
1288 sc->sc_dev.dv_xname, chan);
1289 return(EIO);
1290 }
1291
1292 CSR_WRITE_2(sc, selreg, id);
1293 CSR_WRITE_2(sc, offreg, off);
1294
1295 for (i = 0; i < WI_TIMEOUT; i++) {
1296 status = CSR_READ_2(sc, offreg);
1297 if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
1298 break;
1299 }
1300
1301 if (i == WI_TIMEOUT) {
1302 printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
1303 sc->sc_dev.dv_xname, id, off, status);
1304 return(ETIMEDOUT);
1305 }
1306 return(0);
1307 }
1308
1309 static int wi_read_data(sc, id, off, buf, len)
1310 struct wi_softc *sc;
1311 int id, off;
1312 caddr_t buf;
1313 int len;
1314 {
1315 u_int16_t *ptr;
1316
1317 if (wi_seek(sc, id, off, WI_BAP1))
1318 return(EIO);
1319
1320 ptr = (u_int16_t *)buf;
1321 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
1322
1323 return(0);
1324 }
1325
1326 /*
1327 * According to the comments in the HCF Light code, there is a bug in
1328 * the Hermes (or possibly in certain Hermes firmware revisions) where
1329 * the chip's internal autoincrement counter gets thrown off during
1330 * data writes: the autoincrement is missed, causing one data word to
1331 * be overwritten and subsequent words to be written to the wrong memory
1332 * locations. The end result is that we could end up transmitting bogus
1333 * frames without realizing it. The workaround for this is to write a
1334 * couple of extra guard words after the end of the transfer, then
1335 * attempt to read then back. If we fail to locate the guard words where
1336 * we expect them, we preform the transfer over again.
1337 */
1338 static int wi_write_data(sc, id, off, buf, len)
1339 struct wi_softc *sc;
1340 int id, off;
1341 caddr_t buf;
1342 int len;
1343 {
1344 u_int16_t *ptr;
1345
1346 #ifdef WI_HERMES_AUTOINC_WAR
1347 again:
1348 #endif
1349
1350 if (wi_seek(sc, id, off, WI_BAP0))
1351 return(EIO);
1352
1353 ptr = (u_int16_t *)buf;
1354 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
1355
1356 #ifdef WI_HERMES_AUTOINC_WAR
1357 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1358 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1359
1360 if (wi_seek(sc, id, off + len, WI_BAP0))
1361 return(EIO);
1362
1363 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1364 CSR_READ_2(sc, WI_DATA0) != 0x5678)
1365 goto again;
1366 #endif
1367
1368 return(0);
1369 }
1370
1371 /*
1372 * Allocate a region of memory inside the NIC and zero
1373 * it out.
1374 */
1375 static int wi_alloc_nicmem(sc, len, id)
1376 struct wi_softc *sc;
1377 int len;
1378 int *id;
1379 {
1380 int i;
1381
1382 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
1383 printf("%s: failed to allocate %d bytes on NIC\n",
1384 sc->sc_dev.dv_xname, len);
1385 return(ENOMEM);
1386 }
1387
1388 for (i = 0; i < WI_TIMEOUT; i++) {
1389 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1390 break;
1391 }
1392
1393 if (i == WI_TIMEOUT) {
1394 printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
1395 return(ETIMEDOUT);
1396 }
1397
1398 *id = CSR_READ_2(sc, WI_ALLOC_FID);
1399 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1400
1401 if (wi_seek(sc, *id, 0, WI_BAP0)) {
1402 printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
1403 return(EIO);
1404 }
1405
1406 for (i = 0; i < len / 2; i++)
1407 CSR_WRITE_2(sc, WI_DATA0, 0);
1408
1409 return(0);
1410 }
1411
1412 static void wi_setmulti(sc)
1413 struct wi_softc *sc;
1414 {
1415 struct ifnet *ifp;
1416 int i = 0;
1417 struct wi_ltv_mcast mcast;
1418 struct ether_multi *enm;
1419 struct ether_multistep estep;
1420 struct ethercom *ec = &sc->sc_ethercom;
1421
1422 ifp = &sc->sc_ethercom.ec_if;
1423
1424 if ((ifp->if_flags & IFF_PROMISC) != 0) {
1425 allmulti:
1426 ifp->if_flags |= IFF_ALLMULTI;
1427 memset((char *)&mcast, 0, sizeof(mcast));
1428 mcast.wi_type = WI_RID_MCAST_LIST;
1429 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
1430
1431 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1432 return;
1433 }
1434
1435 i = 0;
1436 ETHER_FIRST_MULTI(estep, ec, enm);
1437 while (enm != NULL) {
1438 /* Punt on ranges or too many multicast addresses. */
1439 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
1440 ETHER_ADDR_LEN) != 0 ||
1441 i >= 16)
1442 goto allmulti;
1443
1444 memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo,
1445 ETHER_ADDR_LEN);
1446 i++;
1447 ETHER_NEXT_MULTI(estep, enm);
1448 }
1449
1450 ifp->if_flags &= ~IFF_ALLMULTI;
1451 mcast.wi_type = WI_RID_MCAST_LIST;
1452 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
1453 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1454 }
1455
1456 static int
1457 wi_setdef(sc, wreq)
1458 struct wi_softc *sc;
1459 struct wi_req *wreq;
1460 {
1461 struct sockaddr_dl *sdl;
1462 struct ifnet *ifp;
1463 int error = 0;
1464
1465 ifp = &sc->sc_ethercom.ec_if;
1466
1467 switch(wreq->wi_type) {
1468 case WI_RID_MAC_NODE:
1469 sdl = (struct sockaddr_dl *)ifp->if_sadl;
1470 memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val,
1471 ETHER_ADDR_LEN);
1472 memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN);
1473 break;
1474 case WI_RID_PORTTYPE:
1475 error = wi_sync_media(sc, le16toh(wreq->wi_val[0]),
1476 sc->wi_tx_rate);
1477 break;
1478 case WI_RID_TX_RATE:
1479 error = wi_sync_media(sc, sc->wi_ptype,
1480 le16toh(wreq->wi_val[0]));
1481 break;
1482 case WI_RID_MAX_DATALEN:
1483 sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
1484 break;
1485 case WI_RID_RTS_THRESH:
1486 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
1487 break;
1488 case WI_RID_SYSTEM_SCALE:
1489 sc->wi_ap_density = le16toh(wreq->wi_val[0]);
1490 break;
1491 case WI_RID_CREATE_IBSS:
1492 sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
1493 error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
1494 break;
1495 case WI_RID_OWN_CHNL:
1496 sc->wi_channel = le16toh(wreq->wi_val[0]);
1497 break;
1498 case WI_RID_NODENAME:
1499 error = wi_set_ssid(&sc->wi_nodeid,
1500 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1501 break;
1502 case WI_RID_DESIRED_SSID:
1503 error = wi_set_ssid(&sc->wi_netid,
1504 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1505 break;
1506 case WI_RID_OWN_SSID:
1507 error = wi_set_ssid(&sc->wi_ibssid,
1508 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1509 break;
1510 case WI_RID_PM_ENABLED:
1511 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
1512 break;
1513 case WI_RID_MICROWAVE_OVEN:
1514 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
1515 break;
1516 case WI_RID_MAX_SLEEP:
1517 sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
1518 break;
1519 case WI_RID_CNFAUTHMODE:
1520 sc->wi_authtype = le16toh(wreq->wi_val[0]);
1521 break;
1522 case WI_RID_ROAMING_MODE:
1523 sc->wi_roaming = le16toh(wreq->wi_val[0]);
1524 break;
1525 case WI_RID_ENCRYPTION:
1526 sc->wi_use_wep = le16toh(wreq->wi_val[0]);
1527 break;
1528 case WI_RID_TX_CRYPT_KEY:
1529 sc->wi_tx_key = le16toh(wreq->wi_val[0]);
1530 break;
1531 case WI_RID_DEFLT_CRYPT_KEYS:
1532 memcpy((char *)&sc->wi_keys, (char *)wreq,
1533 sizeof(struct wi_ltv_keys));
1534 break;
1535 default:
1536 error = EINVAL;
1537 break;
1538 }
1539
1540 return (error);
1541 }
1542
1543 static int
1544 wi_getdef(sc, wreq)
1545 struct wi_softc *sc;
1546 struct wi_req *wreq;
1547 {
1548 struct sockaddr_dl *sdl;
1549 struct ifnet *ifp;
1550 int error = 0;
1551
1552 ifp = &sc->sc_ethercom.ec_if;
1553
1554 wreq->wi_len = 2; /* XXX */
1555 switch (wreq->wi_type) {
1556 case WI_RID_MAC_NODE:
1557 wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
1558 sdl = (struct sockaddr_dl *)ifp->if_sadl;
1559 memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN);
1560 memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
1561 break;
1562 case WI_RID_PORTTYPE:
1563 wreq->wi_val[0] = htole16(sc->wi_ptype);
1564 break;
1565 case WI_RID_TX_RATE:
1566 wreq->wi_val[0] = htole16(sc->wi_tx_rate);
1567 break;
1568 case WI_RID_MAX_DATALEN:
1569 wreq->wi_val[0] = htole16(sc->wi_max_data_len);
1570 break;
1571 case WI_RID_RTS_THRESH:
1572 wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
1573 break;
1574 case WI_RID_SYSTEM_SCALE:
1575 wreq->wi_val[0] = htole16(sc->wi_ap_density);
1576 break;
1577 case WI_RID_CREATE_IBSS:
1578 wreq->wi_val[0] = htole16(sc->wi_create_ibss);
1579 break;
1580 case WI_RID_OWN_CHNL:
1581 wreq->wi_val[0] = htole16(sc->wi_channel);
1582 break;
1583 case WI_RID_NODENAME:
1584 wi_request_fill_ssid(wreq, &sc->wi_nodeid);
1585 break;
1586 case WI_RID_DESIRED_SSID:
1587 wi_request_fill_ssid(wreq, &sc->wi_netid);
1588 break;
1589 case WI_RID_OWN_SSID:
1590 wi_request_fill_ssid(wreq, &sc->wi_ibssid);
1591 break;
1592 case WI_RID_PM_ENABLED:
1593 wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
1594 break;
1595 case WI_RID_MICROWAVE_OVEN:
1596 wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
1597 break;
1598 case WI_RID_MAX_SLEEP:
1599 wreq->wi_val[0] = htole16(sc->wi_max_sleep);
1600 break;
1601 case WI_RID_CNFAUTHMODE:
1602 wreq->wi_val[0] = htole16(sc->wi_authtype);
1603 break;
1604 case WI_RID_ROAMING_MODE:
1605 wreq->wi_val[0] = htole16(sc->wi_roaming);
1606 break;
1607 case WI_RID_WEP_AVAIL:
1608 wreq->wi_val[0] = (sc->wi_flags & WI_FLAGS_HAS_WEP) ?
1609 htole16(1) : htole16(0);
1610 break;
1611 case WI_RID_ENCRYPTION:
1612 wreq->wi_val[0] = htole16(sc->wi_use_wep);
1613 break;
1614 case WI_RID_TX_CRYPT_KEY:
1615 wreq->wi_val[0] = htole16(sc->wi_tx_key);
1616 break;
1617 case WI_RID_DEFLT_CRYPT_KEYS:
1618 wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
1619 memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
1620 break;
1621 default:
1622 #if 0
1623 error = EIO;
1624 #else
1625 #ifdef WI_DEBUG
1626 printf("%s: wi_getdef: unknown request %d\n",
1627 sc->sc_dev.dv_xname, wreq->wi_type);
1628 #endif
1629 #endif
1630 break;
1631 }
1632
1633 return (error);
1634 }
1635
1636 static int
1637 wi_ioctl(ifp, command, data)
1638 struct ifnet *ifp;
1639 u_long command;
1640 caddr_t data;
1641 {
1642 int s, error = 0;
1643 int len;
1644 struct wi_softc *sc = ifp->if_softc;
1645 struct wi_req wreq;
1646 struct ifreq *ifr;
1647 struct proc *p = curproc;
1648 struct ieee80211_nwid nwid;
1649
1650 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
1651 return (ENXIO);
1652
1653 s = splnet();
1654
1655 ifr = (struct ifreq *)data;
1656 switch (command) {
1657 case SIOCSIFADDR:
1658 case SIOCGIFADDR:
1659 case SIOCSIFMTU:
1660 error = ether_ioctl(ifp, command, data);
1661 break;
1662 case SIOCSIFFLAGS:
1663 if (ifp->if_flags & IFF_UP) {
1664 if (ifp->if_flags & IFF_RUNNING &&
1665 ifp->if_flags & IFF_PROMISC &&
1666 !(sc->wi_if_flags & IFF_PROMISC)) {
1667 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1668 WI_SETVAL(WI_RID_PROMISC, 1);
1669 } else if (ifp->if_flags & IFF_RUNNING &&
1670 !(ifp->if_flags & IFF_PROMISC) &&
1671 sc->wi_if_flags & IFF_PROMISC) {
1672 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1673 WI_SETVAL(WI_RID_PROMISC, 0);
1674 } else
1675 wi_init(ifp);
1676 } else if (ifp->if_flags & IFF_RUNNING)
1677 wi_stop(ifp, 0);
1678 sc->wi_if_flags = ifp->if_flags;
1679
1680 if (!(ifp->if_flags & IFF_UP)) {
1681 if (sc->sc_enabled) {
1682 if (sc->sc_disable)
1683 (*sc->sc_disable)(sc);
1684 sc->sc_enabled = 0;
1685 ifp->if_flags &= ~IFF_RUNNING;
1686 }
1687 }
1688 error = 0;
1689 break;
1690 case SIOCADDMULTI:
1691 case SIOCDELMULTI:
1692 error = (command == SIOCADDMULTI) ?
1693 ether_addmulti(ifr, &sc->sc_ethercom) :
1694 ether_delmulti(ifr, &sc->sc_ethercom);
1695 if (error == ENETRESET) {
1696 if (sc->sc_enabled != 0) {
1697 /*
1698 * Multicast list has changed. Set the
1699 * hardware filter accordingly.
1700 */
1701 wi_setmulti(sc);
1702 }
1703 error = 0;
1704 }
1705 break;
1706 case SIOCSIFMEDIA:
1707 case SIOCGIFMEDIA:
1708 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1709 break;
1710 case SIOCGWAVELAN:
1711 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1712 if (error)
1713 break;
1714 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1715 memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
1716 sizeof(sc->wi_stats));
1717 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1718 } else if (wreq.wi_type == WI_RID_READ_APS) {
1719 if (sc->wi_scanning) {
1720 error = EINPROGRESS;
1721 break;
1722 } else {
1723 len = sc->wi_naps * sizeof(struct wi_apinfo);
1724 len = len > WI_MAX_DATALEN ? WI_MAX_DATALEN : len;
1725 len = len / sizeof(struct wi_apinfo);
1726 memcpy((char *)&wreq.wi_val, (char *)&len, sizeof(len));
1727 memcpy((char *)&wreq.wi_val + sizeof(len),
1728 (char *)&sc->wi_aps,
1729 len * sizeof(struct wi_apinfo));
1730 }
1731 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
1732 /* For non-root user, return all-zeroes keys */
1733 if (suser(p->p_ucred, &p->p_acflag))
1734 memset((char *)&wreq, 0,
1735 sizeof(struct wi_ltv_keys));
1736 else
1737 memcpy((char *)&wreq, (char *)&sc->wi_keys,
1738 sizeof(struct wi_ltv_keys));
1739 } else {
1740 if (sc->sc_enabled == 0)
1741 error = wi_getdef(sc, &wreq);
1742 else if (wreq.wi_len > WI_MAX_DATALEN)
1743 error = EINVAL;
1744 else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
1745 error = EINVAL;
1746 }
1747 if (error == 0)
1748 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1749 break;
1750 case SIOCSWAVELAN:
1751 error = suser(p->p_ucred, &p->p_acflag);
1752 if (error)
1753 break;
1754 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1755 if (error)
1756 break;
1757 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1758 if (sc->sc_enabled)
1759 wi_inquire(sc);
1760 break;
1761 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1762 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1763 wreq.wi_len);
1764 } else if (wreq.wi_type == WI_RID_SCAN_APS) {
1765 if (wreq.wi_len != 4) {
1766 error = EINVAL;
1767 break;
1768 }
1769 if (!sc->wi_scanning) {
1770 switch (sc->sc_firmware_type) {
1771 case WI_LUCENT:
1772 break;
1773 case WI_INTERSIL:
1774 wreq.wi_type = WI_RID_SCAN_REQ;
1775 error = wi_write_record(sc,
1776 (struct wi_ltv_gen *)&wreq);
1777 break;
1778 case WI_SYMBOL:
1779 /*
1780 * XXX only supported on 3.x ?
1781 */
1782 wreq.wi_type = WI_RID_BCAST_SCAN_REQ;
1783 wreq.wi_val[0] =
1784 BSCAN_BCAST | BSCAN_ONETIME;
1785 wreq.wi_len = 2;
1786 error = wi_write_record(sc,
1787 (struct wi_ltv_gen *)&wreq);
1788 break;
1789 }
1790 if (!error) {
1791 sc->wi_scanning = 1;
1792 callout_reset(&sc->wi_scan_sh, hz * 1,
1793 wi_wait_scan, sc);
1794 }
1795 }
1796 } else {
1797 /*
1798 * Filter stuff out based on what the
1799 * card can do.
1800 */
1801 if ((wreq.wi_type == WI_RID_ROAMING_MODE &&
1802 (sc->wi_flags & WI_FLAGS_HAS_ROAMING) == 0) ||
1803 (wreq.wi_type == WI_RID_CREATE_IBSS &&
1804 (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0) ||
1805 (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
1806 (sc->wi_flags & WI_FLAGS_HAS_MOR) == 0))
1807 break;
1808
1809 if (wreq.wi_len > WI_MAX_DATALEN)
1810 error = EINVAL;
1811 else if (sc->sc_enabled != 0)
1812 error = wi_write_record(sc,
1813 (struct wi_ltv_gen *)&wreq);
1814 if (error == 0)
1815 error = wi_setdef(sc, &wreq);
1816 if (error == 0 && sc->sc_enabled != 0)
1817 /* Reinitialize WaveLAN. */
1818 wi_init(ifp);
1819 }
1820 break;
1821 case SIOCG80211NWID:
1822 if (sc->sc_enabled == 0) {
1823 /* Return the desired ID */
1824 error = copyout(&sc->wi_netid, ifr->ifr_data,
1825 sizeof(sc->wi_netid));
1826 } else {
1827 wreq.wi_type = WI_RID_CURRENT_SSID;
1828 wreq.wi_len = WI_MAX_DATALEN;
1829 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
1830 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
1831 error = EINVAL;
1832 else {
1833 wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
1834 le16toh(wreq.wi_val[0]));
1835 error = copyout(&nwid, ifr->ifr_data,
1836 sizeof(nwid));
1837 }
1838 }
1839 break;
1840 case SIOCS80211NWID:
1841 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
1842 if (error != 0)
1843 break;
1844 if (nwid.i_len > IEEE80211_NWID_LEN) {
1845 error = EINVAL;
1846 break;
1847 }
1848 if (sc->wi_netid.i_len == nwid.i_len &&
1849 memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
1850 break;
1851 wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
1852 if (sc->sc_enabled != 0)
1853 /* Reinitialize WaveLAN. */
1854 wi_init(ifp);
1855 break;
1856 case SIOCS80211NWKEY:
1857 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1858 break;
1859 case SIOCG80211NWKEY:
1860 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1861 break;
1862 case SIOCS80211POWER:
1863 error = wi_set_pm(sc, (struct ieee80211_power *)data);
1864 break;
1865 case SIOCG80211POWER:
1866 error = wi_get_pm(sc, (struct ieee80211_power *)data);
1867 break;
1868 case SIOCHOSTAP_ADD:
1869 case SIOCHOSTAP_DEL:
1870 case SIOCHOSTAP_GET:
1871 case SIOCHOSTAP_GETALL:
1872 case SIOCHOSTAP_GFLAGS:
1873 case SIOCHOSTAP_SFLAGS:
1874 /* Send all Host-AP specific ioctls to the Host-AP code. */
1875 error = wihap_ioctl(sc, command, data);
1876 break;
1877
1878 default:
1879 error = EINVAL;
1880 break;
1881 }
1882
1883 splx(s);
1884 return (error);
1885 }
1886
1887 static int
1888 wi_init(ifp)
1889 struct ifnet *ifp;
1890 {
1891 struct wi_softc *sc = ifp->if_softc;
1892 struct wi_req wreq;
1893 struct wi_ltv_macaddr mac;
1894 int error, id = 0, wasenabled;
1895
1896 wasenabled = sc->sc_enabled;
1897 if (!sc->sc_enabled) {
1898 if ((error = (*sc->sc_enable)(sc)) != 0)
1899 goto out;
1900 sc->sc_enabled = 1;
1901 }
1902
1903 wi_stop(ifp, 0);
1904 /* Symbol firmware cannot be initialized more than once */
1905 if (!(sc->sc_firmware_type == WI_SYMBOL && wasenabled))
1906 wi_reset(sc);
1907
1908 /* Program max data length. */
1909 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1910
1911 /* Enable/disable IBSS creation. */
1912 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1913
1914 /* Set the port type. */
1915 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1916
1917 /* Program the RTS/CTS threshold. */
1918 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1919
1920 /* Program the TX rate */
1921 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1922
1923 /* Access point density */
1924 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1925
1926 /* Power Management Enabled */
1927 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1928
1929 /* Power Managment Max Sleep */
1930 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1931
1932 /* Roaming type */
1933 if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
1934 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
1935
1936 /* Specify the network name */
1937 wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
1938
1939 /* Specify the IBSS name */
1940 if (sc->wi_netid.i_len != 0 &&
1941 (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
1942 (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
1943 wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_netid);
1944 else
1945 wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
1946
1947 /* Specify the frequency to use */
1948 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1949
1950 /* Program the nodename. */
1951 wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
1952
1953 /* Set our MAC address. */
1954 mac.wi_len = 4;
1955 mac.wi_type = WI_RID_MAC_NODE;
1956 memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
1957 wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1958
1959 /*
1960 * Initialize promisc mode.
1961 * Being in the Host-AP mode causes a great
1962 * deal of pain if primisc mode is set.
1963 * Therefore we avoid confusing the firmware
1964 * and always reset promisc mode in Host-AP
1965 * mode. Host-AP sees all the packets anyway.
1966 */
1967 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP &&
1968 (ifp->if_flags & IFF_PROMISC) != 0) {
1969 WI_SETVAL(WI_RID_PROMISC, 1);
1970 } else {
1971 WI_SETVAL(WI_RID_PROMISC, 0);
1972 }
1973
1974 /* Configure WEP. */
1975 if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
1976 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1977 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1978 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1979 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1980 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1981 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
1982 /*
1983 * ONLY HWB3163 EVAL-CARD Firmware version
1984 * less than 0.8 variant2
1985 *
1986 * If promiscuous mode disable, Prism2 chip
1987 * does not work with WEP .
1988 * It is under investigation for details.
1989 * (ichiro (at) netbsd.org)
1990 */
1991 if (sc->sc_firmware_type == WI_INTERSIL &&
1992 sc->sc_sta_firmware_ver < 802 ) {
1993 /* firm ver < 0.8 variant 2 */
1994 WI_SETVAL(WI_RID_PROMISC, 1);
1995 }
1996 WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
1997 }
1998 }
1999
2000 /* Set multicast filter. */
2001 wi_setmulti(sc);
2002
2003 /* Enable desired port */
2004 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
2005
2006 /* scanning variable is modal, therefore reinit to OFF, in case it was on. */
2007 sc->wi_scanning=0;
2008 sc->wi_naps=0;
2009
2010 if ((error = wi_alloc_nicmem(sc,
2011 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
2012 printf("%s: tx buffer allocation failed\n",
2013 sc->sc_dev.dv_xname);
2014 goto out;
2015 }
2016 sc->wi_tx_data_id = id;
2017
2018 if ((error = wi_alloc_nicmem(sc,
2019 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
2020 printf("%s: mgmt. buffer allocation failed\n",
2021 sc->sc_dev.dv_xname);
2022 goto out;
2023 }
2024 sc->wi_tx_mgmt_id = id;
2025
2026 /* Enable interrupts */
2027 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
2028
2029 wihap_init(sc);
2030
2031 ifp->if_flags |= IFF_RUNNING;
2032 ifp->if_flags &= ~IFF_OACTIVE;
2033
2034 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
2035
2036 out:
2037 if (error) {
2038 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
2039 ifp->if_timer = 0;
2040 printf("%s: interface not running\n", sc->sc_dev.dv_xname);
2041 }
2042 return (error);
2043 }
2044
2045 static const u_int32_t crc32_tab[] = {
2046 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
2047 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
2048 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
2049 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2050 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
2051 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
2052 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
2053 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2054 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
2055 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
2056 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
2057 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2058 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
2059 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
2060 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
2061 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2062 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
2063 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
2064 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
2065 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2066 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
2067 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
2068 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
2069 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2070 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
2071 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
2072 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
2073 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2074 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
2075 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
2076 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
2077 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2078 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
2079 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
2080 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
2081 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2082 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
2083 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
2084 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
2085 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2086 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
2087 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
2088 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
2089 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2090 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
2091 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
2092 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
2093 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2094 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
2095 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
2096 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
2097 0x2d02ef8dL
2098 };
2099
2100 #define RC4STATE 256
2101 #define RC4KEYLEN 16
2102 #define RC4SWAP(x,y) \
2103 do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0)
2104
2105 static void
2106 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2107 {
2108 u_int32_t i, crc, klen;
2109 u_int8_t state[RC4STATE], key[RC4KEYLEN];
2110 u_int8_t x, y, *dat;
2111
2112 if (!sc->wi_icv_flag) {
2113 sc->wi_icv = arc4random();
2114 sc->wi_icv_flag++;
2115 } else
2116 sc->wi_icv++;
2117 /*
2118 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2119 * (B, 255, N) with 3 <= B < 8
2120 */
2121 if (sc->wi_icv >= 0x03ff00 &&
2122 (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2123 sc->wi_icv += 0x000100;
2124
2125 /* prepend 24bit IV to tx key, byte order does not matter */
2126 key[0] = sc->wi_icv >> 16;
2127 key[1] = sc->wi_icv >> 8;
2128 key[2] = sc->wi_icv;
2129
2130 klen = le16toh(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen) +
2131 IEEE80211_WEP_IVLEN;
2132 klen = (klen >= RC4KEYLEN) ? RC4KEYLEN : RC4KEYLEN/2;
2133 bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2134 (char *)key + IEEE80211_WEP_IVLEN, klen - IEEE80211_WEP_IVLEN);
2135
2136 /* rc4 keysetup */
2137 x = y = 0;
2138 for (i = 0; i < RC4STATE; i++)
2139 state[i] = i;
2140 for (i = 0; i < RC4STATE; i++) {
2141 y = (key[x] + state[i] + y) % RC4STATE;
2142 RC4SWAP(i, y);
2143 x = (x + 1) % klen;
2144 }
2145
2146 /* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
2147 dat = buf;
2148 dat[0] = key[0];
2149 dat[1] = key[1];
2150 dat[2] = key[2];
2151 dat[3] = sc->wi_tx_key << 6; /* pad and keyid */
2152 dat += 4;
2153
2154 /* compute rc4 over data, crc32 over data */
2155 crc = ~0;
2156 x = y = 0;
2157 for (i = 0; i < len; i++) {
2158 x = (x + 1) % RC4STATE;
2159 y = (state[x] + y) % RC4STATE;
2160 RC4SWAP(x, y);
2161 crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2162 dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
2163 }
2164 crc = ~crc;
2165 dat += len;
2166
2167 /* append little-endian crc32 and encrypt */
2168 dat[0] = crc;
2169 dat[1] = crc >> 8;
2170 dat[2] = crc >> 16;
2171 dat[3] = crc >> 24;
2172 for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) {
2173 x = (x + 1) % RC4STATE;
2174 y = (state[x] + y) % RC4STATE;
2175 RC4SWAP(x, y);
2176 dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
2177 }
2178 }
2179
2180 static void
2181 wi_start(ifp)
2182 struct ifnet *ifp;
2183 {
2184 struct wi_softc *sc;
2185 struct mbuf *m0;
2186 struct wi_frame tx_frame;
2187 struct ether_header *eh;
2188 int id;
2189
2190 sc = ifp->if_softc;
2191
2192 if (ifp->if_flags & IFF_OACTIVE)
2193 return;
2194
2195 nextpkt:
2196 IFQ_DEQUEUE(&ifp->if_snd, m0);
2197 if (m0 == NULL)
2198 return;
2199
2200 memset((char *)&tx_frame, 0, sizeof(tx_frame));
2201 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
2202 id = sc->wi_tx_data_id;
2203 eh = mtod(m0, struct ether_header *);
2204
2205 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2206 if (wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
2207 &tx_frame.wi_tx_rate) == 0 &&
2208 (ifp->if_flags & IFF_PROMISC) == 0) {
2209 if (ifp->if_flags & IFF_DEBUG)
2210 printf("%s: Host-AP: dropping unassoc "
2211 "dst %s\n", sc->sc_dev.dv_xname,
2212 ether_sprintf(eh->ether_dhost));
2213 m_freem(m0);
2214 goto nextpkt;
2215 }
2216 }
2217
2218 /*
2219 * Use RFC1042 encoding for IP and ARP datagrams,
2220 * 802.3 for anything else.
2221 */
2222 if (eh->ether_type == htons(ETHERTYPE_IP) ||
2223 eh->ether_type == htons(ETHERTYPE_ARP) ||
2224 eh->ether_type == htons(ETHERTYPE_REVARP) ||
2225 eh->ether_type == htons(ETHERTYPE_IPV6)) {
2226 memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost,
2227 ETHER_ADDR_LEN);
2228 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2229 tx_frame.wi_tx_ctl |= htole16(WI_ENC_TX_MGMT);/* XXX */
2230 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
2231 if (sc->wi_use_wep)
2232 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
2233 memcpy((char *)&tx_frame.wi_addr2,
2234 (char *)LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
2235 memcpy((char *)&tx_frame.wi_addr3,
2236 (char *)&eh->ether_shost, ETHER_ADDR_LEN);
2237 } else
2238 memcpy((char *)&tx_frame.wi_addr2,
2239 (char *)&eh->ether_shost, ETHER_ADDR_LEN);
2240 memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost,
2241 ETHER_ADDR_LEN);
2242 memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost,
2243 ETHER_ADDR_LEN);
2244
2245 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
2246 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
2247 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
2248 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
2249 tx_frame.wi_type = eh->ether_type;
2250
2251 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
2252 /* Do host encryption. */
2253 memcpy(&sc->wi_txbuf[4], &tx_frame.wi_dat[0], 8);
2254
2255 m_copydata(m0, sizeof(struct ether_header),
2256 m0->m_pkthdr.len - sizeof(struct ether_header),
2257 (caddr_t)&sc->wi_txbuf[12]);
2258
2259 wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
2260 tx_frame.wi_dat_len);
2261
2262 tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
2263 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2264
2265 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2266
2267 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2268 sizeof(struct wi_frame));
2269 wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
2270 (caddr_t)&sc->wi_txbuf,
2271 (m0->m_pkthdr.len -
2272 sizeof(struct ether_header)) + 18);
2273 } else {
2274 m_copydata(m0, sizeof(struct ether_header),
2275 m0->m_pkthdr.len - sizeof(struct ether_header),
2276 (caddr_t)&sc->wi_txbuf);
2277
2278 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2279
2280 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2281 sizeof(struct wi_frame));
2282 wi_write_data(sc, id, WI_802_11_OFFSET,
2283 (caddr_t)&sc->wi_txbuf,
2284 (m0->m_pkthdr.len -
2285 sizeof(struct ether_header)) + 2);
2286 }
2287 } else {
2288 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
2289
2290 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
2291 /* Do host encryption. (XXX - not implemented) */
2292 printf("%s: host encryption not implemented "
2293 "for 802.3\n", sc->sc_dev.dv_xname);
2294 } else {
2295 m_copydata(m0, 0, m0->m_pkthdr.len,
2296 (caddr_t)&sc->wi_txbuf);
2297
2298 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2299 sizeof(struct wi_frame));
2300 wi_write_data(sc, id, WI_802_3_OFFSET,
2301 (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
2302 }
2303 }
2304
2305 #if NBPFILTER > 0
2306 /*
2307 * If there's a BPF listener, bounce a copy of
2308 * this frame to him.
2309 */
2310 if (ifp->if_bpf)
2311 bpf_mtap(ifp->if_bpf, m0);
2312 #endif
2313
2314 m_freem(m0);
2315
2316 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
2317 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
2318
2319 ifp->if_flags |= IFF_OACTIVE;
2320
2321 /*
2322 * Set a timeout in case the chip goes out to lunch.
2323 */
2324 ifp->if_timer = 5;
2325
2326 return;
2327 }
2328
2329 int
2330 wi_mgmt_xmit(sc, data, len)
2331 struct wi_softc *sc;
2332 caddr_t data;
2333 int len;
2334 {
2335 struct wi_frame tx_frame;
2336 int id;
2337 struct wi_80211_hdr *hdr;
2338 caddr_t dptr;
2339
2340 hdr = (struct wi_80211_hdr *)data;
2341 dptr = data + sizeof(struct wi_80211_hdr);
2342
2343 memset((char *)&tx_frame, 0, sizeof(tx_frame));
2344 id = sc->wi_tx_mgmt_id;
2345
2346 memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr,
2347 sizeof(struct wi_80211_hdr));
2348
2349 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
2350 tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2351 tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
2352
2353 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2354
2355 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2356 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2357 (len - sizeof(struct wi_80211_hdr)) + 2);
2358
2359 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
2360 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
2361 return(EIO);
2362 }
2363
2364 return(0);
2365 }
2366
2367 static void
2368 wi_stop(ifp, disable)
2369 struct ifnet *ifp;
2370 {
2371 struct wi_softc *sc = ifp->if_softc;
2372
2373 wihap_shutdown(sc);
2374
2375 CSR_WRITE_2(sc, WI_INT_EN, 0);
2376 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
2377
2378 callout_stop(&sc->wi_inquire_ch);
2379 callout_stop(&sc->wi_scan_sh);
2380
2381 if (disable) {
2382 if (sc->sc_enabled) {
2383 if (sc->sc_disable)
2384 (*sc->sc_disable)(sc);
2385 sc->sc_enabled = 0;
2386 }
2387 }
2388
2389 ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
2390 ifp->if_timer = 0;
2391 }
2392
2393 static void
2394 wi_watchdog(ifp)
2395 struct ifnet *ifp;
2396 {
2397 struct wi_softc *sc;
2398
2399 sc = ifp->if_softc;
2400
2401 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
2402
2403 wi_init(ifp);
2404
2405 ifp->if_oerrors++;
2406
2407 return;
2408 }
2409
2410 void
2411 wi_shutdown(sc)
2412 struct wi_softc *sc;
2413 {
2414 int s;
2415
2416 s = splnet();
2417 if (sc->sc_enabled) {
2418 if (sc->sc_disable)
2419 (*sc->sc_disable)(sc);
2420 sc->sc_enabled = 0;
2421 }
2422 splx(s);
2423 }
2424
2425 int
2426 wi_activate(self, act)
2427 struct device *self;
2428 enum devact act;
2429 {
2430 struct wi_softc *sc = (struct wi_softc *)self;
2431 int rv = 0, s;
2432
2433 s = splnet();
2434 switch (act) {
2435 case DVACT_ACTIVATE:
2436 rv = EOPNOTSUPP;
2437 break;
2438
2439 case DVACT_DEACTIVATE:
2440 if_deactivate(&sc->sc_ethercom.ec_if);
2441 break;
2442 }
2443 splx(s);
2444 return (rv);
2445 }
2446
2447 static void
2448 wi_get_id(sc)
2449 struct wi_softc *sc;
2450 {
2451 struct wi_ltv_ver ver;
2452 struct wi_card_ident *id;
2453
2454 /* getting chip identity */
2455 memset(&ver, 0, sizeof(ver));
2456 ver.wi_type = WI_RID_CARD_ID;
2457 ver.wi_len = 5;
2458 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2459 printf("%s: using ", sc->sc_dev.dv_xname);
2460
2461 sc->sc_firmware_type = WI_NOTYPE;
2462 for (id = wi_card_ident; id->card_name != NULL; id++) {
2463 if (le16toh(ver.wi_ver[0]) == id->card_id) {
2464 printf("%s", id->card_name);
2465 sc->sc_firmware_type = id->firm_type;
2466 break;
2467 }
2468 }
2469 if (sc->sc_firmware_type == WI_NOTYPE) {
2470 if (le16toh(ver.wi_ver[0]) & 0x8000) {
2471 printf("Unknown PRISM2 chip");
2472 sc->sc_firmware_type = WI_INTERSIL;
2473 } else {
2474 printf("Unknown Lucent chip");
2475 sc->sc_firmware_type = WI_LUCENT;
2476 }
2477 }
2478
2479 /* get primary firmware version (Only Prism chips) */
2480 if (sc->sc_firmware_type != WI_LUCENT) {
2481 memset(&ver, 0, sizeof(ver));
2482 ver.wi_type = WI_RID_PRI_IDENTITY;
2483 ver.wi_len = 5;
2484 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2485 LE16TOH(ver.wi_ver[1]);
2486 LE16TOH(ver.wi_ver[2]);
2487 LE16TOH(ver.wi_ver[3]);
2488 sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
2489 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2490 }
2491
2492 /* get station firmware version */
2493 memset(&ver, 0, sizeof(ver));
2494 ver.wi_type = WI_RID_STA_IDENTITY;
2495 ver.wi_len = 5;
2496 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2497 LE16TOH(ver.wi_ver[1]);
2498 LE16TOH(ver.wi_ver[2]);
2499 LE16TOH(ver.wi_ver[3]);
2500 sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2501 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2502 if (sc->sc_firmware_type == WI_INTERSIL &&
2503 (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2504 struct wi_ltv_str sver;
2505 char *p;
2506
2507 memset(&sver, 0, sizeof(sver));
2508 sver.wi_type = WI_RID_SYMBOL_IDENTITY;
2509 sver.wi_len = 7;
2510 /* value should be the format like "V2.00-11" */
2511 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2512 *(p = (char *)sver.wi_str) >= 'A' &&
2513 p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2514 sc->sc_firmware_type = WI_SYMBOL;
2515 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2516 (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2517 (p[6] - '0') * 10 + (p[7] - '0');
2518 }
2519 }
2520
2521 printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
2522 sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
2523 (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
2524 if (sc->sc_firmware_type != WI_LUCENT) /* XXX */
2525 printf("Primary (%u.%u.%u), ", sc->sc_pri_firmware_ver / 10000,
2526 (sc->sc_pri_firmware_ver % 10000) / 100,
2527 sc->sc_pri_firmware_ver % 100);
2528 printf("Station (%u.%u.%u)\n",
2529 sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
2530 sc->sc_sta_firmware_ver % 100);
2531
2532 return;
2533 }
2534
2535 int
2536 wi_detach(sc)
2537 struct wi_softc *sc;
2538 {
2539 struct ifnet *ifp = sc->sc_ifp;
2540 int s;
2541
2542 if (!sc->sc_attached)
2543 return (0);
2544
2545 s = splnet();
2546 callout_stop(&sc->wi_inquire_ch);
2547
2548 /* Delete all remaining media. */
2549 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
2550
2551 ether_ifdetach(ifp);
2552 if_detach(ifp);
2553 if (sc->sc_enabled) {
2554 if (sc->sc_disable)
2555 (*sc->sc_disable)(sc);
2556 sc->sc_enabled = 0;
2557 }
2558 splx(s);
2559 return (0);
2560 }
2561
2562 void
2563 wi_power(sc, why)
2564 struct wi_softc *sc;
2565 int why;
2566 {
2567 int s;
2568
2569 if (!sc->sc_enabled)
2570 return;
2571
2572 s = splnet();
2573 switch (why) {
2574 case PWR_SUSPEND:
2575 case PWR_STANDBY:
2576 wi_stop(sc->sc_ifp, 0);
2577 if (sc->sc_enabled) {
2578 if (sc->sc_disable)
2579 (*sc->sc_disable)(sc);
2580 }
2581 break;
2582 case PWR_RESUME:
2583 sc->sc_enabled = 0;
2584 wi_init(sc->sc_ifp);
2585 (void)wi_intr(sc);
2586 break;
2587 case PWR_SOFTSUSPEND:
2588 case PWR_SOFTSTANDBY:
2589 case PWR_SOFTRESUME:
2590 break;
2591 }
2592 splx(s);
2593 }
2594
2595 static int
2596 wi_set_ssid(ws, id, len)
2597 struct ieee80211_nwid *ws;
2598 u_int8_t *id;
2599 int len;
2600 {
2601
2602 if (len > IEEE80211_NWID_LEN)
2603 return (EINVAL);
2604 ws->i_len = len;
2605 memcpy(ws->i_nwid, id, len);
2606 return (0);
2607 }
2608
2609 static void
2610 wi_request_fill_ssid(wreq, ws)
2611 struct wi_req *wreq;
2612 struct ieee80211_nwid *ws;
2613 {
2614 int len = ws->i_len;
2615
2616 memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
2617 wreq->wi_val[0] = htole16(len);
2618 wreq->wi_len = roundup(len, 2) / 2 + 2;
2619 memcpy(&wreq->wi_val[1], ws->i_nwid, len);
2620 }
2621
2622 static int
2623 wi_write_ssid(sc, type, wreq, ws)
2624 struct wi_softc *sc;
2625 int type;
2626 struct wi_req *wreq;
2627 struct ieee80211_nwid *ws;
2628 {
2629
2630 wreq->wi_type = type;
2631 wi_request_fill_ssid(wreq, ws);
2632 return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
2633 }
2634
2635 static int
2636 wi_sync_media(sc, ptype, txrate)
2637 struct wi_softc *sc;
2638 int ptype;
2639 int txrate;
2640 {
2641 int media = sc->sc_media.ifm_cur->ifm_media;
2642 int options = IFM_OPTIONS(media);
2643 int subtype;
2644
2645 switch (txrate) {
2646 case 1:
2647 subtype = IFM_IEEE80211_DS1;
2648 break;
2649 case 2:
2650 subtype = IFM_IEEE80211_DS2;
2651 break;
2652 case 3:
2653 subtype = IFM_AUTO;
2654 break;
2655 case 5:
2656 subtype = IFM_IEEE80211_DS5;
2657 break;
2658 case 11:
2659 subtype = IFM_IEEE80211_DS11;
2660 break;
2661 default:
2662 subtype = IFM_MANUAL; /* Unable to represent */
2663 break;
2664 }
2665
2666 options &= ~IFM_OMASK;
2667 switch (ptype) {
2668 case WI_PORTTYPE_BSS:
2669 /* default port type */
2670 break;
2671 case WI_PORTTYPE_ADHOC:
2672 options |= IFM_IEEE80211_ADHOC;
2673 break;
2674 case WI_PORTTYPE_IBSS:
2675 if (sc->wi_create_ibss)
2676 options |= IFM_IEEE80211_IBSSMASTER;
2677 else
2678 options |= IFM_IEEE80211_IBSS;
2679 break;
2680 default:
2681 subtype = IFM_MANUAL; /* Unable to represent */
2682 break;
2683 }
2684 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
2685 IFM_INST(media));
2686 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
2687 return (EINVAL);
2688 ifmedia_set(&sc->sc_media, media);
2689 sc->wi_ptype = ptype;
2690 sc->wi_tx_rate = txrate;
2691 return (0);
2692 }
2693
2694 static int
2695 wi_media_change(ifp)
2696 struct ifnet *ifp;
2697 {
2698 struct wi_softc *sc = ifp->if_softc;
2699 int otype = sc->wi_ptype;
2700 int orate = sc->wi_tx_rate;
2701 int ocreate_ibss = sc->wi_create_ibss;
2702
2703 sc->wi_create_ibss = 0;
2704
2705 switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
2706 case 0:
2707 sc->wi_ptype = WI_PORTTYPE_BSS;
2708 break;
2709 case IFM_IEEE80211_ADHOC:
2710 sc->wi_ptype = WI_PORTTYPE_ADHOC;
2711 break;
2712 case IFM_IEEE80211_HOSTAP:
2713 sc->wi_ptype = WI_PORTTYPE_HOSTAP;
2714 break;
2715 case IFM_IEEE80211_IBSSMASTER:
2716 case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
2717 if ((sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0)
2718 return (EINVAL);
2719 sc->wi_create_ibss = 1;
2720 /* FALLTHROUGH */
2721 case IFM_IEEE80211_IBSS:
2722 sc->wi_ptype = WI_PORTTYPE_IBSS;
2723 break;
2724 default:
2725 /* Invalid combination. */
2726 sc->wi_create_ibss = ocreate_ibss;
2727 return (EINVAL);
2728 }
2729
2730 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
2731 case IFM_IEEE80211_DS1:
2732 sc->wi_tx_rate = 1;
2733 break;
2734 case IFM_IEEE80211_DS2:
2735 sc->wi_tx_rate = 2;
2736 break;
2737 case IFM_AUTO:
2738 sc->wi_tx_rate = 3;
2739 break;
2740 case IFM_IEEE80211_DS5:
2741 sc->wi_tx_rate = 5;
2742 break;
2743 case IFM_IEEE80211_DS11:
2744 sc->wi_tx_rate = 11;
2745 break;
2746 }
2747
2748 if (sc->sc_enabled != 0) {
2749 if (otype != sc->wi_ptype ||
2750 orate != sc->wi_tx_rate ||
2751 ocreate_ibss != sc->wi_create_ibss)
2752 wi_init(ifp);
2753 }
2754
2755 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2756
2757 return (0);
2758 }
2759
2760 static void
2761 wi_media_status(ifp, imr)
2762 struct ifnet *ifp;
2763 struct ifmediareq *imr;
2764 {
2765 struct wi_softc *sc = ifp->if_softc;
2766
2767 if (sc->sc_enabled == 0) {
2768 imr->ifm_active = IFM_IEEE80211|IFM_NONE;
2769 imr->ifm_status = 0;
2770 return;
2771 }
2772
2773 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2774 imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
2775 }
2776
2777 static int
2778 wi_set_nwkey(sc, nwkey)
2779 struct wi_softc *sc;
2780 struct ieee80211_nwkey *nwkey;
2781 {
2782 int i, error;
2783 size_t len;
2784 struct wi_req wreq;
2785 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
2786
2787 if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
2788 return ENODEV;
2789 if (nwkey->i_defkid <= 0 ||
2790 nwkey->i_defkid > IEEE80211_WEP_NKID)
2791 return EINVAL;
2792 memcpy(wk, &sc->wi_keys, sizeof(*wk));
2793 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2794 if (nwkey->i_key[i].i_keydat == NULL)
2795 continue;
2796 len = nwkey->i_key[i].i_keylen;
2797 if (len > sizeof(wk->wi_keys[i].wi_keydat))
2798 return EINVAL;
2799 error = copyin(nwkey->i_key[i].i_keydat,
2800 wk->wi_keys[i].wi_keydat, len);
2801 if (error)
2802 return error;
2803 wk->wi_keys[i].wi_keylen = htole16(len);
2804 }
2805
2806 wk->wi_len = (sizeof(*wk) / 2) + 1;
2807 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2808 if (sc->sc_enabled != 0) {
2809 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2810 if (error)
2811 return error;
2812 }
2813 error = wi_setdef(sc, &wreq);
2814 if (error)
2815 return error;
2816
2817 wreq.wi_len = 2;
2818 wreq.wi_type = WI_RID_TX_CRYPT_KEY;
2819 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
2820 if (sc->sc_enabled != 0) {
2821 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2822 if (error)
2823 return error;
2824 }
2825 error = wi_setdef(sc, &wreq);
2826 if (error)
2827 return error;
2828
2829 wreq.wi_type = WI_RID_ENCRYPTION;
2830 wreq.wi_val[0] = htole16(nwkey->i_wepon);
2831 if (sc->sc_enabled != 0) {
2832 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2833 if (error)
2834 return error;
2835 }
2836 error = wi_setdef(sc, &wreq);
2837 if (error)
2838 return error;
2839
2840 if (sc->sc_enabled != 0)
2841 wi_init(&sc->sc_ethercom.ec_if);
2842 return 0;
2843 }
2844
2845 static int
2846 wi_get_nwkey(sc, nwkey)
2847 struct wi_softc *sc;
2848 struct ieee80211_nwkey *nwkey;
2849 {
2850 int i, len, error;
2851 struct wi_ltv_keys *wk = &sc->wi_keys;
2852
2853 if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
2854 return ENODEV;
2855 nwkey->i_wepon = sc->wi_use_wep;
2856 nwkey->i_defkid = sc->wi_tx_key + 1;
2857
2858 /* do not show any keys to non-root user */
2859 error = suser(curproc->p_ucred, &curproc->p_acflag);
2860 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2861 if (nwkey->i_key[i].i_keydat == NULL)
2862 continue;
2863 /* error holds results of suser() for the first time */
2864 if (error)
2865 return error;
2866 len = le16toh(wk->wi_keys[i].wi_keylen);
2867 if (nwkey->i_key[i].i_keylen < len)
2868 return ENOSPC;
2869 nwkey->i_key[i].i_keylen = len;
2870 error = copyout(wk->wi_keys[i].wi_keydat,
2871 nwkey->i_key[i].i_keydat, len);
2872 if (error)
2873 return error;
2874 }
2875 return 0;
2876 }
2877
2878 static int
2879 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2880 {
2881
2882 sc->wi_pm_enabled = power->i_enabled;
2883 sc->wi_max_sleep = power->i_maxsleep;
2884
2885 if (sc->sc_enabled)
2886 return (wi_init(&sc->sc_ethercom.ec_if));
2887
2888 return (0);
2889 }
2890
2891 static int
2892 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2893 {
2894
2895 power->i_enabled = sc->wi_pm_enabled;
2896 power->i_maxsleep = sc->wi_max_sleep;
2897
2898 return (0);
2899 }
2900