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