wi.c revision 1.78 1 /* $NetBSD: wi.c,v 1.78 2002/08/11 01:35:10 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.78 2002/08/11 01:35:10 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 static int wi_mgmt_xmit __P((struct wi_softc *, caddr_t, int));
132
133 static int wi_media_change __P((struct ifnet *));
134 static void wi_media_status __P((struct ifnet *, struct ifmediareq *));
135
136 static void wi_get_id __P((struct wi_softc *));
137
138 static int wi_set_ssid __P((struct ieee80211_nwid *, u_int8_t *, int));
139 static void wi_request_fill_ssid __P((struct wi_req *,
140 struct ieee80211_nwid *));
141 static int wi_write_ssid __P((struct wi_softc *, int, struct wi_req *,
142 struct ieee80211_nwid *));
143 static int wi_set_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
144 static int wi_get_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
145 static int wi_sync_media __P((struct wi_softc *, int, int));
146 static int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
147 static int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
148
149 struct wi_card_ident wi_card_ident[] = {
150 /* CARD_ID CARD_NAME FIRM_TYPE */
151 { WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT },
152 { WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT },
153 { WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT },
154 { WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL },
155 { WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL },
156 { WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL },
157 { WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL },
158 { WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL },
159 { WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL },
160 { WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL },
161 { WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL },
162 { WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL },
163 { WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
164 { WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
165 { WI_NIC_3842_PCMCIA_ATM_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
166 { WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
167 { WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
168 { WI_NIC_3842_MINI_ATM_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
169 { WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
170 { WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
171 { WI_NIC_3842_PCI_ATM_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
172 { WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL },
173 { WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL },
174 { WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL },
175 { WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL },
176 { 0, NULL, 0 },
177 };
178
179 int
180 wi_attach(sc)
181 struct wi_softc *sc;
182 {
183 struct ifnet *ifp = sc->sc_ifp;
184 const char *sep = "";
185 struct wi_ltv_macaddr mac;
186 struct wi_ltv_gen gen;
187 static const u_int8_t empty_macaddr[ETHER_ADDR_LEN] = {
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
189 };
190 int s;
191
192 s = splnet();
193
194 callout_init(&sc->wi_inquire_ch);
195 callout_init(&sc->wi_scan_sh);
196
197 /* Make sure interrupts are disabled. */
198 CSR_WRITE_2(sc, WI_INT_EN, 0);
199 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
200
201 /* Reset the NIC. */
202 wi_reset(sc);
203
204 memset(&mac, 0, sizeof(mac));
205 /* Read the station address. */
206 mac.wi_type = WI_RID_MAC_NODE;
207 mac.wi_len = 4;
208 wi_read_record(sc, (struct wi_ltv_gen *)&mac);
209 memcpy(sc->sc_macaddr, mac.wi_mac_addr, ETHER_ADDR_LEN);
210
211 /*
212 * Check if we got anything meaningful.
213 *
214 * Is it really enough just checking against null ethernet address?
215 * Or, check against possible vendor? XXX.
216 */
217 if (memcmp(sc->sc_macaddr, empty_macaddr, ETHER_ADDR_LEN) == 0) {
218 printf("could not get mac address, attach failed\n");
219 splx(s);
220 return 1;
221 }
222
223 printf(" 802.11 address %s\n", ether_sprintf(sc->sc_macaddr));
224
225 /* Read NIC identification */
226 wi_get_id(sc);
227
228 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
229 ifp->if_softc = sc;
230 ifp->if_start = wi_start;
231 ifp->if_ioctl = wi_ioctl;
232 ifp->if_watchdog = wi_watchdog;
233 ifp->if_init = wi_init;
234 ifp->if_stop = wi_stop;
235 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
236 #ifdef IFF_NOTRAILERS
237 ifp->if_flags |= IFF_NOTRAILERS;
238 #endif
239 IFQ_SET_READY(&ifp->if_snd);
240
241 (void)wi_set_ssid(&sc->wi_nodeid, WI_DEFAULT_NODENAME,
242 sizeof(WI_DEFAULT_NODENAME) - 1);
243 (void)wi_set_ssid(&sc->wi_netid, WI_DEFAULT_NETNAME,
244 sizeof(WI_DEFAULT_NETNAME) - 1);
245 (void)wi_set_ssid(&sc->wi_ibssid, WI_DEFAULT_IBSS,
246 sizeof(WI_DEFAULT_IBSS) - 1);
247
248 sc->wi_portnum = WI_DEFAULT_PORT;
249 sc->wi_ptype = WI_PORTTYPE_BSS;
250 sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
251 sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
252 sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
253 sc->wi_max_data_len = WI_DEFAULT_DATALEN;
254 sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
255 sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
256 sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
257 sc->wi_roaming = WI_DEFAULT_ROAMING;
258 sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
259
260 /*
261 * Read the default channel from the NIC. This may vary
262 * depending on the country where the NIC was purchased, so
263 * we can't hard-code a default and expect it to work for
264 * everyone.
265 */
266 gen.wi_type = WI_RID_OWN_CHNL;
267 gen.wi_len = 2;
268 wi_read_record(sc, &gen);
269 sc->wi_channel = le16toh(gen.wi_val);
270
271 memset((char *)&sc->wi_stats, 0, sizeof(sc->wi_stats));
272
273 /* AP info was filled with 0 */
274 memset((char *)&sc->wi_aps, 0, sizeof(sc->wi_aps));
275 sc->wi_scanning = 0;
276 sc->wi_naps = 0;
277
278 /*
279 * Set flags based on firmware version.
280 */
281 switch (sc->sc_firmware_type) {
282 case WI_LUCENT:
283 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
284 if (sc->sc_sta_firmware_ver >= 60000)
285 sc->wi_flags |= WI_FLAGS_HAS_MOR;
286 if (sc->sc_sta_firmware_ver >= 60006) {
287 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
288 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
289 }
290 sc->wi_ibss_port = htole16(1);
291 break;
292
293 case WI_INTERSIL:
294 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
295 if (sc->sc_sta_firmware_ver >= 800) {
296 sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
297 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
298 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
299 }
300 sc->wi_ibss_port = htole16(0);
301 break;
302
303 case WI_SYMBOL:
304 sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
305 if (sc->sc_sta_firmware_ver >= 20000)
306 sc->wi_flags |= WI_FLAGS_HAS_IBSS;
307 if (sc->sc_sta_firmware_ver >= 25000)
308 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
309 sc->wi_ibss_port = htole16(4);
310 break;
311 }
312
313 /*
314 * Find out if we support WEP on this card.
315 */
316 gen.wi_type = WI_RID_WEP_AVAIL;
317 gen.wi_len = 2;
318 if (wi_read_record(sc, &gen) == 0 &&
319 gen.wi_val != le16toh(0))
320 sc->wi_flags |= WI_FLAGS_HAS_WEP;
321
322 /* Find supported rates. */
323 gen.wi_type = WI_RID_DATA_RATES;
324 gen.wi_len = 2;
325 if (wi_read_record(sc, &gen))
326 sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
327 WI_SUPPRATES_5M | WI_SUPPRATES_11M;
328 else
329 sc->wi_supprates = le16toh(gen.wi_val);
330
331 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
332 if (sc->wi_supprates != 0)
333 printf("%s: supported rates: ", sc->sc_dev.dv_xname);
334 #define ADD(m, c) ifmedia_add(&sc->sc_media, (m), (c), NULL)
335 #define PRINT(n) printf("%s%s", sep, (n)); sep = ", "
336 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
337 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
338 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
339 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
340 0), 0);
341 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
342 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
343 IFM_IEEE80211_IBSSMASTER, 0), 0);
344 if (sc->wi_supprates & WI_SUPPRATES_1M) {
345 PRINT("1Mbps");
346 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
347 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
348 IFM_IEEE80211_ADHOC, 0), 0);
349 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
350 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
351 IFM_IEEE80211_IBSS, 0), 0);
352 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
353 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
354 IFM_IEEE80211_IBSSMASTER, 0), 0);
355 }
356 if (sc->wi_supprates & WI_SUPPRATES_2M) {
357 PRINT("2Mbps");
358 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
359 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
360 IFM_IEEE80211_ADHOC, 0), 0);
361 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
362 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
363 IFM_IEEE80211_IBSS, 0), 0);
364 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
365 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
366 IFM_IEEE80211_IBSSMASTER, 0), 0);
367 }
368 if (sc->wi_supprates & WI_SUPPRATES_5M) {
369 PRINT("5.5Mbps");
370 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
371 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
372 IFM_IEEE80211_ADHOC, 0), 0);
373 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
374 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
375 IFM_IEEE80211_IBSS, 0), 0);
376 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
377 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
378 IFM_IEEE80211_IBSSMASTER, 0), 0);
379 }
380 if (sc->wi_supprates & WI_SUPPRATES_11M) {
381 PRINT("11Mbps");
382 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
383 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
384 IFM_IEEE80211_ADHOC, 0), 0);
385 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
386 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
387 IFM_IEEE80211_IBSS, 0), 0);
388 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
389 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
390 IFM_IEEE80211_IBSSMASTER, 0), 0);
391 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
392 }
393 if (sc->wi_supprates != 0)
394 printf("\n");
395 ifmedia_set(&sc->sc_media,
396 IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
397 #undef ADD
398 #undef PRINT
399
400 /*
401 * Call MI attach routines.
402 */
403 if_attach(ifp);
404 ether_ifattach(ifp, mac.wi_mac_addr);
405
406 ifp->if_baudrate = IF_Mbps(2);
407
408 /* Attach is successful. */
409 sc->sc_attached = 1;
410
411 splx(s);
412 return 0;
413 }
414
415 static void wi_rxeof(sc)
416 struct wi_softc *sc;
417 {
418 struct ifnet *ifp;
419 struct ether_header *eh;
420 struct wi_frame rx_frame;
421 struct mbuf *m;
422 int id;
423
424 ifp = sc->sc_ifp;
425
426 id = CSR_READ_2(sc, WI_RX_FID);
427
428 /* First read in the frame header */
429 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
430 ifp->if_ierrors++;
431 return;
432 }
433
434 /*
435 * Drop undecryptable or packets with receive errors here
436 */
437 if (le16toh(rx_frame.wi_status) & WI_STAT_ERRSTAT) {
438 ifp->if_ierrors++;
439 return;
440 }
441
442 MGETHDR(m, M_DONTWAIT, MT_DATA);
443 if (m == NULL) {
444 ifp->if_ierrors++;
445 return;
446 }
447 MCLGET(m, M_DONTWAIT);
448 if (!(m->m_flags & M_EXT)) {
449 m_freem(m);
450 ifp->if_ierrors++;
451 return;
452 }
453
454 /* Align the data after the ethernet header */
455 m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header))
456 - sizeof(struct ether_header);
457
458 eh = mtod(m, struct ether_header *);
459 m->m_pkthdr.rcvif = ifp;
460
461 if ((le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_1042 ||
462 (le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_TUNNEL ||
463 (le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_WMP_MSG) {
464 if ((le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > MCLBYTES) {
465 printf("%s: oversized packet received "
466 "(wi_dat_len=%d, wi_status=0x%x)\n",
467 sc->sc_dev.dv_xname,
468 le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
469 m_freem(m);
470 ifp->if_ierrors++;
471 return;
472 }
473 m->m_pkthdr.len = m->m_len =
474 le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
475
476 memcpy((char *)&eh->ether_dhost, (char *)&rx_frame.wi_dst_addr,
477 ETHER_ADDR_LEN);
478 memcpy((char *)&eh->ether_shost, (char *)&rx_frame.wi_src_addr,
479 ETHER_ADDR_LEN);
480 memcpy((char *)&eh->ether_type, (char *)&rx_frame.wi_type,
481 sizeof(u_int16_t));
482
483 if (wi_read_data(sc, id, WI_802_11_OFFSET,
484 mtod(m, caddr_t) + sizeof(struct ether_header),
485 m->m_len + 2)) {
486 m_freem(m);
487 ifp->if_ierrors++;
488 return;
489 }
490 } else {
491 if ((le16toh(rx_frame.wi_dat_len) +
492 sizeof(struct ether_header)) > MCLBYTES) {
493 printf("%s: oversized packet received "
494 "(wi_dat_len=%d, wi_status=0x%x)\n",
495 sc->sc_dev.dv_xname,
496 le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
497 m_freem(m);
498 ifp->if_ierrors++;
499 return;
500 }
501 m->m_pkthdr.len = m->m_len =
502 le16toh(rx_frame.wi_dat_len) + sizeof(struct ether_header);
503
504 if (wi_read_data(sc, id, WI_802_3_OFFSET,
505 mtod(m, caddr_t), m->m_len + 2)) {
506 m_freem(m);
507 ifp->if_ierrors++;
508 return;
509 }
510 }
511
512 ifp->if_ipackets++;
513
514 #if NBPFILTER > 0
515 /* Handle BPF listeners. */
516 if (ifp->if_bpf)
517 bpf_mtap(ifp->if_bpf, m);
518 #endif
519
520 /* Receive packet. */
521 (*ifp->if_input)(ifp, m);
522 }
523
524 static void wi_txeof(sc, status)
525 struct wi_softc *sc;
526 int status;
527 {
528 struct ifnet *ifp = sc->sc_ifp;
529
530 ifp->if_timer = 0;
531 ifp->if_flags &= ~IFF_OACTIVE;
532
533 if (status & WI_EV_TX_EXC)
534 ifp->if_oerrors++;
535 else
536 ifp->if_opackets++;
537
538 return;
539 }
540
541 void wi_inquire(xsc)
542 void *xsc;
543 {
544 struct wi_softc *sc;
545 struct ifnet *ifp;
546 int s;
547
548 sc = xsc;
549 ifp = &sc->sc_ethercom.ec_if;
550
551 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
552 return;
553
554 KASSERT(sc->sc_enabled);
555
556 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
557
558 /* Don't do this while we're transmitting */
559 if (ifp->if_flags & IFF_OACTIVE)
560 return;
561
562 s = splnet();
563 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
564 splx(s);
565 }
566
567 void wi_wait_scan(xsc)
568 void *xsc;
569 {
570 struct wi_softc *sc;
571 struct ifnet *ifp;
572 int s, result;
573
574 sc = xsc;
575 ifp = &sc->sc_ethercom.ec_if;
576
577 /* If not scanning, ignore */
578 if (!sc->wi_scanning)
579 return;
580
581 s = splnet();
582
583 /* Wait for sending complete to make INQUIRE */
584 if (ifp->if_flags & IFF_OACTIVE) {
585 callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
586 splx(s);
587 return;
588 }
589
590 /* try INQUIRE */
591 result = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS);
592 if (result == ETIMEDOUT)
593 callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
594
595 splx(s);
596 }
597
598 void wi_update_stats(sc)
599 struct wi_softc *sc;
600 {
601 struct wi_ltv_gen gen;
602 struct wi_scan_header ap2_header; /* Prism2 header */
603 struct wi_scan_data_p2 ap2; /* Prism2 scantable*/
604 struct wi_scan_data ap; /* Lucent scantable */
605 struct wi_assoc assoc; /* Association Status */
606 u_int16_t id;
607 struct ifnet *ifp;
608 u_int32_t *ptr;
609 int len, naps, i, j;
610 u_int16_t t;
611
612 ifp = &sc->sc_ethercom.ec_if;
613
614 id = CSR_READ_2(sc, WI_INFO_FID);
615
616 if (wi_seek(sc, id, 0, WI_BAP1)) {
617 return;
618 }
619
620 gen.wi_len = CSR_READ_2(sc, WI_DATA1);
621 gen.wi_type = CSR_READ_2(sc, WI_DATA1);
622
623 switch (gen.wi_type) {
624 case WI_INFO_SCAN_RESULTS:
625 case WI_INFO_HOST_SCAN_RESULTS:
626 if (gen.wi_len <= 3) {
627 sc->wi_naps = 0;
628 sc->wi_scanning = 0;
629 break;
630 }
631 switch (sc->sc_firmware_type) {
632 case WI_INTERSIL:
633 case WI_SYMBOL:
634 if (sc->sc_firmware_type == WI_INTERSIL) {
635 naps = 2 * (gen.wi_len - 3) / sizeof(ap2);
636 /* Read Header */
637 for(j=0; j < sizeof(ap2_header) / 2; j++)
638 ((u_int16_t *)&ap2_header)[j] =
639 CSR_READ_2(sc, WI_DATA1);
640 } else { /* WI_SYMBOL */
641 naps = 2 * (gen.wi_len - 1) / (sizeof(ap2) + 6);
642 ap2_header.wi_reason = 0;
643 }
644 naps = naps > MAXAPINFO ? MAXAPINFO : naps;
645 sc->wi_naps = naps;
646 /* Read Data */
647 for (i=0; i < naps; i++) {
648 for(j=0; j < sizeof(ap2) / 2; j++)
649 ((u_int16_t *)&ap2)[j] =
650 CSR_READ_2(sc, WI_DATA1);
651 if (sc->sc_firmware_type == WI_SYMBOL) {
652 /* 3 more words */
653 for (j = 0; j < 3; j++)
654 CSR_READ_2(sc, WI_DATA1);
655 }
656 /* unswap 8 bit data fields: */
657 for(j=0;j<sizeof(ap.wi_bssid)/2;j++)
658 LE16TOH(((u_int16_t *)&ap.wi_bssid[0])[j]);
659 for(j=0;j<sizeof(ap.wi_name)/2;j++)
660 LE16TOH(((u_int16_t *)&ap.wi_name[0])[j]);
661 sc->wi_aps[i].scanreason = ap2_header.wi_reason;
662 memcpy(sc->wi_aps[i].bssid, ap2.wi_bssid, 6);
663 sc->wi_aps[i].channel = ap2.wi_chid;
664 sc->wi_aps[i].signal = ap2.wi_signal;
665 sc->wi_aps[i].noise = ap2.wi_noise;
666 sc->wi_aps[i].quality = ap2.wi_signal - ap2.wi_noise;
667 sc->wi_aps[i].capinfo = ap2.wi_capinfo;
668 sc->wi_aps[i].interval = ap2.wi_interval;
669 sc->wi_aps[i].rate = ap2.wi_rate;
670 if (ap2.wi_namelen > 32)
671 ap2.wi_namelen = 32;
672 sc->wi_aps[i].namelen = ap2.wi_namelen;
673 memcpy(sc->wi_aps[i].name, ap2.wi_name,
674 ap2.wi_namelen);
675 }
676 break;
677
678 case WI_LUCENT:
679 naps = 2 * gen.wi_len / sizeof(ap);
680 naps = naps > MAXAPINFO ? MAXAPINFO : naps;
681 sc->wi_naps = naps;
682 /* Read Data*/
683 for (i=0; i < naps; i++) {
684 for(j=0; j < sizeof(ap) / 2; j++)
685 ((u_int16_t *)&ap)[j] =
686 CSR_READ_2(sc, WI_DATA1);
687 /* unswap 8 bit data fields: */
688 for(j=0;j<sizeof(ap.wi_bssid)/2;j++)
689 HTOLE16(((u_int16_t *)&ap.wi_bssid[0])[j]);
690 for(j=0;j<sizeof(ap.wi_name)/2;j++)
691 HTOLE16(((u_int16_t *)&ap.wi_name[0])[j]);
692 memcpy(sc->wi_aps[i].bssid, ap.wi_bssid, 6);
693 sc->wi_aps[i].channel = ap.wi_chid;
694 sc->wi_aps[i].signal = ap.wi_signal;
695 sc->wi_aps[i].noise = ap.wi_noise;
696 sc->wi_aps[i].quality = ap.wi_signal - ap.wi_noise;
697 sc->wi_aps[i].capinfo = ap.wi_capinfo;
698 sc->wi_aps[i].interval = ap.wi_interval;
699 if (ap.wi_namelen > 32)
700 ap.wi_namelen = 32;
701 sc->wi_aps[i].namelen = ap.wi_namelen;
702 memcpy(sc->wi_aps[i].name, ap.wi_name,
703 ap.wi_namelen);
704 }
705 break;
706 }
707 /* Done scanning */
708 sc->wi_scanning = 0;
709 break;
710
711 case WI_INFO_COUNTERS:
712 /* some card versions have a larger stats structure */
713 len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
714 gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
715 ptr = (u_int32_t *)&sc->wi_stats;
716
717 for (i = 0; i < len; i++) {
718 t = CSR_READ_2(sc, WI_DATA1);
719 #ifdef WI_HERMES_STATS_WAR
720 if (t > 0xF000)
721 t = ~t & 0xFFFF;
722 #endif
723 ptr[i] += t;
724 }
725
726 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
727 sc->wi_stats.wi_tx_multi_retries +
728 sc->wi_stats.wi_tx_retry_limit;
729 break;
730
731 case WI_INFO_LINK_STAT: {
732 static char *msg[] = {
733 "connected",
734 "disconnected",
735 "AP change",
736 "AP out of range",
737 "AP in range",
738 "Association Failed"
739 };
740
741 if (gen.wi_len != 2) {
742 #ifdef WI_DEBUG
743 printf("WI_INFO_LINK_STAT: len=%d\n", gen.wi_len);
744 #endif
745 break;
746 }
747 t = CSR_READ_2(sc, WI_DATA1);
748 if ((t < 1) || (t > 6)) {
749 #ifdef WI_DEBUG
750 printf("WI_INFO_LINK_STAT: status %d\n", t);
751 #endif
752 break;
753 }
754 if (sc->sc_firmware_type == WI_SYMBOL && t == 4) {
755 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_HOST_SCAN_RESULTS);
756 break;
757 }
758 /*
759 * Some cards issue streams of "connected" messages while
760 * trying to find a peer. Don't bother the user with this
761 * unless he is debugging.
762 */
763 if (ifp->if_flags & IFF_DEBUG)
764 printf("%s: %s\n", sc->sc_dev.dv_xname, msg[t - 1]);
765 break;
766 }
767
768 case WI_INFO_ASSOC_STAT: {
769 static char *msg[] = {
770 "STA Associated",
771 "STA Reassociated",
772 "STA Disassociated",
773 "Association Failure",
774 "Authentication Failed"
775 };
776 if (gen.wi_len != 10)
777 break;
778 for (i=0; i < gen.wi_len - 1; i++)
779 ((u_int16_t *)&assoc)[i] = CSR_READ_2(sc, WI_DATA1);
780 /* unswap 8 bit data fields: */
781 for(j=0;j<sizeof(assoc.wi_assoc_sta)/2;j++)
782 HTOLE16(((u_int16_t *)&assoc.wi_assoc_sta[0])[j]);
783 for(j=0;j<sizeof(assoc.wi_assoc_osta)/2;j++)
784 HTOLE16(((u_int16_t *)&assoc.wi_assoc_osta[0])[j]);
785 switch (assoc.wi_assoc_stat) {
786 case ASSOC:
787 case DISASSOC:
788 case ASSOCFAIL:
789 case AUTHFAIL:
790 printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x\n",
791 sc->sc_dev.dv_xname,
792 msg[assoc.wi_assoc_stat - 1],
793 assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
794 assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
795 assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff);
796 break;
797 case REASSOC:
798 printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x, "
799 "OldAP = %02x:%02x:%02x:%02x:%02x:%02x\n",
800 sc->sc_dev.dv_xname, msg[assoc.wi_assoc_stat - 1],
801 assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
802 assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
803 assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff,
804 assoc.wi_assoc_osta[0]&0xff, assoc.wi_assoc_osta[1]&0xff,
805 assoc.wi_assoc_osta[2]&0xff, assoc.wi_assoc_osta[3]&0xff,
806 assoc.wi_assoc_osta[4]&0xff, assoc.wi_assoc_osta[5]&0xff);
807 break;
808 }
809 }
810
811 default:
812 #ifdef WI_DEBUG
813 printf("%s: got info type: 0x%04x len=0x%04x\n",
814 sc->sc_dev.dv_xname, gen.wi_type,gen.wi_len);
815 #endif
816 #if 0
817 for (i = 0; i < gen.wi_len; i++) {
818 t = CSR_READ_2(sc, WI_DATA1);
819 printf("[0x%02x] = 0x%04x\n", i, t);
820 }
821 #endif
822 break;
823 }
824 }
825
826 int wi_intr(arg)
827 void *arg;
828 {
829 struct wi_softc *sc = arg;
830 struct ifnet *ifp;
831 u_int16_t status;
832
833 if (sc->sc_enabled == 0 ||
834 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
835 (sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0)
836 return (0);
837
838 ifp = &sc->sc_ethercom.ec_if;
839
840 if (!(ifp->if_flags & IFF_UP)) {
841 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
842 CSR_WRITE_2(sc, WI_INT_EN, 0);
843 return 1;
844 }
845
846 /* Disable interrupts. */
847 CSR_WRITE_2(sc, WI_INT_EN, 0);
848
849 status = CSR_READ_2(sc, WI_EVENT_STAT);
850 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
851
852 if (status & WI_EV_RX) {
853 wi_rxeof(sc);
854 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
855 }
856
857 if (status & WI_EV_TX) {
858 wi_txeof(sc, status);
859 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
860 }
861
862 if (status & WI_EV_ALLOC) {
863 int id;
864 id = CSR_READ_2(sc, WI_ALLOC_FID);
865 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
866 if (id == sc->wi_tx_data_id)
867 wi_txeof(sc, status);
868 }
869
870 if (status & WI_EV_INFO) {
871 wi_update_stats(sc);
872 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
873 }
874
875 if (status & WI_EV_TX_EXC) {
876 wi_txeof(sc, status);
877 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
878 }
879
880 if (status & WI_EV_INFO_DROP) {
881 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
882 }
883
884 /* Re-enable interrupts. */
885 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
886
887 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
888 wi_start(ifp);
889
890 return 1;
891 }
892
893 /* Must be called at proper protection level! */
894 static int
895 wi_cmd(sc, cmd, val)
896 struct wi_softc *sc;
897 int cmd;
898 int val;
899 {
900 int i, s = 0;
901
902 /* wait for the busy bit to clear */
903 for (i = 0; i < WI_TIMEOUT; i++) {
904 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
905 break;
906 }
907
908 if (i == WI_TIMEOUT) {
909 printf("%s: wi_cmd: BUSY did not clear, cmd=0x%x\n",
910 sc->sc_dev.dv_xname, cmd);
911 return EIO;
912 }
913
914 CSR_WRITE_2(sc, WI_PARAM0, val);
915 CSR_WRITE_2(sc, WI_PARAM1, 0);
916 CSR_WRITE_2(sc, WI_PARAM2, 0);
917 CSR_WRITE_2(sc, WI_COMMAND, cmd);
918
919 /* wait for the cmd completed bit */
920 for (i = 0; i < WI_TIMEOUT; i++) {
921 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
922 break;
923 DELAY(1);
924 }
925
926 /* Ack the command */
927 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
928
929 s = CSR_READ_2(sc, WI_STATUS);
930 if (s & WI_STAT_CMD_RESULT)
931 return(EIO);
932
933 if (i == WI_TIMEOUT) {
934 if (!sc->wi_scanning)
935 printf("%s: command timed out, cmd=0x%x\n",
936 sc->sc_dev.dv_xname, cmd);
937 return(ETIMEDOUT);
938 }
939
940 return(0);
941 }
942
943 static void
944 wi_reset(sc)
945 struct wi_softc *sc;
946 {
947
948 DELAY(100*1000); /* 100 m sec */
949 if (wi_cmd(sc, WI_CMD_INI, 0))
950 printf("%s: init failed\n", sc->sc_dev.dv_xname);
951 CSR_WRITE_2(sc, WI_INT_EN, 0);
952 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
953
954 /* Calibrate timer. */
955 WI_SETVAL(WI_RID_TICK_TIME, 8);
956
957 return;
958 }
959
960 /*
961 * Read an LTV record from the NIC.
962 */
963 static int wi_read_record(sc, ltv)
964 struct wi_softc *sc;
965 struct wi_ltv_gen *ltv;
966 {
967 u_int16_t *ptr;
968 int len, code;
969 struct wi_ltv_gen *oltv, p2ltv;
970
971 if (sc->sc_firmware_type != WI_LUCENT) {
972 oltv = ltv;
973 switch (ltv->wi_type) {
974 case WI_RID_ENCRYPTION:
975 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
976 p2ltv.wi_len = 2;
977 ltv = &p2ltv;
978 break;
979 case WI_RID_TX_CRYPT_KEY:
980 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
981 p2ltv.wi_len = 2;
982 ltv = &p2ltv;
983 break;
984 case WI_RID_ROAMING_MODE:
985 if (sc->sc_firmware_type == WI_INTERSIL)
986 break;
987 /* not supported */
988 ltv->wi_len = 1;
989 return 0;
990 case WI_RID_MICROWAVE_OVEN:
991 /* not supported */
992 ltv->wi_len = 1;
993 return 0;
994 }
995 }
996
997 /* Tell the NIC to enter record read mode. */
998 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
999 return(EIO);
1000
1001 /* Seek to the record. */
1002 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1003 return(EIO);
1004
1005 /*
1006 * Read the length and record type and make sure they
1007 * match what we expect (this verifies that we have enough
1008 * room to hold all of the returned data).
1009 */
1010 len = CSR_READ_2(sc, WI_DATA1);
1011 if (len > ltv->wi_len)
1012 return(ENOSPC);
1013 code = CSR_READ_2(sc, WI_DATA1);
1014 if (code != ltv->wi_type)
1015 return(EIO);
1016
1017 ltv->wi_len = len;
1018 ltv->wi_type = code;
1019
1020 /* Now read the data. */
1021 ptr = <v->wi_val;
1022 if (ltv->wi_len > 1)
1023 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
1024
1025 if (ltv->wi_type == WI_RID_PORTTYPE &&
1026 sc->wi_ptype == WI_PORTTYPE_IBSS &&
1027 ltv->wi_val == sc->wi_ibss_port) {
1028 /*
1029 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
1030 * Since Lucent uses port type 1 for BSS *and* IBSS we
1031 * have to rely on wi_ptype to distinguish this for us.
1032 */
1033 ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
1034 } else if (sc->sc_firmware_type != WI_LUCENT) {
1035 int v;
1036
1037 switch (oltv->wi_type) {
1038 case WI_RID_TX_RATE:
1039 case WI_RID_CUR_TX_RATE:
1040 switch (le16toh(ltv->wi_val)) {
1041 case 1: v = 1; break;
1042 case 2: v = 2; break;
1043 case 3: v = 6; break;
1044 case 4: v = 5; break;
1045 case 7: v = 7; break;
1046 case 8: v = 11; break;
1047 case 15: v = 3; break;
1048 default: v = 0x100 + le16toh(ltv->wi_val); break;
1049 }
1050 oltv->wi_val = htole16(v);
1051 break;
1052 case WI_RID_ENCRYPTION:
1053 oltv->wi_len = 2;
1054 if (le16toh(ltv->wi_val) & 0x01)
1055 oltv->wi_val = htole16(1);
1056 else
1057 oltv->wi_val = htole16(0);
1058 break;
1059 case WI_RID_TX_CRYPT_KEY:
1060 oltv->wi_len = 2;
1061 oltv->wi_val = ltv->wi_val;
1062 break;
1063 case WI_RID_AUTH_CNTL:
1064 oltv->wi_len = 2;
1065 if (le16toh(ltv->wi_val) & 0x01)
1066 oltv->wi_val = htole16(1);
1067 else if (le16toh(ltv->wi_val) & 0x02)
1068 oltv->wi_val = htole16(2);
1069 break;
1070 }
1071 }
1072
1073 return(0);
1074 }
1075
1076 /*
1077 * Same as read, except we inject data instead of reading it.
1078 */
1079 static int wi_write_record(sc, ltv)
1080 struct wi_softc *sc;
1081 struct wi_ltv_gen *ltv;
1082 {
1083 u_int16_t *ptr;
1084 int i;
1085 struct wi_ltv_gen p2ltv;
1086
1087 if (ltv->wi_type == WI_RID_PORTTYPE &&
1088 ltv->wi_val == le16toh(WI_PORTTYPE_IBSS)) {
1089 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
1090 p2ltv.wi_type = WI_RID_PORTTYPE;
1091 p2ltv.wi_len = 2;
1092 p2ltv.wi_val = sc->wi_ibss_port;
1093 ltv = &p2ltv;
1094 } else if (sc->sc_firmware_type != WI_LUCENT) {
1095 int v;
1096
1097 switch (ltv->wi_type) {
1098 case WI_RID_TX_RATE:
1099 p2ltv.wi_type = WI_RID_TX_RATE;
1100 p2ltv.wi_len = 2;
1101 switch (le16toh(ltv->wi_val)) {
1102 case 1: v = 1; break;
1103 case 2: v = 2; break;
1104 case 3: v = 15; break;
1105 case 5: v = 4; break;
1106 case 6: v = 3; break;
1107 case 7: v = 7; break;
1108 case 11: v = 8; break;
1109 default: return EINVAL;
1110 }
1111 p2ltv.wi_val = htole16(v);
1112 ltv = &p2ltv;
1113 break;
1114 case WI_RID_ENCRYPTION:
1115 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1116 p2ltv.wi_len = 2;
1117 if (le16toh(ltv->wi_val))
1118 p2ltv.wi_val = htole16(PRIVACY_INVOKED |
1119 EXCLUDE_UNENCRYPTED);
1120 else
1121 p2ltv.wi_val =
1122 htole16(HOST_ENCRYPT | HOST_DECRYPT);
1123 ltv = &p2ltv;
1124 break;
1125 case WI_RID_TX_CRYPT_KEY:
1126 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1127 p2ltv.wi_len = 2;
1128 p2ltv.wi_val = ltv->wi_val;
1129 ltv = &p2ltv;
1130 break;
1131 case WI_RID_DEFLT_CRYPT_KEYS:
1132 {
1133 int error;
1134 int keylen;
1135 struct wi_ltv_str ws;
1136 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
1137
1138 keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1139
1140 for (i = 0; i < 4; i++) {
1141 memset(&ws, 0, sizeof(ws));
1142 ws.wi_len = (keylen > 5) ? 8 : 4;
1143 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1144 memcpy(ws.wi_str,
1145 &wk->wi_keys[i].wi_keydat, keylen);
1146 error = wi_write_record(sc,
1147 (struct wi_ltv_gen *)&ws);
1148 if (error)
1149 return error;
1150 }
1151 return 0;
1152 }
1153 case WI_RID_AUTH_CNTL:
1154 p2ltv.wi_type = WI_RID_AUTH_CNTL;
1155 p2ltv.wi_len = 2;
1156 if (le16toh(ltv->wi_val) == 1)
1157 p2ltv.wi_val = htole16(0x01);
1158 else if (le16toh(ltv->wi_val) == 2)
1159 p2ltv.wi_val = htole16(0x02);
1160 ltv = &p2ltv;
1161 break;
1162
1163 case WI_RID_ROAMING_MODE:
1164 if (sc->sc_firmware_type == WI_INTERSIL)
1165 break;
1166 /* not supported */
1167 return 0;
1168
1169 case WI_RID_MICROWAVE_OVEN:
1170 /* not supported */
1171 return 0;
1172 }
1173 }
1174
1175 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1176 return(EIO);
1177
1178 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1179 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1180
1181 /* Write data */
1182 ptr = <v->wi_val;
1183 if (ltv->wi_len > 1)
1184 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
1185
1186 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
1187 return(EIO);
1188
1189 return(0);
1190 }
1191
1192 static int wi_seek(sc, id, off, chan)
1193 struct wi_softc *sc;
1194 int id, off, chan;
1195 {
1196 int i;
1197 int selreg, offreg;
1198 int status;
1199
1200 switch (chan) {
1201 case WI_BAP0:
1202 selreg = WI_SEL0;
1203 offreg = WI_OFF0;
1204 break;
1205 case WI_BAP1:
1206 selreg = WI_SEL1;
1207 offreg = WI_OFF1;
1208 break;
1209 default:
1210 printf("%s: invalid data path: %x\n",
1211 sc->sc_dev.dv_xname, chan);
1212 return(EIO);
1213 }
1214
1215 CSR_WRITE_2(sc, selreg, id);
1216 CSR_WRITE_2(sc, offreg, off);
1217
1218 for (i = 0; i < WI_TIMEOUT; i++) {
1219 status = CSR_READ_2(sc, offreg);
1220 if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
1221 break;
1222 }
1223
1224 if (i == WI_TIMEOUT) {
1225 printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
1226 sc->sc_dev.dv_xname, id, off, status);
1227 return(ETIMEDOUT);
1228 }
1229 return(0);
1230 }
1231
1232 static int wi_read_data(sc, id, off, buf, len)
1233 struct wi_softc *sc;
1234 int id, off;
1235 caddr_t buf;
1236 int len;
1237 {
1238 u_int16_t *ptr;
1239
1240 if (wi_seek(sc, id, off, WI_BAP1))
1241 return(EIO);
1242
1243 ptr = (u_int16_t *)buf;
1244 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
1245
1246 return(0);
1247 }
1248
1249 /*
1250 * According to the comments in the HCF Light code, there is a bug in
1251 * the Hermes (or possibly in certain Hermes firmware revisions) where
1252 * the chip's internal autoincrement counter gets thrown off during
1253 * data writes: the autoincrement is missed, causing one data word to
1254 * be overwritten and subsequent words to be written to the wrong memory
1255 * locations. The end result is that we could end up transmitting bogus
1256 * frames without realizing it. The workaround for this is to write a
1257 * couple of extra guard words after the end of the transfer, then
1258 * attempt to read then back. If we fail to locate the guard words where
1259 * we expect them, we preform the transfer over again.
1260 */
1261 static int wi_write_data(sc, id, off, buf, len)
1262 struct wi_softc *sc;
1263 int id, off;
1264 caddr_t buf;
1265 int len;
1266 {
1267 u_int16_t *ptr;
1268
1269 #ifdef WI_HERMES_AUTOINC_WAR
1270 again:
1271 #endif
1272
1273 if (wi_seek(sc, id, off, WI_BAP0))
1274 return(EIO);
1275
1276 ptr = (u_int16_t *)buf;
1277 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
1278
1279 #ifdef WI_HERMES_AUTOINC_WAR
1280 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1281 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1282
1283 if (wi_seek(sc, id, off + len, WI_BAP0))
1284 return(EIO);
1285
1286 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1287 CSR_READ_2(sc, WI_DATA0) != 0x5678)
1288 goto again;
1289 #endif
1290
1291 return(0);
1292 }
1293
1294 /*
1295 * Allocate a region of memory inside the NIC and zero
1296 * it out.
1297 */
1298 static int wi_alloc_nicmem(sc, len, id)
1299 struct wi_softc *sc;
1300 int len;
1301 int *id;
1302 {
1303 int i;
1304
1305 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
1306 printf("%s: failed to allocate %d bytes on NIC\n",
1307 sc->sc_dev.dv_xname, len);
1308 return(ENOMEM);
1309 }
1310
1311 for (i = 0; i < WI_TIMEOUT; i++) {
1312 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1313 break;
1314 }
1315
1316 if (i == WI_TIMEOUT) {
1317 printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
1318 return(ETIMEDOUT);
1319 }
1320
1321 *id = CSR_READ_2(sc, WI_ALLOC_FID);
1322 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1323
1324 if (wi_seek(sc, *id, 0, WI_BAP0)) {
1325 printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
1326 return(EIO);
1327 }
1328
1329 for (i = 0; i < len / 2; i++)
1330 CSR_WRITE_2(sc, WI_DATA0, 0);
1331
1332 return(0);
1333 }
1334
1335 static void wi_setmulti(sc)
1336 struct wi_softc *sc;
1337 {
1338 struct ifnet *ifp;
1339 int i = 0;
1340 struct wi_ltv_mcast mcast;
1341 struct ether_multi *enm;
1342 struct ether_multistep estep;
1343 struct ethercom *ec = &sc->sc_ethercom;
1344
1345 ifp = &sc->sc_ethercom.ec_if;
1346
1347 if ((ifp->if_flags & IFF_PROMISC) != 0) {
1348 allmulti:
1349 ifp->if_flags |= IFF_ALLMULTI;
1350 memset((char *)&mcast, 0, sizeof(mcast));
1351 mcast.wi_type = WI_RID_MCAST_LIST;
1352 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
1353
1354 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1355 return;
1356 }
1357
1358 i = 0;
1359 ETHER_FIRST_MULTI(estep, ec, enm);
1360 while (enm != NULL) {
1361 /* Punt on ranges or too many multicast addresses. */
1362 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
1363 ETHER_ADDR_LEN) != 0 ||
1364 i >= 16)
1365 goto allmulti;
1366
1367 memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo,
1368 ETHER_ADDR_LEN);
1369 i++;
1370 ETHER_NEXT_MULTI(estep, enm);
1371 }
1372
1373 ifp->if_flags &= ~IFF_ALLMULTI;
1374 mcast.wi_type = WI_RID_MCAST_LIST;
1375 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
1376 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1377 }
1378
1379 static int
1380 wi_setdef(sc, wreq)
1381 struct wi_softc *sc;
1382 struct wi_req *wreq;
1383 {
1384 struct sockaddr_dl *sdl;
1385 struct ifnet *ifp;
1386 int error = 0;
1387
1388 ifp = &sc->sc_ethercom.ec_if;
1389
1390 switch(wreq->wi_type) {
1391 case WI_RID_MAC_NODE:
1392 sdl = (struct sockaddr_dl *)ifp->if_sadl;
1393 memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val,
1394 ETHER_ADDR_LEN);
1395 memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN);
1396 break;
1397 case WI_RID_PORTTYPE:
1398 error = wi_sync_media(sc, le16toh(wreq->wi_val[0]),
1399 sc->wi_tx_rate);
1400 break;
1401 case WI_RID_TX_RATE:
1402 error = wi_sync_media(sc, sc->wi_ptype,
1403 le16toh(wreq->wi_val[0]));
1404 break;
1405 case WI_RID_MAX_DATALEN:
1406 sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
1407 break;
1408 case WI_RID_RTS_THRESH:
1409 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
1410 break;
1411 case WI_RID_SYSTEM_SCALE:
1412 sc->wi_ap_density = le16toh(wreq->wi_val[0]);
1413 break;
1414 case WI_RID_CREATE_IBSS:
1415 sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
1416 error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
1417 break;
1418 case WI_RID_OWN_CHNL:
1419 sc->wi_channel = le16toh(wreq->wi_val[0]);
1420 break;
1421 case WI_RID_NODENAME:
1422 error = wi_set_ssid(&sc->wi_nodeid,
1423 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1424 break;
1425 case WI_RID_DESIRED_SSID:
1426 error = wi_set_ssid(&sc->wi_netid,
1427 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1428 break;
1429 case WI_RID_OWN_SSID:
1430 error = wi_set_ssid(&sc->wi_ibssid,
1431 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1432 break;
1433 case WI_RID_PM_ENABLED:
1434 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
1435 break;
1436 case WI_RID_MICROWAVE_OVEN:
1437 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
1438 break;
1439 case WI_RID_MAX_SLEEP:
1440 sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
1441 break;
1442 case WI_RID_AUTH_CNTL:
1443 sc->wi_authtype = le16toh(wreq->wi_val[0]);
1444 break;
1445 case WI_RID_ROAMING_MODE:
1446 sc->wi_roaming = le16toh(wreq->wi_val[0]);
1447 break;
1448 case WI_RID_ENCRYPTION:
1449 sc->wi_use_wep = le16toh(wreq->wi_val[0]);
1450 break;
1451 case WI_RID_TX_CRYPT_KEY:
1452 sc->wi_tx_key = le16toh(wreq->wi_val[0]);
1453 break;
1454 case WI_RID_DEFLT_CRYPT_KEYS:
1455 memcpy((char *)&sc->wi_keys, (char *)wreq,
1456 sizeof(struct wi_ltv_keys));
1457 break;
1458 default:
1459 error = EINVAL;
1460 break;
1461 }
1462
1463 return (error);
1464 }
1465
1466 static int
1467 wi_getdef(sc, wreq)
1468 struct wi_softc *sc;
1469 struct wi_req *wreq;
1470 {
1471 struct sockaddr_dl *sdl;
1472 struct ifnet *ifp;
1473 int error = 0;
1474
1475 ifp = &sc->sc_ethercom.ec_if;
1476
1477 wreq->wi_len = 2; /* XXX */
1478 switch (wreq->wi_type) {
1479 case WI_RID_MAC_NODE:
1480 wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
1481 sdl = (struct sockaddr_dl *)ifp->if_sadl;
1482 memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN);
1483 memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
1484 break;
1485 case WI_RID_PORTTYPE:
1486 wreq->wi_val[0] = htole16(sc->wi_ptype);
1487 break;
1488 case WI_RID_TX_RATE:
1489 wreq->wi_val[0] = htole16(sc->wi_tx_rate);
1490 break;
1491 case WI_RID_MAX_DATALEN:
1492 wreq->wi_val[0] = htole16(sc->wi_max_data_len);
1493 break;
1494 case WI_RID_RTS_THRESH:
1495 wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
1496 break;
1497 case WI_RID_SYSTEM_SCALE:
1498 wreq->wi_val[0] = htole16(sc->wi_ap_density);
1499 break;
1500 case WI_RID_CREATE_IBSS:
1501 wreq->wi_val[0] = htole16(sc->wi_create_ibss);
1502 break;
1503 case WI_RID_OWN_CHNL:
1504 wreq->wi_val[0] = htole16(sc->wi_channel);
1505 break;
1506 case WI_RID_NODENAME:
1507 wi_request_fill_ssid(wreq, &sc->wi_nodeid);
1508 break;
1509 case WI_RID_DESIRED_SSID:
1510 wi_request_fill_ssid(wreq, &sc->wi_netid);
1511 break;
1512 case WI_RID_OWN_SSID:
1513 wi_request_fill_ssid(wreq, &sc->wi_ibssid);
1514 break;
1515 case WI_RID_PM_ENABLED:
1516 wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
1517 break;
1518 case WI_RID_MICROWAVE_OVEN:
1519 wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
1520 break;
1521 case WI_RID_MAX_SLEEP:
1522 wreq->wi_val[0] = htole16(sc->wi_max_sleep);
1523 break;
1524 case WI_RID_AUTH_CNTL:
1525 wreq->wi_val[0] = htole16(sc->wi_authtype);
1526 break;
1527 case WI_RID_ROAMING_MODE:
1528 wreq->wi_val[0] = htole16(sc->wi_roaming);
1529 break;
1530 case WI_RID_WEP_AVAIL:
1531 wreq->wi_val[0] = (sc->wi_flags & WI_FLAGS_HAS_WEP) ?
1532 htole16(1) : htole16(0);
1533 break;
1534 case WI_RID_ENCRYPTION:
1535 wreq->wi_val[0] = htole16(sc->wi_use_wep);
1536 break;
1537 case WI_RID_TX_CRYPT_KEY:
1538 wreq->wi_val[0] = htole16(sc->wi_tx_key);
1539 break;
1540 case WI_RID_DEFLT_CRYPT_KEYS:
1541 wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
1542 memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
1543 break;
1544 default:
1545 #if 0
1546 error = EIO;
1547 #else
1548 #ifdef WI_DEBUG
1549 printf("%s: wi_getdef: unknown request %d\n",
1550 sc->sc_dev.dv_xname, wreq->wi_type);
1551 #endif
1552 #endif
1553 break;
1554 }
1555
1556 return (error);
1557 }
1558
1559 static int
1560 wi_ioctl(ifp, command, data)
1561 struct ifnet *ifp;
1562 u_long command;
1563 caddr_t data;
1564 {
1565 int s, error = 0;
1566 int len;
1567 struct wi_softc *sc = ifp->if_softc;
1568 struct wi_req wreq;
1569 struct ifreq *ifr;
1570 struct proc *p = curproc;
1571 struct ieee80211_nwid nwid;
1572
1573 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
1574 return (ENXIO);
1575
1576 s = splnet();
1577
1578 ifr = (struct ifreq *)data;
1579 switch (command) {
1580 case SIOCSIFADDR:
1581 case SIOCGIFADDR:
1582 case SIOCSIFMTU:
1583 error = ether_ioctl(ifp, command, data);
1584 break;
1585 case SIOCSIFFLAGS:
1586 if (ifp->if_flags & IFF_UP) {
1587 if (ifp->if_flags & IFF_RUNNING &&
1588 ifp->if_flags & IFF_PROMISC &&
1589 !(sc->wi_if_flags & IFF_PROMISC)) {
1590 WI_SETVAL(WI_RID_PROMISC, 1);
1591 } else if (ifp->if_flags & IFF_RUNNING &&
1592 !(ifp->if_flags & IFF_PROMISC) &&
1593 sc->wi_if_flags & IFF_PROMISC) {
1594 WI_SETVAL(WI_RID_PROMISC, 0);
1595 }
1596 wi_init(ifp);
1597 } else {
1598 if (ifp->if_flags & IFF_RUNNING) {
1599 wi_stop(ifp, 0);
1600 }
1601 }
1602 sc->wi_if_flags = ifp->if_flags;
1603
1604 if (!(ifp->if_flags & IFF_UP)) {
1605 if (sc->sc_enabled) {
1606 if (sc->sc_disable)
1607 (*sc->sc_disable)(sc);
1608 sc->sc_enabled = 0;
1609 ifp->if_flags &= ~IFF_RUNNING;
1610 }
1611 }
1612 error = 0;
1613 break;
1614 case SIOCADDMULTI:
1615 case SIOCDELMULTI:
1616 error = (command == SIOCADDMULTI) ?
1617 ether_addmulti(ifr, &sc->sc_ethercom) :
1618 ether_delmulti(ifr, &sc->sc_ethercom);
1619 if (error == ENETRESET) {
1620 if (sc->sc_enabled != 0) {
1621 /*
1622 * Multicast list has changed. Set the
1623 * hardware filter accordingly.
1624 */
1625 wi_setmulti(sc);
1626 }
1627 error = 0;
1628 }
1629 break;
1630 case SIOCSIFMEDIA:
1631 case SIOCGIFMEDIA:
1632 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1633 break;
1634 case SIOCGWAVELAN:
1635 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1636 if (error)
1637 break;
1638 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1639 memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
1640 sizeof(sc->wi_stats));
1641 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1642 } else if (wreq.wi_type == WI_RID_READ_APS) {
1643 if (sc->wi_scanning) {
1644 error = EINPROGRESS;
1645 break;
1646 } else {
1647 len = sc->wi_naps * sizeof(struct wi_apinfo);
1648 len = len > WI_MAX_DATALEN ? WI_MAX_DATALEN : len;
1649 len = len / sizeof(struct wi_apinfo);
1650 memcpy((char *)&wreq.wi_val, (char *)&len, sizeof(len));
1651 memcpy((char *)&wreq.wi_val + sizeof(len),
1652 (char *)&sc->wi_aps,
1653 len * sizeof(struct wi_apinfo));
1654 }
1655 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
1656 /* For non-root user, return all-zeroes keys */
1657 if (suser(p->p_ucred, &p->p_acflag))
1658 memset((char *)&wreq, 0,
1659 sizeof(struct wi_ltv_keys));
1660 else
1661 memcpy((char *)&wreq, (char *)&sc->wi_keys,
1662 sizeof(struct wi_ltv_keys));
1663 } else {
1664 if (sc->sc_enabled == 0)
1665 error = wi_getdef(sc, &wreq);
1666 else if (wreq.wi_len > WI_MAX_DATALEN)
1667 error = EINVAL;
1668 else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
1669 error = EINVAL;
1670 }
1671 if (error == 0)
1672 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1673 break;
1674 case SIOCSWAVELAN:
1675 error = suser(p->p_ucred, &p->p_acflag);
1676 if (error)
1677 break;
1678 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1679 if (error)
1680 break;
1681 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1682 if (sc->sc_enabled)
1683 wi_inquire(sc);
1684 break;
1685 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1686 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1687 wreq.wi_len);
1688 } else if (wreq.wi_type == WI_RID_SCAN_APS) {
1689 if (wreq.wi_len != 4) {
1690 error = EINVAL;
1691 break;
1692 }
1693 if (!sc->wi_scanning) {
1694 switch (sc->sc_firmware_type) {
1695 case WI_LUCENT:
1696 break;
1697 case WI_INTERSIL:
1698 wreq.wi_type = WI_RID_SCAN_REQ;
1699 error = wi_write_record(sc,
1700 (struct wi_ltv_gen *)&wreq);
1701 break;
1702 case WI_SYMBOL:
1703 /*
1704 * XXX only supported on 3.x ?
1705 */
1706 wreq.wi_type = WI_RID_BCAST_SCAN_REQ;
1707 wreq.wi_val[0] =
1708 BSCAN_BCAST | BSCAN_ONETIME;
1709 wreq.wi_len = 2;
1710 error = wi_write_record(sc,
1711 (struct wi_ltv_gen *)&wreq);
1712 break;
1713 }
1714 if (!error) {
1715 sc->wi_scanning = 1;
1716 callout_reset(&sc->wi_scan_sh, hz * 1,
1717 wi_wait_scan, sc);
1718 }
1719 }
1720 } else {
1721 /*
1722 * Filter stuff out based on what the
1723 * card can do.
1724 */
1725 if ((wreq.wi_type == WI_RID_ROAMING_MODE &&
1726 (sc->wi_flags & WI_FLAGS_HAS_ROAMING) == 0) ||
1727 (wreq.wi_type == WI_RID_CREATE_IBSS &&
1728 (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0) ||
1729 (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
1730 (sc->wi_flags & WI_FLAGS_HAS_MOR) == 0))
1731 break;
1732
1733 if (wreq.wi_len > WI_MAX_DATALEN)
1734 error = EINVAL;
1735 else if (sc->sc_enabled != 0)
1736 error = wi_write_record(sc,
1737 (struct wi_ltv_gen *)&wreq);
1738 if (error == 0)
1739 error = wi_setdef(sc, &wreq);
1740 if (error == 0 && sc->sc_enabled != 0)
1741 /* Reinitialize WaveLAN. */
1742 wi_init(ifp);
1743 }
1744 break;
1745 case SIOCG80211NWID:
1746 if (sc->sc_enabled == 0) {
1747 /* Return the desired ID */
1748 error = copyout(&sc->wi_netid, ifr->ifr_data,
1749 sizeof(sc->wi_netid));
1750 } else {
1751 wreq.wi_type = WI_RID_CURRENT_SSID;
1752 wreq.wi_len = WI_MAX_DATALEN;
1753 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
1754 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
1755 error = EINVAL;
1756 else {
1757 wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
1758 le16toh(wreq.wi_val[0]));
1759 error = copyout(&nwid, ifr->ifr_data,
1760 sizeof(nwid));
1761 }
1762 }
1763 break;
1764 case SIOCS80211NWID:
1765 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
1766 if (error != 0)
1767 break;
1768 if (nwid.i_len > IEEE80211_NWID_LEN) {
1769 error = EINVAL;
1770 break;
1771 }
1772 if (sc->wi_netid.i_len == nwid.i_len &&
1773 memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
1774 break;
1775 wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
1776 if (sc->sc_enabled != 0)
1777 /* Reinitialize WaveLAN. */
1778 wi_init(ifp);
1779 break;
1780 case SIOCS80211NWKEY:
1781 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1782 break;
1783 case SIOCG80211NWKEY:
1784 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1785 break;
1786 case SIOCS80211POWER:
1787 error = wi_set_pm(sc, (struct ieee80211_power *)data);
1788 break;
1789 case SIOCG80211POWER:
1790 error = wi_get_pm(sc, (struct ieee80211_power *)data);
1791 break;
1792
1793 default:
1794 error = EINVAL;
1795 break;
1796 }
1797
1798 splx(s);
1799 return (error);
1800 }
1801
1802 static int
1803 wi_init(ifp)
1804 struct ifnet *ifp;
1805 {
1806 struct wi_softc *sc = ifp->if_softc;
1807 struct wi_req wreq;
1808 struct wi_ltv_macaddr mac;
1809 int error, id = 0, wasenabled;
1810
1811 wasenabled = sc->sc_enabled;
1812 if (!sc->sc_enabled) {
1813 if ((error = (*sc->sc_enable)(sc)) != 0)
1814 goto out;
1815 sc->sc_enabled = 1;
1816 }
1817
1818 wi_stop(ifp, 0);
1819 /* Symbol firmware cannot be initialized more than once */
1820 if (!(sc->sc_firmware_type == WI_SYMBOL && wasenabled))
1821 wi_reset(sc);
1822
1823 /* Program max data length. */
1824 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1825
1826 /* Enable/disable IBSS creation. */
1827 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1828
1829 /* Set the port type. */
1830 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1831
1832 /* Program the RTS/CTS threshold. */
1833 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1834
1835 /* Program the TX rate */
1836 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1837
1838 /* Access point density */
1839 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1840
1841 /* Power Management Enabled */
1842 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1843
1844 /* Power Managment Max Sleep */
1845 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1846
1847 /* Roaming type */
1848 if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
1849 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
1850
1851 /* Specify the network name */
1852 wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
1853
1854 /* Specify the IBSS name */
1855 if (sc->wi_netid.i_len != 0 &&
1856 (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS))
1857 wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_netid);
1858 else
1859 wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
1860
1861 /* Specify the frequency to use */
1862 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1863
1864 /* Program the nodename. */
1865 wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
1866
1867 /* Set our MAC address. */
1868 mac.wi_len = 4;
1869 mac.wi_type = WI_RID_MAC_NODE;
1870 memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
1871 wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1872
1873 /* Initialize promisc mode. */
1874 if (ifp->if_flags & IFF_PROMISC) {
1875 WI_SETVAL(WI_RID_PROMISC, 1);
1876 } else {
1877 WI_SETVAL(WI_RID_PROMISC, 0);
1878 }
1879
1880 /* Configure WEP. */
1881 if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
1882 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1883 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1884 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1885 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1886 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1887 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
1888 /*
1889 * ONLY HWB3163 EVAL-CARD Firmware version
1890 * less than 0.8 variant2
1891 *
1892 * If promiscuous mode disable, Prism2 chip
1893 * does not work with WEP .
1894 * It is under investigation for details.
1895 * (ichiro (at) netbsd.org)
1896 */
1897 if (sc->sc_firmware_type == WI_INTERSIL &&
1898 sc->sc_sta_firmware_ver < 802 ) {
1899 /* firm ver < 0.8 variant 2 */
1900 WI_SETVAL(WI_RID_PROMISC, 1);
1901 }
1902 WI_SETVAL(WI_RID_AUTH_CNTL, sc->wi_authtype);
1903 }
1904 }
1905
1906 /* Set multicast filter. */
1907 wi_setmulti(sc);
1908
1909 /* Enable desired port */
1910 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
1911
1912 /* scanning variable is modal, therefore reinit to OFF, in case it was on. */
1913 sc->wi_scanning=0;
1914 sc->wi_naps=0;
1915
1916 if ((error = wi_alloc_nicmem(sc,
1917 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
1918 printf("%s: tx buffer allocation failed\n",
1919 sc->sc_dev.dv_xname);
1920 goto out;
1921 }
1922 sc->wi_tx_data_id = id;
1923
1924 if ((error = wi_alloc_nicmem(sc,
1925 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
1926 printf("%s: mgmt. buffer allocation failed\n",
1927 sc->sc_dev.dv_xname);
1928 goto out;
1929 }
1930 sc->wi_tx_mgmt_id = id;
1931
1932 /* Enable interrupts */
1933 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1934
1935 ifp->if_flags |= IFF_RUNNING;
1936 ifp->if_flags &= ~IFF_OACTIVE;
1937
1938 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
1939
1940 out:
1941 if (error) {
1942 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1943 ifp->if_timer = 0;
1944 printf("%s: interface not running\n", sc->sc_dev.dv_xname);
1945 }
1946 return (error);
1947 }
1948
1949 static void
1950 wi_start(ifp)
1951 struct ifnet *ifp;
1952 {
1953 struct wi_softc *sc;
1954 struct mbuf *m0;
1955 struct wi_frame tx_frame;
1956 struct ether_header *eh;
1957 int id;
1958
1959 sc = ifp->if_softc;
1960
1961 if (ifp->if_flags & IFF_OACTIVE)
1962 return;
1963
1964 IFQ_DEQUEUE(&ifp->if_snd, m0);
1965 if (m0 == NULL)
1966 return;
1967
1968 memset((char *)&tx_frame, 0, sizeof(tx_frame));
1969 id = sc->wi_tx_data_id;
1970 eh = mtod(m0, struct ether_header *);
1971
1972 /*
1973 * Use RFC1042 encoding for IP and ARP datagrams,
1974 * 802.3 for anything else.
1975 */
1976 if (eh->ether_type == htons(ETHERTYPE_IP) ||
1977 eh->ether_type == htons(ETHERTYPE_ARP) ||
1978 eh->ether_type == htons(ETHERTYPE_REVARP) ||
1979 eh->ether_type == htons(ETHERTYPE_IPV6)) {
1980 memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost,
1981 ETHER_ADDR_LEN);
1982 memcpy((char *)&tx_frame.wi_addr2, (char *)&eh->ether_shost,
1983 ETHER_ADDR_LEN);
1984 memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost,
1985 ETHER_ADDR_LEN);
1986 memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost,
1987 ETHER_ADDR_LEN);
1988
1989 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1990 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
1991 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
1992 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
1993 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1994 tx_frame.wi_type = eh->ether_type;
1995
1996 m_copydata(m0, sizeof(struct ether_header),
1997 m0->m_pkthdr.len - sizeof(struct ether_header),
1998 (caddr_t)&sc->wi_txbuf);
1999
2000 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2001 sizeof(struct wi_frame));
2002 wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
2003 (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
2004 } else {
2005 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
2006
2007 m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
2008
2009 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2010 sizeof(struct wi_frame));
2011 wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
2012 m0->m_pkthdr.len + 2);
2013 }
2014
2015 #if NBPFILTER > 0
2016 /*
2017 * If there's a BPF listener, bounce a copy of
2018 * this frame to him.
2019 */
2020 if (ifp->if_bpf)
2021 bpf_mtap(ifp->if_bpf, m0);
2022 #endif
2023
2024 m_freem(m0);
2025
2026 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
2027 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
2028
2029 ifp->if_flags |= IFF_OACTIVE;
2030
2031 /*
2032 * Set a timeout in case the chip goes out to lunch.
2033 */
2034 ifp->if_timer = 5;
2035
2036 return;
2037 }
2038
2039 static int
2040 wi_mgmt_xmit(sc, data, len)
2041 struct wi_softc *sc;
2042 caddr_t data;
2043 int len;
2044 {
2045 struct wi_frame tx_frame;
2046 int id;
2047 struct wi_80211_hdr *hdr;
2048 caddr_t dptr;
2049
2050 hdr = (struct wi_80211_hdr *)data;
2051 dptr = data + sizeof(struct wi_80211_hdr);
2052
2053 memset((char *)&tx_frame, 0, sizeof(tx_frame));
2054 id = sc->wi_tx_mgmt_id;
2055
2056 memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr,
2057 sizeof(struct wi_80211_hdr));
2058
2059 tx_frame.wi_dat_len = htole16(len - WI_SNAPHDR_LEN);
2060 tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
2061
2062 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2063 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2064 (len - sizeof(struct wi_80211_hdr)) + 2);
2065
2066 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
2067 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
2068 return(EIO);
2069 }
2070
2071 return(0);
2072 }
2073
2074 static void
2075 wi_stop(ifp, disable)
2076 struct ifnet *ifp;
2077 {
2078 struct wi_softc *sc = ifp->if_softc;
2079
2080 CSR_WRITE_2(sc, WI_INT_EN, 0);
2081 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
2082
2083 callout_stop(&sc->wi_inquire_ch);
2084 callout_stop(&sc->wi_scan_sh);
2085
2086 if (disable) {
2087 if (sc->sc_enabled) {
2088 if (sc->sc_disable)
2089 (*sc->sc_disable)(sc);
2090 sc->sc_enabled = 0;
2091 }
2092 }
2093
2094 ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
2095 ifp->if_timer = 0;
2096 }
2097
2098 static void
2099 wi_watchdog(ifp)
2100 struct ifnet *ifp;
2101 {
2102 struct wi_softc *sc;
2103
2104 sc = ifp->if_softc;
2105
2106 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
2107
2108 wi_init(ifp);
2109
2110 ifp->if_oerrors++;
2111
2112 return;
2113 }
2114
2115 void
2116 wi_shutdown(sc)
2117 struct wi_softc *sc;
2118 {
2119 int s;
2120
2121 s = splnet();
2122 if (sc->sc_enabled) {
2123 if (sc->sc_disable)
2124 (*sc->sc_disable)(sc);
2125 sc->sc_enabled = 0;
2126 }
2127 splx(s);
2128 }
2129
2130 int
2131 wi_activate(self, act)
2132 struct device *self;
2133 enum devact act;
2134 {
2135 struct wi_softc *sc = (struct wi_softc *)self;
2136 int rv = 0, s;
2137
2138 s = splnet();
2139 switch (act) {
2140 case DVACT_ACTIVATE:
2141 rv = EOPNOTSUPP;
2142 break;
2143
2144 case DVACT_DEACTIVATE:
2145 if_deactivate(&sc->sc_ethercom.ec_if);
2146 break;
2147 }
2148 splx(s);
2149 return (rv);
2150 }
2151
2152 static void
2153 wi_get_id(sc)
2154 struct wi_softc *sc;
2155 {
2156 struct wi_ltv_ver ver;
2157 struct wi_card_ident *id;
2158
2159 /* getting chip identity */
2160 memset(&ver, 0, sizeof(ver));
2161 ver.wi_type = WI_RID_CARD_ID;
2162 ver.wi_len = 5;
2163 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2164 printf("%s: using ", sc->sc_dev.dv_xname);
2165
2166 sc->sc_firmware_type = WI_NOTYPE;
2167 for (id = wi_card_ident; id->card_name != NULL; id++) {
2168 if (le16toh(ver.wi_ver[0]) == id->card_id) {
2169 printf("%s", id->card_name);
2170 sc->sc_firmware_type = id->firm_type;
2171 break;
2172 }
2173 }
2174 if (sc->sc_firmware_type == WI_NOTYPE) {
2175 if (le16toh(ver.wi_ver[0]) & 0x8000) {
2176 printf("Unknown PRISM2 chip");
2177 sc->sc_firmware_type = WI_INTERSIL;
2178 } else {
2179 printf("Unknown Lucent chip");
2180 sc->sc_firmware_type = WI_LUCENT;
2181 }
2182 }
2183
2184 /* get primary firmware version (Only Prism chips) */
2185 if (sc->sc_firmware_type != WI_LUCENT) {
2186 memset(&ver, 0, sizeof(ver));
2187 ver.wi_type = WI_RID_PRI_IDENTITY;
2188 ver.wi_len = 5;
2189 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2190 LE16TOH(ver.wi_ver[1]);
2191 LE16TOH(ver.wi_ver[2]);
2192 LE16TOH(ver.wi_ver[3]);
2193 sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
2194 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2195 }
2196
2197 /* get station firmware version */
2198 memset(&ver, 0, sizeof(ver));
2199 ver.wi_type = WI_RID_STA_IDENTITY;
2200 ver.wi_len = 5;
2201 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2202 LE16TOH(ver.wi_ver[1]);
2203 LE16TOH(ver.wi_ver[2]);
2204 LE16TOH(ver.wi_ver[3]);
2205 sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2206 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2207 if (sc->sc_firmware_type == WI_INTERSIL &&
2208 (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2209 struct wi_ltv_str sver;
2210 char *p;
2211
2212 memset(&sver, 0, sizeof(sver));
2213 sver.wi_type = WI_RID_SYMBOL_IDENTITY;
2214 sver.wi_len = 7;
2215 /* value should be the format like "V2.00-11" */
2216 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2217 *(p = (char *)sver.wi_str) >= 'A' &&
2218 p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2219 sc->sc_firmware_type = WI_SYMBOL;
2220 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2221 (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2222 (p[6] - '0') * 10 + (p[7] - '0');
2223 }
2224 }
2225
2226 printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
2227 sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
2228 (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
2229 if (sc->sc_firmware_type != WI_LUCENT) /* XXX */
2230 printf("Primary (%u.%u.%u), ", sc->sc_pri_firmware_ver / 10000,
2231 (sc->sc_pri_firmware_ver % 10000) / 100,
2232 sc->sc_pri_firmware_ver % 100);
2233 printf("Station (%u.%u.%u)\n",
2234 sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
2235 sc->sc_sta_firmware_ver % 100);
2236
2237 return;
2238 }
2239
2240 int
2241 wi_detach(sc)
2242 struct wi_softc *sc;
2243 {
2244 struct ifnet *ifp = sc->sc_ifp;
2245 int s;
2246
2247 if (!sc->sc_attached)
2248 return (0);
2249
2250 s = splnet();
2251 callout_stop(&sc->wi_inquire_ch);
2252
2253 /* Delete all remaining media. */
2254 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
2255
2256 ether_ifdetach(ifp);
2257 if_detach(ifp);
2258 if (sc->sc_enabled) {
2259 if (sc->sc_disable)
2260 (*sc->sc_disable)(sc);
2261 sc->sc_enabled = 0;
2262 }
2263 splx(s);
2264 return (0);
2265 }
2266
2267 void
2268 wi_power(sc, why)
2269 struct wi_softc *sc;
2270 int why;
2271 {
2272 int s;
2273
2274 if (!sc->sc_enabled)
2275 return;
2276
2277 s = splnet();
2278 switch (why) {
2279 case PWR_SUSPEND:
2280 case PWR_STANDBY:
2281 wi_stop(sc->sc_ifp, 0);
2282 if (sc->sc_enabled) {
2283 if (sc->sc_disable)
2284 (*sc->sc_disable)(sc);
2285 }
2286 break;
2287 case PWR_RESUME:
2288 sc->sc_enabled = 0;
2289 wi_init(sc->sc_ifp);
2290 (void)wi_intr(sc);
2291 break;
2292 case PWR_SOFTSUSPEND:
2293 case PWR_SOFTSTANDBY:
2294 case PWR_SOFTRESUME:
2295 break;
2296 }
2297 splx(s);
2298 }
2299
2300 static int
2301 wi_set_ssid(ws, id, len)
2302 struct ieee80211_nwid *ws;
2303 u_int8_t *id;
2304 int len;
2305 {
2306
2307 if (len > IEEE80211_NWID_LEN)
2308 return (EINVAL);
2309 ws->i_len = len;
2310 memcpy(ws->i_nwid, id, len);
2311 return (0);
2312 }
2313
2314 static void
2315 wi_request_fill_ssid(wreq, ws)
2316 struct wi_req *wreq;
2317 struct ieee80211_nwid *ws;
2318 {
2319 int len = ws->i_len;
2320
2321 memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
2322 wreq->wi_val[0] = htole16(len);
2323 wreq->wi_len = roundup(len, 2) / 2 + 2;
2324 memcpy(&wreq->wi_val[1], ws->i_nwid, len);
2325 }
2326
2327 static int
2328 wi_write_ssid(sc, type, wreq, ws)
2329 struct wi_softc *sc;
2330 int type;
2331 struct wi_req *wreq;
2332 struct ieee80211_nwid *ws;
2333 {
2334
2335 wreq->wi_type = type;
2336 wi_request_fill_ssid(wreq, ws);
2337 return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
2338 }
2339
2340 static int
2341 wi_sync_media(sc, ptype, txrate)
2342 struct wi_softc *sc;
2343 int ptype;
2344 int txrate;
2345 {
2346 int media = sc->sc_media.ifm_cur->ifm_media;
2347 int options = IFM_OPTIONS(media);
2348 int subtype;
2349
2350 switch (txrate) {
2351 case 1:
2352 subtype = IFM_IEEE80211_DS1;
2353 break;
2354 case 2:
2355 subtype = IFM_IEEE80211_DS2;
2356 break;
2357 case 3:
2358 subtype = IFM_AUTO;
2359 break;
2360 case 5:
2361 subtype = IFM_IEEE80211_DS5;
2362 break;
2363 case 11:
2364 subtype = IFM_IEEE80211_DS11;
2365 break;
2366 default:
2367 subtype = IFM_MANUAL; /* Unable to represent */
2368 break;
2369 }
2370
2371 options &= ~IFM_OMASK;
2372 switch (ptype) {
2373 case WI_PORTTYPE_BSS:
2374 /* default port type */
2375 break;
2376 case WI_PORTTYPE_ADHOC:
2377 options |= IFM_IEEE80211_ADHOC;
2378 break;
2379 case WI_PORTTYPE_IBSS:
2380 if (sc->wi_create_ibss)
2381 options |= IFM_IEEE80211_IBSSMASTER;
2382 else
2383 options |= IFM_IEEE80211_IBSS;
2384 break;
2385 default:
2386 subtype = IFM_MANUAL; /* Unable to represent */
2387 break;
2388 }
2389 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
2390 IFM_INST(media));
2391 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
2392 return (EINVAL);
2393 ifmedia_set(&sc->sc_media, media);
2394 sc->wi_ptype = ptype;
2395 sc->wi_tx_rate = txrate;
2396 return (0);
2397 }
2398
2399 static int
2400 wi_media_change(ifp)
2401 struct ifnet *ifp;
2402 {
2403 struct wi_softc *sc = ifp->if_softc;
2404 int otype = sc->wi_ptype;
2405 int orate = sc->wi_tx_rate;
2406 int ocreate_ibss = sc->wi_create_ibss;
2407
2408 sc->wi_create_ibss = 0;
2409
2410 switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
2411 case 0:
2412 sc->wi_ptype = WI_PORTTYPE_BSS;
2413 break;
2414 case IFM_IEEE80211_ADHOC:
2415 sc->wi_ptype = WI_PORTTYPE_ADHOC;
2416 break;
2417 case IFM_IEEE80211_IBSSMASTER:
2418 case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
2419 if ((sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0)
2420 return (EINVAL);
2421 sc->wi_create_ibss = 1;
2422 /* FALLTHROUGH */
2423 case IFM_IEEE80211_IBSS:
2424 sc->wi_ptype = WI_PORTTYPE_IBSS;
2425 break;
2426 default:
2427 /* Invalid combination. */
2428 sc->wi_create_ibss = ocreate_ibss;
2429 return (EINVAL);
2430 }
2431
2432 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
2433 case IFM_IEEE80211_DS1:
2434 sc->wi_tx_rate = 1;
2435 break;
2436 case IFM_IEEE80211_DS2:
2437 sc->wi_tx_rate = 2;
2438 break;
2439 case IFM_AUTO:
2440 sc->wi_tx_rate = 3;
2441 break;
2442 case IFM_IEEE80211_DS5:
2443 sc->wi_tx_rate = 5;
2444 break;
2445 case IFM_IEEE80211_DS11:
2446 sc->wi_tx_rate = 11;
2447 break;
2448 }
2449
2450 if (sc->sc_enabled != 0) {
2451 if (otype != sc->wi_ptype ||
2452 orate != sc->wi_tx_rate ||
2453 ocreate_ibss != sc->wi_create_ibss)
2454 wi_init(ifp);
2455 }
2456
2457 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2458
2459 return (0);
2460 }
2461
2462 static void
2463 wi_media_status(ifp, imr)
2464 struct ifnet *ifp;
2465 struct ifmediareq *imr;
2466 {
2467 struct wi_softc *sc = ifp->if_softc;
2468
2469 if (sc->sc_enabled == 0) {
2470 imr->ifm_active = IFM_IEEE80211|IFM_NONE;
2471 imr->ifm_status = 0;
2472 return;
2473 }
2474
2475 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2476 imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
2477 }
2478
2479 static int
2480 wi_set_nwkey(sc, nwkey)
2481 struct wi_softc *sc;
2482 struct ieee80211_nwkey *nwkey;
2483 {
2484 int i, error;
2485 size_t len;
2486 struct wi_req wreq;
2487 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
2488
2489 if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
2490 return ENODEV;
2491 if (nwkey->i_defkid <= 0 ||
2492 nwkey->i_defkid > IEEE80211_WEP_NKID)
2493 return EINVAL;
2494 memcpy(wk, &sc->wi_keys, sizeof(*wk));
2495 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2496 if (nwkey->i_key[i].i_keydat == NULL)
2497 continue;
2498 len = nwkey->i_key[i].i_keylen;
2499 if (len > sizeof(wk->wi_keys[i].wi_keydat))
2500 return EINVAL;
2501 error = copyin(nwkey->i_key[i].i_keydat,
2502 wk->wi_keys[i].wi_keydat, len);
2503 if (error)
2504 return error;
2505 wk->wi_keys[i].wi_keylen = htole16(len);
2506 }
2507
2508 wk->wi_len = (sizeof(*wk) / 2) + 1;
2509 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2510 if (sc->sc_enabled != 0) {
2511 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2512 if (error)
2513 return error;
2514 }
2515 error = wi_setdef(sc, &wreq);
2516 if (error)
2517 return error;
2518
2519 wreq.wi_len = 2;
2520 wreq.wi_type = WI_RID_TX_CRYPT_KEY;
2521 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
2522 if (sc->sc_enabled != 0) {
2523 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2524 if (error)
2525 return error;
2526 }
2527 error = wi_setdef(sc, &wreq);
2528 if (error)
2529 return error;
2530
2531 wreq.wi_type = WI_RID_ENCRYPTION;
2532 wreq.wi_val[0] = htole16(nwkey->i_wepon);
2533 if (sc->sc_enabled != 0) {
2534 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2535 if (error)
2536 return error;
2537 }
2538 error = wi_setdef(sc, &wreq);
2539 if (error)
2540 return error;
2541
2542 if (sc->sc_enabled != 0)
2543 wi_init(&sc->sc_ethercom.ec_if);
2544 return 0;
2545 }
2546
2547 static int
2548 wi_get_nwkey(sc, nwkey)
2549 struct wi_softc *sc;
2550 struct ieee80211_nwkey *nwkey;
2551 {
2552 int i, len, error;
2553 struct wi_ltv_keys *wk = &sc->wi_keys;
2554
2555 if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
2556 return ENODEV;
2557 nwkey->i_wepon = sc->wi_use_wep;
2558 nwkey->i_defkid = sc->wi_tx_key + 1;
2559
2560 /* do not show any keys to non-root user */
2561 error = suser(curproc->p_ucred, &curproc->p_acflag);
2562 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2563 if (nwkey->i_key[i].i_keydat == NULL)
2564 continue;
2565 /* error holds results of suser() for the first time */
2566 if (error)
2567 return error;
2568 len = le16toh(wk->wi_keys[i].wi_keylen);
2569 if (nwkey->i_key[i].i_keylen < len)
2570 return ENOSPC;
2571 nwkey->i_key[i].i_keylen = len;
2572 error = copyout(wk->wi_keys[i].wi_keydat,
2573 nwkey->i_key[i].i_keydat, len);
2574 if (error)
2575 return error;
2576 }
2577 return 0;
2578 }
2579
2580 static int
2581 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2582 {
2583
2584 sc->wi_pm_enabled = power->i_enabled;
2585 sc->wi_max_sleep = power->i_maxsleep;
2586
2587 if (sc->sc_enabled)
2588 return (wi_init(&sc->sc_ethercom.ec_if));
2589
2590 return (0);
2591 }
2592
2593 static int
2594 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2595 {
2596
2597 power->i_enabled = sc->wi_pm_enabled;
2598 power->i_maxsleep = sc->wi_max_sleep;
2599
2600 return (0);
2601 }
2602