bbc0ac61d2929adb735d85864b2bce8f20155d7c
[dragonfly.git] / sys / dev / netif / wi / if_wi.c
1 /*      $NetBSD: wi.c,v 1.109 2003/01/09 08:52:19 dyoung Exp $  */
2
3 /*
4  * Copyright (c) 1997, 1998, 1999
5  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Bill Paul.
18  * 4. Neither the name of the author nor the names of any co-contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * $FreeBSD: src/sys/dev/wi/if_wi.c,v 1.166 2004/04/01 00:38:45 sam Exp $
35  * $DragonFly: src/sys/dev/netif/wi/if_wi.c,v 1.33 2005/12/16 21:05:48 dillon Exp $
36  */
37
38 /*
39  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver.
40  *
41  * Original FreeBSD driver written by Bill Paul <wpaul@ctr.columbia.edu>
42  * Electrical Engineering Department
43  * Columbia University, New York City
44  */
45
46 /*
47  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
48  * from Lucent. Unlike the older cards, the new ones are programmed
49  * entirely via a firmware-driven controller called the Hermes.
50  * Unfortunately, Lucent will not release the Hermes programming manual
51  * without an NDA (if at all). What they do release is an API library
52  * called the HCF (Hardware Control Functions) which is supposed to
53  * do the device-specific operations of a device driver for you. The
54  * publically available version of the HCF library (the 'HCF Light') is 
55  * a) extremely gross, b) lacks certain features, particularly support
56  * for 802.11 frames, and c) is contaminated by the GNU Public License.
57  *
58  * This driver does not use the HCF or HCF Light at all. Instead, it
59  * programs the Hermes controller directly, using information gleaned
60  * from the HCF Light code and corresponding documentation.
61  *
62  * This driver supports the ISA, PCMCIA and PCI versions of the Lucent
63  * WaveLan cards (based on the Hermes chipset), as well as the newer
64  * Prism 2 chipsets with firmware from Intersil and Symbol.
65  */
66
67 #define WI_HERMES_AUTOINC_WAR   /* Work around data write autoinc bug. */
68 #define WI_HERMES_STATS_WAR     /* Work around stats counter bug. */
69
70 #include "opt_polling.h"
71
72 #include <sys/param.h>
73 #include <sys/endian.h>
74 #include <sys/systm.h>
75 #include <sys/sockio.h>
76 #include <sys/mbuf.h>
77 #include <sys/proc.h>
78 #include <sys/kernel.h>
79 #include <sys/socket.h>
80 #include <sys/module.h>
81 #include <sys/bus.h>
82 #include <sys/random.h>
83 #include <sys/syslog.h>
84 #include <sys/sysctl.h>
85 #include <sys/serialize.h>
86 #include <sys/thread2.h>
87
88 #include <machine/bus.h>
89 #include <machine/resource.h>
90 #include <machine/atomic.h>
91 #include <sys/rman.h>
92
93 #include <net/if.h>
94 #include <net/if_arp.h>
95 #include <net/ethernet.h>
96 #include <net/if_dl.h>
97 #include <net/if_media.h>
98 #include <net/if_types.h>
99 #include <net/ifq_var.h>
100
101 #include <netproto/802_11/ieee80211_var.h>
102 #include <netproto/802_11/ieee80211_ioctl.h>
103 #include <netproto/802_11/ieee80211_radiotap.h>
104 #include <netproto/802_11/if_wavelan_ieee.h>
105
106 #include <netinet/in.h>
107 #include <netinet/in_systm.h>
108 #include <netinet/in_var.h>
109 #include <netinet/ip.h>
110 #include <netinet/if_ether.h>
111
112 #include <net/bpf.h>
113
114 #include <dev/netif/wi/if_wireg.h>
115 #include <dev/netif/wi/if_wivar.h>
116
117 static void wi_start(struct ifnet *);
118 static int  wi_reset(struct wi_softc *);
119 static void wi_watchdog(struct ifnet *);
120 static int  wi_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
121 static int  wi_media_change(struct ifnet *);
122 static void wi_media_status(struct ifnet *, struct ifmediareq *);
123
124 static void wi_rx_intr(struct wi_softc *);
125 static void wi_tx_intr(struct wi_softc *);
126 static void wi_tx_ex_intr(struct wi_softc *);
127 static void wi_info_intr(struct wi_softc *);
128
129 static int  wi_get_cfg(struct ifnet *, u_long, caddr_t, struct ucred *);
130 static int  wi_set_cfg(struct ifnet *, u_long, caddr_t);
131 static int  wi_write_txrate(struct wi_softc *);
132 static int  wi_write_wep(struct wi_softc *);
133 static int  wi_write_multi(struct wi_softc *);
134 static int  wi_alloc_fid(struct wi_softc *, int, int *);
135 static void wi_read_nicid(struct wi_softc *);
136 static int  wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
137
138 static int  wi_cmd(struct wi_softc *, int, int, int, int);
139 static int  wi_seek_bap(struct wi_softc *, int, int);
140 static int  wi_read_bap(struct wi_softc *, int, int, void *, int);
141 static int  wi_write_bap(struct wi_softc *, int, int, void *, int);
142 static int  wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
143 static int  wi_read_rid(struct wi_softc *, int, void *, int *);
144 static int  wi_write_rid(struct wi_softc *, int, void *, int);
145
146 static int  wi_newstate(struct ieee80211com *, enum ieee80211_state, int);
147
148 static int  wi_scan_ap(struct wi_softc *, u_int16_t, u_int16_t);
149 static void wi_scan_result(struct wi_softc *, int, int);
150
151 static void wi_dump_pkt(struct wi_frame *, struct ieee80211_node *, int rssi);
152
153 static int wi_get_debug(struct wi_softc *, struct wi_req *);
154 static int wi_set_debug(struct wi_softc *, struct wi_req *);
155
156 /* support to download firmware for symbol CF card */
157 static int wi_symbol_write_firm(struct wi_softc *, const void *, int,
158                 const void *, int);
159 static int wi_symbol_set_hcr(struct wi_softc *, int);
160 #ifdef DEVICE_POLLING
161 static void wi_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
162 #endif
163
164 static __inline int
165 wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
166 {
167
168         val = htole16(val);
169         return wi_write_rid(sc, rid, &val, sizeof(val));
170 }
171
172 SYSCTL_NODE(_hw, OID_AUTO, wi, CTLFLAG_RD, 0, "Wireless driver parameters");
173
174 static  struct timeval lasttxerror;     /* time of last tx error msg */
175 static  int curtxeps;                   /* current tx error msgs/sec */
176 static  int wi_txerate = 0;             /* tx error rate: max msgs/sec */
177 SYSCTL_INT(_hw_wi, OID_AUTO, txerate, CTLFLAG_RW, &wi_txerate,
178             0, "max tx error msgs/sec; 0 to disable msgs");
179
180 #define WI_DEBUG
181 #ifdef WI_DEBUG
182 static  int wi_debug = 0;
183 SYSCTL_INT(_hw_wi, OID_AUTO, debug, CTLFLAG_RW, &wi_debug,
184             0, "control debugging printfs");
185
186 #define DPRINTF(X)      if (wi_debug) if_printf X
187 #define DPRINTF2(X)     if (wi_debug > 1) if_printf X
188 #define IFF_DUMPPKTS(_ifp) \
189         (((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
190 #else
191 #define DPRINTF(X)
192 #define DPRINTF2(X)
193 #define IFF_DUMPPKTS(_ifp)      0
194 #endif
195
196 #define WI_INTRS        (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO)
197
198 struct wi_card_ident wi_card_ident[] = {
199         /* CARD_ID                      CARD_NAME               FIRM_TYPE */
200         { WI_NIC_LUCENT_ID,             WI_NIC_LUCENT_STR,      WI_LUCENT },
201         { WI_NIC_SONY_ID,               WI_NIC_SONY_STR,        WI_LUCENT },
202         { WI_NIC_LUCENT_EMB_ID,         WI_NIC_LUCENT_EMB_STR,  WI_LUCENT },
203         { WI_NIC_EVB2_ID,               WI_NIC_EVB2_STR,        WI_INTERSIL },
204         { WI_NIC_HWB3763_ID,            WI_NIC_HWB3763_STR,     WI_INTERSIL },
205         { WI_NIC_HWB3163_ID,            WI_NIC_HWB3163_STR,     WI_INTERSIL },
206         { WI_NIC_HWB3163B_ID,           WI_NIC_HWB3163B_STR,    WI_INTERSIL },
207         { WI_NIC_EVB3_ID,               WI_NIC_EVB3_STR,        WI_INTERSIL },
208         { WI_NIC_HWB1153_ID,            WI_NIC_HWB1153_STR,     WI_INTERSIL },
209         { WI_NIC_P2_SST_ID,             WI_NIC_P2_SST_STR,      WI_INTERSIL },
210         { WI_NIC_EVB2_SST_ID,           WI_NIC_EVB2_SST_STR,    WI_INTERSIL },
211         { WI_NIC_3842_EVA_ID,           WI_NIC_3842_EVA_STR,    WI_INTERSIL },
212         { WI_NIC_3842_PCMCIA_AMD_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
213         { WI_NIC_3842_PCMCIA_SST_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
214         { WI_NIC_3842_PCMCIA_ATL_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
215         { WI_NIC_3842_PCMCIA_ATS_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
216         { WI_NIC_3842_MINI_AMD_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
217         { WI_NIC_3842_MINI_SST_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
218         { WI_NIC_3842_MINI_ATL_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
219         { WI_NIC_3842_MINI_ATS_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
220         { WI_NIC_3842_PCI_AMD_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
221         { WI_NIC_3842_PCI_SST_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
222         { WI_NIC_3842_PCI_ATS_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
223         { WI_NIC_3842_PCI_ATL_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
224         { WI_NIC_P3_PCMCIA_AMD_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
225         { WI_NIC_P3_PCMCIA_SST_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
226         { WI_NIC_P3_PCMCIA_ATL_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
227         { WI_NIC_P3_PCMCIA_ATS_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
228         { WI_NIC_P3_MINI_AMD_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
229         { WI_NIC_P3_MINI_SST_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
230         { WI_NIC_P3_MINI_ATL_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
231         { WI_NIC_P3_MINI_ATS_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
232         { 0,    NULL,   0 },
233 };
234
235 devclass_t wi_devclass;
236
237 int
238 wi_attach(device_t dev)
239 {
240         struct wi_softc *sc = device_get_softc(dev);
241         struct ieee80211com *ic = &sc->sc_ic;
242         struct ifnet *ifp = &ic->ic_if;
243         int i, nrates, buflen;
244         u_int16_t val;
245         u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
246         struct ieee80211_rateset *rs;
247         static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
248                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
249         };
250         int error;
251
252         ifp->if_softc = sc;
253         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
254
255         sc->wi_cmd_count = 500;
256         /* Reset the NIC. */
257         error = wi_reset(sc);
258         if (error)
259                 goto fail;
260
261         /*
262          * Read the station address.
263          * And do it twice. I've seen PRISM-based cards that return
264          * an error when trying to read it the first time, which causes
265          * the probe to fail.
266          */
267         buflen = IEEE80211_ADDR_LEN;
268         error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
269         if (error != 0) {
270                 buflen = IEEE80211_ADDR_LEN;
271                 error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
272         }
273         if (error) {
274                 device_printf(dev, "mac read failed %d\n", error);
275                 goto fail;
276         }
277         if (IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
278                 device_printf(dev, "mac read failed (all zeros)\n");
279                 error = ENXIO;
280                 goto fail;
281         }
282
283         /* Read NIC identification */
284         wi_read_nicid(sc);
285
286         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
287         ifp->if_ioctl = wi_ioctl;
288         ifp->if_start = wi_start;
289         ifp->if_watchdog = wi_watchdog;
290         ifp->if_init = wi_init;
291         ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
292         ifq_set_ready(&ifp->if_snd);
293 #ifdef DEVICE_POLLING
294         ifp->if_poll = wi_poll;
295 #endif
296         ifp->if_capenable = ifp->if_capabilities;
297
298         ic->ic_phytype = IEEE80211_T_DS;
299         ic->ic_opmode = IEEE80211_M_STA;
300         ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_AHDEMO;
301         ic->ic_state = IEEE80211_S_INIT;
302
303         /*
304          * Query the card for available channels and setup the
305          * channel table.  We assume these are all 11b channels.
306          */
307         buflen = sizeof(val);
308         if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0)
309                 val = htole16(0x1fff);  /* assume 1-11 */
310         KASSERT(val != 0, ("wi_attach: no available channels listed!"));
311
312         val <<= 1;                      /* shift for base 1 indices */
313         for (i = 1; i < 16; i++) {
314                 if (isset((u_int8_t*)&val, i)) {
315                         ic->ic_channels[i].ic_freq =
316                                 ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
317                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
318                 }
319         }
320
321         /*
322          * Read the default channel from the NIC. This may vary
323          * depending on the country where the NIC was purchased, so
324          * we can't hard-code a default and expect it to work for
325          * everyone.
326          *
327          * If no channel is specified, let the 802.11 code select.
328          */
329         buflen = sizeof(val);
330         if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) {
331                 val = le16toh(val);
332                 KASSERT(val < IEEE80211_CHAN_MAX &&
333                         ic->ic_channels[val].ic_flags != 0,
334                         ("wi_attach: invalid own channel %u!", val));
335                 ic->ic_ibss_chan = &ic->ic_channels[val];
336         } else {
337                 device_printf(dev,
338                         "WI_RID_OWN_CHNL failed, using first channel!\n");
339                 ic->ic_ibss_chan = &ic->ic_channels[0];
340         }
341
342         /*
343          * Set flags based on firmware version.
344          */
345         switch (sc->sc_firmware_type) {
346         case WI_LUCENT:
347                 sc->sc_ntxbuf = 1;
348                 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
349 #ifdef WI_HERMES_AUTOINC_WAR
350                 /* XXX: not confirmed, but never seen for recent firmware */
351                 if (sc->sc_sta_firmware_ver <  40000) {
352                         sc->sc_flags |= WI_FLAGS_BUG_AUTOINC;
353                 }
354 #endif
355                 if (sc->sc_sta_firmware_ver >= 60000)
356                         sc->sc_flags |= WI_FLAGS_HAS_MOR;
357                 if (sc->sc_sta_firmware_ver >= 60006) {
358                         ic->ic_caps |= IEEE80211_C_IBSS;
359                         ic->ic_caps |= IEEE80211_C_MONITOR;
360                 }
361                 sc->sc_ibss_port = htole16(1);
362
363                 sc->sc_min_rssi = WI_LUCENT_MIN_RSSI;
364                 sc->sc_max_rssi = WI_LUCENT_MAX_RSSI;
365                 sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
366                 break;
367
368         case WI_INTERSIL:
369                 sc->sc_ntxbuf = WI_NTXBUF;
370                 sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
371                 sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
372                 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
373                 /*
374                  * Old firmware are slow, so give peace a chance.
375                  */
376                 if (sc->sc_sta_firmware_ver < 10000)
377                         sc->wi_cmd_count = 5000;
378                 if (sc->sc_sta_firmware_ver > 10101)
379                         sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
380                 if (sc->sc_sta_firmware_ver >= 800) {
381                         ic->ic_caps |= IEEE80211_C_IBSS;
382                         ic->ic_caps |= IEEE80211_C_MONITOR;
383                 }
384                 /*
385                  * version 0.8.3 and newer are the only ones that are known
386                  * to currently work.  Earlier versions can be made to work,
387                  * at least according to the Linux driver.
388                  */
389                 if (sc->sc_sta_firmware_ver >= 803)
390                         ic->ic_caps |= IEEE80211_C_HOSTAP;
391                 sc->sc_ibss_port = htole16(0);
392
393                 sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
394                 sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
395                 sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
396                 break;
397
398         case WI_SYMBOL:
399                 sc->sc_ntxbuf = 1;
400                 sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
401                 if (sc->sc_sta_firmware_ver >= 25000)
402                         ic->ic_caps |= IEEE80211_C_IBSS;
403                 sc->sc_ibss_port = htole16(4);
404
405                 sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
406                 sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
407                 sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
408                 break;
409         }
410
411         /*
412          * Find out if we support WEP on this card.
413          */
414         buflen = sizeof(val);
415         if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 &&
416             val != htole16(0))
417                 ic->ic_caps |= IEEE80211_C_WEP;
418
419         /* Find supported rates. */
420         buflen = sizeof(ratebuf);
421         rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
422         if (wi_read_rid(sc, WI_RID_DATA_RATES, ratebuf, &buflen) == 0) {
423                 nrates = le16toh(*(u_int16_t *)ratebuf);
424                 if (nrates > IEEE80211_RATE_MAXSIZE)
425                         nrates = IEEE80211_RATE_MAXSIZE;
426                 rs->rs_nrates = 0;
427                 for (i = 0; i < nrates; i++)
428                         if (ratebuf[2+i])
429                                 rs->rs_rates[rs->rs_nrates++] = ratebuf[2+i];
430         } else {
431                 /* XXX fallback on error? */
432                 rs->rs_nrates = 0;
433         }
434
435         buflen = sizeof(val);
436         if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
437             wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0) {
438                 sc->sc_dbm_offset = le16toh(val);
439         }
440
441         sc->sc_max_datalen = 2304;
442         sc->sc_system_scale = 1;
443         sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
444         sc->sc_roaming_mode = 1;
445
446         sc->sc_portnum = WI_DEFAULT_PORT;
447         sc->sc_authtype = WI_DEFAULT_AUTHTYPE;
448
449         bzero(sc->sc_nodename, sizeof(sc->sc_nodename));
450         sc->sc_nodelen = sizeof(WI_DEFAULT_NODENAME) - 1;
451         bcopy(WI_DEFAULT_NODENAME, sc->sc_nodename, sc->sc_nodelen);
452
453         bzero(sc->sc_net_name, sizeof(sc->sc_net_name));
454         bcopy(WI_DEFAULT_NETNAME, sc->sc_net_name,
455             sizeof(WI_DEFAULT_NETNAME) - 1);
456
457         /*
458          * Call MI attach routine.
459          */
460         ieee80211_ifattach(ifp);
461         /* override state transition method */
462         sc->sc_newstate = ic->ic_newstate;
463         ic->ic_newstate = wi_newstate;
464         ieee80211_media_init(ifp, wi_media_change, wi_media_status);
465
466         bpfattach_dlt(ifp, DLT_IEEE802_11_RADIO,
467                 sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th),
468                 &sc->sc_drvbpf);
469         /*
470          * Initialize constant fields.
471          * XXX make header lengths a multiple of 32-bits so subsequent
472          *     headers are properly aligned; this is a kludge to keep
473          *     certain applications happy.
474          *
475          * NB: the channel is setup each time we transition to the
476          *     RUN state to avoid filling it in for each frame.
477          */
478         sc->sc_tx_th_len = roundup(sizeof(sc->sc_tx_th), sizeof(u_int32_t));
479         sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len);
480         sc->sc_tx_th.wt_ihdr.it_present = htole32(WI_TX_RADIOTAP_PRESENT);
481
482         sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(u_int32_t));
483         sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len);
484         sc->sc_rx_th.wr_ihdr.it_present = htole32(WI_RX_RADIOTAP_PRESENT);
485
486
487         error = bus_setup_intr(dev, sc->irq, INTR_MPSAFE,
488                                wi_intr, sc, &sc->wi_intrhand,
489                                ifp->if_serializer);
490         if (error) {
491                 ieee80211_ifdetach(ifp);
492                 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
493                 goto fail;
494         }
495
496         return(0);
497
498 fail:
499         wi_free(dev);
500         return(error);
501 }
502
503 int
504 wi_detach(device_t dev)
505 {
506         struct wi_softc *sc = device_get_softc(dev);
507         struct ifnet *ifp = &sc->sc_ic.ic_if;
508
509         lwkt_serialize_enter(ifp->if_serializer);
510
511         /* check if device was removed */
512         sc->wi_gone |= !bus_child_present(dev);
513
514         wi_stop(ifp, 0);
515
516         ieee80211_ifdetach(ifp);
517         wi_free(dev);
518
519         lwkt_serialize_exit(ifp->if_serializer);
520
521         return (0);
522 }
523
524 void
525 wi_shutdown(device_t dev)
526 {
527         struct wi_softc *sc = device_get_softc(dev);
528         struct ifnet *ifp = &sc->sc_if;
529
530         lwkt_serialize_enter(ifp->if_serializer);
531         wi_stop(ifp, 1);
532         lwkt_serialize_exit(ifp->if_serializer);
533 }
534
535 #ifdef DEVICE_POLLING
536
537 static void
538 wi_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
539 {
540         struct wi_softc *sc = ifp->if_softc;
541         uint16_t status;
542
543         switch(cmd) {
544         case POLL_REGISTER:
545                 /* disable interruptds */
546                 CSR_WRITE_2(sc, WI_INT_EN, 0);
547                 break;
548         case POLL_DEREGISTER:
549                 /* enable interrupts */
550                 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
551                 break;
552         default:
553                 status = CSR_READ_2(sc, WI_EVENT_STAT);
554
555                 if (status & WI_EV_RX)
556                         wi_rx_intr(sc);
557                 if (status & WI_EV_ALLOC)
558                         wi_tx_intr(sc);
559                 if (status & WI_EV_INFO)
560                         wi_info_intr(sc);
561
562                 if (cmd == POLL_AND_CHECK_STATUS) {
563                         if (status & WI_EV_INFO)
564                                 wi_info_intr(sc);
565                 }
566
567                 if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
568                     (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 && !ifq_is_empty(&ifp->if_snd)) {
569                         wi_start(ifp);
570                 }
571                 break;
572         }
573 }
574 #endif /* DEVICE_POLLING */
575
576 void
577 wi_intr(void *arg)
578 {
579         struct wi_softc *sc = arg;
580         struct ifnet *ifp = &sc->sc_ic.ic_if;
581         u_int16_t status;
582
583         if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
584                 CSR_WRITE_2(sc, WI_INT_EN, 0);
585                 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
586                 return;
587         }
588
589         /* Disable interrupts. */
590         CSR_WRITE_2(sc, WI_INT_EN, 0);
591
592         status = CSR_READ_2(sc, WI_EVENT_STAT);
593         if (status & WI_EV_RX)
594                 wi_rx_intr(sc);
595         if (status & WI_EV_ALLOC)
596                 wi_tx_intr(sc);
597         if (status & WI_EV_TX_EXC)
598                 wi_tx_ex_intr(sc);
599         if (status & WI_EV_INFO)
600                 wi_info_intr(sc);
601         if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
602             (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
603             !ifq_is_empty(&ifp->if_snd))
604                 wi_start(ifp);
605
606         /* Re-enable interrupts. */
607         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
608
609         return;
610 }
611
612 void
613 wi_init(void *arg)
614 {
615         struct wi_softc *sc = arg;
616         struct ifnet *ifp = &sc->sc_if;
617         struct ieee80211com *ic = &sc->sc_ic;
618         struct wi_joinreq join;
619         int i;
620         int error = 0, wasenabled;
621
622         if (sc->wi_gone)
623                 return;
624
625         if ((wasenabled = sc->sc_enabled))
626                 wi_stop(ifp, 1);
627         wi_reset(sc);
628
629         /* common 802.11 configuration */
630         ic->ic_flags &= ~IEEE80211_F_IBSSON;
631         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
632         switch (ic->ic_opmode) {
633         case IEEE80211_M_STA:
634                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
635                 break;
636         case IEEE80211_M_IBSS:
637                 wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
638                 ic->ic_flags |= IEEE80211_F_IBSSON;
639                 break;
640         case IEEE80211_M_AHDEMO:
641                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
642                 break;
643         case IEEE80211_M_HOSTAP:
644                 /*
645                  * For PRISM cards, override the empty SSID, because in
646                  * HostAP mode the controller will lock up otherwise.
647                  */
648                 if (sc->sc_firmware_type == WI_INTERSIL &&
649                     ic->ic_des_esslen == 0) {
650                         ic->ic_des_essid[0] = ' ';
651                         ic->ic_des_esslen = 1;
652                 }
653                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
654                 break;
655         case IEEE80211_M_MONITOR:
656                 if (sc->sc_firmware_type == WI_LUCENT)
657                         wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
658                 wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
659                 break;
660         }
661
662         /* Intersil interprets this RID as joining ESS even in IBSS mode */
663         if (sc->sc_firmware_type == WI_LUCENT &&
664             (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0)
665                 wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
666         else
667                 wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
668         wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
669         wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid,
670             ic->ic_des_esslen);
671         wi_write_val(sc, WI_RID_OWN_CHNL,
672                 ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
673         wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen);
674
675         IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
676         wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
677
678         wi_write_val(sc, WI_RID_PM_ENABLED,
679             (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
680
681         /* not yet common 802.11 configuration */
682         wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
683         wi_write_val(sc, WI_RID_RTS_THRESH, ic->ic_rtsthreshold);
684         if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
685                 wi_write_val(sc, WI_RID_FRAG_THRESH, ic->ic_fragthreshold);
686
687         /* driver specific 802.11 configuration */
688         if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)
689                 wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale);
690         if (sc->sc_flags & WI_FLAGS_HAS_ROAMING)
691                 wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode);
692         if (sc->sc_flags & WI_FLAGS_HAS_MOR)
693                 wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven);
694         wi_write_txrate(sc);
695         wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
696
697         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
698             sc->sc_firmware_type == WI_INTERSIL) {
699                 wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_lintval);
700                 wi_write_val(sc, WI_RID_BASIC_RATE, 0x03);   /* 1, 2 */
701                 wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */
702                 wi_write_val(sc, WI_RID_DTIM_PERIOD, 1);
703         }
704
705         /*
706          * Initialize promisc mode.
707          *      Being in the Host-AP mode causes a great
708          *      deal of pain if primisc mode is set.
709          *      Therefore we avoid confusing the firmware
710          *      and always reset promisc mode in Host-AP
711          *      mode.  Host-AP sees all the packets anyway.
712          */
713         if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
714             (ifp->if_flags & IFF_PROMISC) != 0) {
715                 wi_write_val(sc, WI_RID_PROMISC, 1);
716         } else {
717                 wi_write_val(sc, WI_RID_PROMISC, 0);
718         }
719
720         /* Configure WEP. */
721         if (ic->ic_caps & IEEE80211_C_WEP)
722                 wi_write_wep(sc);
723
724         /* Set multicast filter. */
725         wi_write_multi(sc);
726
727         /* Allocate fids for the card */
728         if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
729                 sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
730                 if (sc->sc_firmware_type == WI_SYMBOL)
731                         sc->sc_buflen = 1585;   /* XXX */
732                 for (i = 0; i < sc->sc_ntxbuf; i++) {
733                         error = wi_alloc_fid(sc, sc->sc_buflen,
734                             &sc->sc_txd[i].d_fid);
735                         if (error) {
736                                 if_printf(ifp,
737                                     "tx buffer allocation failed (error %u)\n",
738                                     error);
739                                 goto out;
740                         }
741                         sc->sc_txd[i].d_len = 0;
742                 }
743         }
744         sc->sc_txcur = sc->sc_txnext = 0;
745
746         /* Enable desired port */
747         wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0);
748
749         sc->sc_enabled = 1;
750         ifp->if_flags |= IFF_RUNNING;
751         ifp->if_flags &= ~IFF_OACTIVE;
752         if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
753             ic->ic_opmode == IEEE80211_M_MONITOR ||
754             ic->ic_opmode == IEEE80211_M_HOSTAP)
755                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
756
757         /* Enable interrupts if not polling */
758 #ifdef DEVICE_POLLING
759         if ((ifp->if_flags & IFF_POLLING) == 0)
760 #endif
761                 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
762
763         if (!wasenabled &&
764             ic->ic_opmode == IEEE80211_M_HOSTAP &&
765             sc->sc_firmware_type == WI_INTERSIL) {
766                 /* XXX: some card need to be re-enabled for hostap */
767                 wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
768                 wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
769         }
770
771         if (ic->ic_opmode == IEEE80211_M_STA &&
772             ((ic->ic_flags & IEEE80211_F_DESBSSID) ||
773             ic->ic_des_chan != IEEE80211_CHAN_ANYC)) {
774                 memset(&join, 0, sizeof(join));
775                 if (ic->ic_flags & IEEE80211_F_DESBSSID)
776                         IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
777                 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
778                         join.wi_chan = htole16(
779                                 ieee80211_chan2ieee(ic, ic->ic_des_chan));
780                 /* Lucent firmware does not support the JOIN RID. */
781                 if (sc->sc_firmware_type != WI_LUCENT)
782                         wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
783         }
784         return;
785 out:
786         if (error) {
787                 if_printf(ifp, "interface not running\n");
788                 wi_stop(ifp, 1);
789         }
790
791         DPRINTF((ifp, "wi_init: return %d\n", error));
792         return;
793 }
794
795 void
796 wi_stop(struct ifnet *ifp, int disable)
797 {
798         struct ieee80211com *ic = (struct ieee80211com *) ifp;
799         struct wi_softc *sc = ifp->if_softc;
800
801         DELAY(100000);
802
803         ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
804         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
805         if (sc->sc_enabled && !sc->wi_gone) {
806                 CSR_WRITE_2(sc, WI_INT_EN, 0);
807                 wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
808                 if (disable) {
809 #ifdef __NetBSD__
810                         if (sc->sc_disable)
811                                 (*sc->sc_disable)(sc);
812 #endif
813                         sc->sc_enabled = 0;
814                 }
815         } else if (sc->wi_gone && disable)      /* gone --> not enabled */
816             sc->sc_enabled = 0;
817
818         sc->sc_tx_timer = 0;
819         sc->sc_scan_timer = 0;
820         sc->sc_syn_timer = 0;
821         sc->sc_false_syns = 0;
822         sc->sc_naps = 0;
823         ifp->if_timer = 0;
824 }
825
826 static void
827 wi_start(struct ifnet *ifp)
828 {
829         struct wi_softc *sc = ifp->if_softc;
830         struct ieee80211com *ic = &sc->sc_ic;
831         struct ieee80211_node *ni;
832         struct ieee80211_frame *wh;
833         struct mbuf *m0;
834         struct wi_frame frmhdr;
835         int cur, fid, off, error;
836
837         if (sc->wi_gone)
838                 return;
839
840         if (sc->sc_flags & WI_FLAGS_OUTRANGE)
841                 return;
842
843         memset(&frmhdr, 0, sizeof(frmhdr));
844         cur = sc->sc_txnext;
845         for (;;) {
846                 IF_POLL(&ic->ic_mgtq, m0);
847                 if (m0 != NULL) {
848                         if (sc->sc_txd[cur].d_len != 0) {
849                                 ifp->if_flags |= IFF_OACTIVE;
850                                 break;
851                         }
852                         IF_DEQUEUE(&ic->ic_mgtq, m0);
853                         /*
854                          * Hack!  The referenced node pointer is in the
855                          * rcvif field of the packet header.  This is
856                          * placed there by ieee80211_mgmt_output because
857                          * we need to hold the reference with the frame
858                          * and there's no other way (other than packet
859                          * tags which we consider too expensive to use)
860                          * to pass it along.
861                          */
862                         ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
863                         m0->m_pkthdr.rcvif = NULL;
864
865                         m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
866                             (caddr_t)&frmhdr.wi_ehdr);
867                         frmhdr.wi_ehdr.ether_type = 0;
868                         wh = mtod(m0, struct ieee80211_frame *);
869                 } else {
870                         if (ic->ic_state != IEEE80211_S_RUN)
871                                 break;
872                         m0 = ifq_poll(&ifp->if_snd);
873                         if (m0 == NULL)
874                                 break;
875                         if (sc->sc_txd[cur].d_len != 0) {
876                                 ifp->if_flags |= IFF_OACTIVE;
877                                 break;
878                         }
879                         ifq_dequeue(&ifp->if_snd, m0);
880                         ifp->if_opackets++;
881                         m_copydata(m0, 0, ETHER_HDR_LEN, 
882                             (caddr_t)&frmhdr.wi_ehdr);
883                         BPF_MTAP(ifp, m0);
884
885                         m0 = ieee80211_encap(ifp, m0, &ni);
886                         if (m0 == NULL) {
887                                 ifp->if_oerrors++;
888                                 continue;
889                         }
890                         wh = mtod(m0, struct ieee80211_frame *);
891                         if (ic->ic_flags & IEEE80211_F_WEPON)
892                                 wh->i_fc[1] |= IEEE80211_FC1_WEP;
893
894                 }
895
896                 if (ic->ic_rawbpf != NULL)
897                         bpf_mtap(ic->ic_rawbpf, m0);
898
899                 frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX);
900                 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
901                     (wh->i_fc[1] & IEEE80211_FC1_WEP)) {
902                         if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) {
903                                 ifp->if_oerrors++;
904                                 if (ni && ni != ic->ic_bss)
905                                         ieee80211_free_node(ic, ni);
906                                 continue;
907                         }
908                         frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
909                 }
910
911                 if (sc->sc_drvbpf) {
912                         sc->sc_tx_th.wt_rate =
913                                 ni->ni_rates.rs_rates[ni->ni_txrate];
914                         bpf_ptap(sc->sc_drvbpf, m0, &sc->sc_tx_th,
915                                  sc->sc_tx_th_len);
916                 }
917
918                 m_copydata(m0, 0, sizeof(struct ieee80211_frame),
919                     (caddr_t)&frmhdr.wi_whdr);
920                 m_adj(m0, sizeof(struct ieee80211_frame));
921                 frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
922                 if (IFF_DUMPPKTS(ifp))
923                         wi_dump_pkt(&frmhdr, NULL, -1);
924                 fid = sc->sc_txd[cur].d_fid;
925                 off = sizeof(frmhdr);
926                 error = wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0
927                      || wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
928                 m_freem(m0);
929                 if (ni && ni != ic->ic_bss)
930                         ieee80211_free_node(ic, ni);
931                 if (error) {
932                         ifp->if_oerrors++;
933                         continue;
934                 }
935                 sc->sc_txd[cur].d_len = off;
936                 if (sc->sc_txcur == cur) {
937                         if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
938                                 if_printf(ifp, "xmit failed\n");
939                                 sc->sc_txd[cur].d_len = 0;
940                                 continue;
941                         }
942                         sc->sc_tx_timer = 5;
943                         ifp->if_timer = 1;
944                 }
945                 sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
946         }
947 }
948
949 static int
950 wi_reset(struct wi_softc *sc)
951 {
952         struct ieee80211com *ic = &sc->sc_ic;
953         struct ifnet *ifp = &ic->ic_if;
954 #define WI_INIT_TRIES 3
955         int i;
956         int error = 0;
957         int tries;
958         
959         /* Symbol firmware cannot be initialized more than once */
960         if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_reset)
961                 return (0);
962         if (sc->sc_firmware_type == WI_SYMBOL)
963                 tries = 1;
964         else
965                 tries = WI_INIT_TRIES;
966
967         for (i = 0; i < tries; i++) {
968                 if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
969                         break;
970                 DELAY(WI_DELAY * 1000);
971         }
972         sc->sc_reset = 1;
973
974         if (i == tries) {
975                 if_printf(ifp, "init failed\n");
976                 return (error);
977         }
978
979         CSR_WRITE_2(sc, WI_INT_EN, 0);
980         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
981
982         /* Calibrate timer. */
983         wi_write_val(sc, WI_RID_TICK_TIME, 8);
984
985         return (0);
986 #undef WI_INIT_TRIES
987 }
988
989 static void
990 wi_watchdog(struct ifnet *ifp)
991 {
992         struct wi_softc *sc = ifp->if_softc;
993
994         ifp->if_timer = 0;
995         if (!sc->sc_enabled)
996                 return;
997
998         if (sc->sc_tx_timer) {
999                 if (--sc->sc_tx_timer == 0) {
1000                         if_printf(ifp, "device timeout\n");
1001                         ifp->if_oerrors++;
1002                         wi_init(ifp->if_softc);
1003                         return;
1004                 }
1005                 ifp->if_timer = 1;
1006         }
1007
1008         if (sc->sc_scan_timer) {
1009                 if (--sc->sc_scan_timer <= WI_SCAN_WAIT - WI_SCAN_INQWAIT &&
1010                     sc->sc_firmware_type == WI_INTERSIL) {
1011                         DPRINTF((ifp, "wi_watchdog: inquire scan\n"));
1012                         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
1013                 }
1014                 if (sc->sc_scan_timer)
1015                         ifp->if_timer = 1;
1016         }
1017
1018         if (sc->sc_syn_timer) {
1019                 if (--sc->sc_syn_timer == 0) {
1020                         struct ieee80211com *ic = (struct ieee80211com *) ifp;
1021                         DPRINTF2((ifp, "wi_watchdog: %d false syns\n",
1022                             sc->sc_false_syns));
1023                         sc->sc_false_syns = 0;
1024                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1025                         sc->sc_syn_timer = 5;
1026                 }
1027                 ifp->if_timer = 1;
1028         }
1029
1030         /* TODO: rate control */
1031         ieee80211_watchdog(ifp);
1032 }
1033
1034 static int
1035 wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
1036 {
1037         struct wi_softc *sc = ifp->if_softc;
1038         struct ieee80211com *ic = &sc->sc_ic;
1039         struct ifreq *ifr = (struct ifreq *)data;
1040         struct ieee80211req *ireq;
1041         u_int8_t nodename[IEEE80211_NWID_LEN];
1042         int error = 0;
1043         struct wi_req wreq;
1044
1045         if (sc->wi_gone) {
1046                 error = ENODEV;
1047                 goto out;
1048         }
1049
1050         switch (cmd) {
1051         case SIOCSIFFLAGS:
1052                 /*
1053                  * Can't do promisc and hostap at the same time.  If all that's
1054                  * changing is the promisc flag, try to short-circuit a call to
1055                  * wi_init() by just setting PROMISC in the hardware.
1056                  */
1057                 if (ifp->if_flags & IFF_UP) {
1058                         if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
1059                             ifp->if_flags & IFF_RUNNING) {
1060                                 if (ifp->if_flags & IFF_PROMISC &&
1061                                     !(sc->sc_if_flags & IFF_PROMISC)) {
1062                                         wi_write_val(sc, WI_RID_PROMISC, 1);
1063                                 } else if (!(ifp->if_flags & IFF_PROMISC) &&
1064                                     sc->sc_if_flags & IFF_PROMISC) {
1065                                         wi_write_val(sc, WI_RID_PROMISC, 0);
1066                                 } else {
1067                                         wi_init(sc);
1068                                 }
1069                         } else {
1070                                 wi_init(sc);
1071                         }
1072                 } else {
1073                         if (ifp->if_flags & IFF_RUNNING) {
1074                                 wi_stop(ifp, 1);
1075                         }
1076                         sc->wi_gone = 0;
1077                 }
1078                 sc->sc_if_flags = ifp->if_flags;
1079                 error = 0;
1080                 break;
1081         case SIOCADDMULTI:
1082         case SIOCDELMULTI:
1083                 error = wi_write_multi(sc);
1084                 break;
1085         case SIOCGIFGENERIC:
1086                 error = wi_get_cfg(ifp, cmd, data, cr);
1087                 break;
1088         case SIOCSIFGENERIC:
1089                 error = suser_cred(cr, NULL_CRED_OKAY);
1090                 if (error)
1091                         break;
1092                 error = wi_set_cfg(ifp, cmd, data);
1093                 break;
1094         case SIOCGPRISM2DEBUG:
1095                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1096                 if (error)
1097                         break;
1098                 if (!(ifp->if_flags & IFF_RUNNING) ||
1099                     sc->sc_firmware_type == WI_LUCENT) {
1100                         error = EIO;
1101                         break;
1102                 }
1103                 error = wi_get_debug(sc, &wreq);
1104                 if (error == 0)
1105                         error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1106                 break;
1107         case SIOCSPRISM2DEBUG:
1108                 if ((error = suser_cred(cr, NULL_CRED_OKAY)))
1109                         goto out;
1110                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1111                 if (error)
1112                         break;
1113                 error = wi_set_debug(sc, &wreq);
1114                 break;
1115         case SIOCG80211:
1116                 ireq = (struct ieee80211req *) data;
1117                 switch (ireq->i_type) {
1118                 case IEEE80211_IOC_STATIONNAME:
1119                         ireq->i_len = sc->sc_nodelen + 1;
1120                         error = copyout(sc->sc_nodename, ireq->i_data,
1121                                         ireq->i_len);
1122                         break;
1123                 default:
1124                         error = ieee80211_ioctl(ifp, cmd, data, cr);
1125                         break;
1126                 }
1127                 break;
1128         case SIOCS80211:
1129                 error = suser_cred(cr, NULL_CRED_OKAY);
1130                 if (error)
1131                         break;
1132                 ireq = (struct ieee80211req *) data;
1133                 switch (ireq->i_type) {
1134                 case IEEE80211_IOC_STATIONNAME:
1135                         if (ireq->i_val != 0 ||
1136                             ireq->i_len > IEEE80211_NWID_LEN) {
1137                                 error = EINVAL;
1138                                 break;
1139                         }
1140                         memset(nodename, 0, IEEE80211_NWID_LEN);
1141                         error = copyin(ireq->i_data, nodename, ireq->i_len);
1142                         if (error)
1143                                 break;
1144                         if (sc->sc_enabled) {
1145                                 error = wi_write_ssid(sc, WI_RID_NODENAME,
1146                                         nodename, ireq->i_len);
1147                                 if (error)
1148                                         break;
1149                         }
1150                         memcpy(sc->sc_nodename, nodename, IEEE80211_NWID_LEN);
1151                         sc->sc_nodelen = ireq->i_len;
1152                         break;
1153                 default:
1154                         error = ieee80211_ioctl(ifp, cmd, data, cr);
1155                         break;
1156                 }
1157                 break;
1158         case SIOCSIFCAP:
1159                 if (ifp->if_flags & IFF_RUNNING)
1160                         wi_init(sc);
1161                 break;
1162         default:
1163                 error = ieee80211_ioctl(ifp, cmd, data, cr);
1164                 break;
1165         }
1166         if (error == ENETRESET) {
1167                 if (sc->sc_enabled)
1168                         wi_init(sc);    /* XXX no error return */
1169                 error = 0;
1170         }
1171 out:
1172         return error;
1173 }
1174
1175 static int
1176 wi_media_change(struct ifnet *ifp)
1177 {
1178         struct wi_softc *sc = ifp->if_softc;
1179         int error;
1180
1181         error = ieee80211_media_change(ifp);
1182         if (error == ENETRESET) {
1183                 if (sc->sc_enabled)
1184                         wi_init(sc);    /* XXX no error return */
1185                 error = 0;
1186         }
1187         return error;
1188 }
1189
1190 static void
1191 wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1192 {
1193         struct wi_softc *sc = ifp->if_softc;
1194         struct ieee80211com *ic = &sc->sc_ic;
1195         u_int16_t val;
1196         int rate, len;
1197
1198         if (sc->wi_gone || !sc->sc_enabled) {
1199                 imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
1200                 imr->ifm_status = 0;
1201                 return;
1202         }
1203
1204         imr->ifm_status = IFM_AVALID;
1205         imr->ifm_active = IFM_IEEE80211;
1206         if (ic->ic_state == IEEE80211_S_RUN &&
1207             (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0)
1208                 imr->ifm_status |= IFM_ACTIVE;
1209         len = sizeof(val);
1210         if (wi_read_rid(sc, WI_RID_CUR_TX_RATE, &val, &len) != 0)
1211                 rate = 0;
1212         else {
1213                 /* convert to 802.11 rate */
1214                 rate = val * 2;
1215                 if (sc->sc_firmware_type == WI_LUCENT) {
1216                         if (rate == 4 * 2)
1217                                 rate = 11;      /* 5.5Mbps */
1218                         else if (rate == 5 * 2)
1219                                 rate = 22;      /* 11Mbps */
1220                 } else {
1221                         if (rate == 4*2)
1222                                 rate = 11;      /* 5.5Mbps */
1223                         else if (rate == 8*2)
1224                                 rate = 22;      /* 11Mbps */
1225                 }
1226         }
1227         imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
1228         switch (ic->ic_opmode) {
1229         case IEEE80211_M_STA:
1230                 break;
1231         case IEEE80211_M_IBSS:
1232                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
1233                 break;
1234         case IEEE80211_M_AHDEMO:
1235                 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
1236                 break;
1237         case IEEE80211_M_HOSTAP:
1238                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
1239                 break;
1240         case IEEE80211_M_MONITOR:
1241                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
1242                 break;
1243         }
1244 }
1245
1246 static void
1247 wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
1248 {
1249         struct ieee80211com *ic = &sc->sc_ic;
1250         struct ieee80211_node *ni = ic->ic_bss;
1251         struct ifnet *ifp = &ic->ic_if;
1252
1253         if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid))
1254                 return;
1255
1256         DPRINTF((ifp, "wi_sync_bssid: bssid %6D -> %6D ?\n", ni->ni_bssid, ":",
1257             new_bssid, ":"));
1258
1259         /* In promiscuous mode, the BSSID field is not a reliable
1260          * indicator of the firmware's BSSID. Damp spurious
1261          * change-of-BSSID indications.
1262          */
1263         if ((ifp->if_flags & IFF_PROMISC) != 0 &&
1264             sc->sc_false_syns >= WI_MAX_FALSE_SYNS)
1265                 return;
1266
1267         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1268 }
1269
1270 static void
1271 wi_rx_monitor(struct wi_softc *sc, int fid)
1272 {
1273         struct ieee80211com *ic = &sc->sc_ic;
1274         struct ifnet *ifp = &ic->ic_if;
1275         struct wi_frame *rx_frame;
1276         struct mbuf *m;
1277         int datlen, hdrlen;
1278
1279         /* first allocate mbuf for packet storage */
1280         m = m_getcl(MB_DONTWAIT, MT_DATA, 0);
1281         if (m == NULL) {
1282                 ifp->if_ierrors++;
1283                 return;
1284         }
1285
1286         m->m_pkthdr.rcvif = ifp;
1287
1288         /* now read wi_frame first so we know how much data to read */
1289         if (wi_read_bap(sc, fid, 0, mtod(m, caddr_t), sizeof(*rx_frame))) {
1290                 ifp->if_ierrors++;
1291                 goto done;
1292         }
1293
1294         rx_frame = mtod(m, struct wi_frame *);
1295
1296         switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {
1297         case 7:
1298                 switch (rx_frame->wi_whdr.i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1299                 case IEEE80211_FC0_TYPE_DATA:
1300                         hdrlen = WI_DATA_HDRLEN;
1301                         datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1302                         break;
1303                 case IEEE80211_FC0_TYPE_MGT:
1304                         hdrlen = WI_MGMT_HDRLEN;
1305                         datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1306                         break;
1307                 case IEEE80211_FC0_TYPE_CTL:
1308                         /*
1309                          * prism2 cards don't pass control packets
1310                          * down properly or consistently, so we'll only
1311                          * pass down the header.
1312                          */
1313                         hdrlen = WI_CTL_HDRLEN;
1314                         datlen = 0;
1315                         break;
1316                 default:
1317                         if_printf(ifp, "received packet of unknown type "
1318                                 "on port 7\n");
1319                         ifp->if_ierrors++;
1320                         goto done;
1321                 }
1322                 break;
1323         case 0:
1324                 hdrlen = WI_DATA_HDRLEN;
1325                 datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1326                 break;
1327         default:
1328                 if_printf(ifp, "received packet on invalid "
1329                     "port (wi_status=0x%x)\n", rx_frame->wi_status);
1330                 ifp->if_ierrors++;
1331                 goto done;
1332         }
1333
1334         if (hdrlen + datlen + 2 > MCLBYTES) {
1335                 if_printf(ifp, "oversized packet received "
1336                     "(wi_dat_len=%d, wi_status=0x%x)\n",
1337                     datlen, rx_frame->wi_status);
1338                 ifp->if_ierrors++;
1339                 goto done;
1340         }
1341
1342         if (wi_read_bap(sc, fid, hdrlen, mtod(m, caddr_t) + hdrlen,
1343             datlen + 2) == 0) {
1344                 m->m_pkthdr.len = m->m_len = hdrlen + datlen;
1345                 ifp->if_ipackets++;
1346                 BPF_MTAP(ifp, m);       /* Handle BPF listeners. */
1347         } else
1348                 ifp->if_ierrors++;
1349 done:
1350         m_freem(m);
1351 }
1352
1353 static void
1354 wi_rx_intr(struct wi_softc *sc)
1355 {
1356         struct ieee80211com *ic = &sc->sc_ic;
1357         struct ifnet *ifp = &ic->ic_if;
1358         struct wi_frame frmhdr;
1359         struct mbuf *m;
1360         struct ieee80211_frame *wh;
1361         struct ieee80211_node *ni;
1362         int fid, len, off, rssi;
1363         u_int8_t dir;
1364         u_int16_t status;
1365         u_int32_t rstamp;
1366
1367         fid = CSR_READ_2(sc, WI_RX_FID);
1368
1369         if (sc->wi_debug.wi_monitor) {
1370                 /*
1371                  * If we are in monitor mode just
1372                  * read the data from the device.
1373                  */
1374                 wi_rx_monitor(sc, fid);
1375                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1376                 return;
1377         }
1378
1379         /* First read in the frame header */
1380         if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
1381                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1382                 ifp->if_ierrors++;
1383                 DPRINTF((ifp, "wi_rx_intr: read fid %x failed\n", fid));
1384                 return;
1385         }
1386
1387         if (IFF_DUMPPKTS(ifp))
1388                 wi_dump_pkt(&frmhdr, NULL, frmhdr.wi_rx_signal);
1389
1390         /*
1391          * Drop undecryptable or packets with receive errors here
1392          */
1393         status = le16toh(frmhdr.wi_status);
1394         if (status & WI_STAT_ERRSTAT) {
1395                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1396                 ifp->if_ierrors++;
1397                 DPRINTF((ifp, "wi_rx_intr: fid %x error status %x\n",
1398                          fid, status));
1399                 return;
1400         }
1401         rssi = frmhdr.wi_rx_signal;
1402         rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
1403             le16toh(frmhdr.wi_rx_tstamp1);
1404
1405         len = le16toh(frmhdr.wi_dat_len);
1406         off = ALIGN(sizeof(struct ieee80211_frame));
1407
1408         /*
1409          * Sometimes the PRISM2.x returns bogusly large frames. Except
1410          * in monitor mode, just throw them away.
1411          */
1412         if (off + len > MCLBYTES) {
1413                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1414                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1415                         ifp->if_ierrors++;
1416                         DPRINTF((ifp, "wi_rx_intr: oversized packet\n"));
1417                         return;
1418                 } else
1419                         len = 0;
1420         }
1421
1422         m = m_getl(off + len, MB_DONTWAIT, MT_DATA, M_PKTHDR, NULL);
1423         if (m == NULL) {
1424                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1425                 ifp->if_ierrors++;
1426                 DPRINTF((ifp, "wi_rx_intr: m_getl failed\n"));
1427                 return;
1428         }
1429
1430         m->m_data += off - sizeof(struct ieee80211_frame);
1431         memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame));
1432         wi_read_bap(sc, fid, sizeof(frmhdr),
1433             m->m_data + sizeof(struct ieee80211_frame), len);
1434         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
1435         m->m_pkthdr.rcvif = ifp;
1436
1437         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1438
1439         if (sc->sc_drvbpf) {
1440                 /* XXX replace divide by table */
1441                 sc->sc_rx_th.wr_rate = frmhdr.wi_rx_rate / 5;
1442                 sc->sc_rx_th.wr_antsignal = frmhdr.wi_rx_signal;
1443                 sc->sc_rx_th.wr_antnoise = frmhdr.wi_rx_silence;
1444                 sc->sc_rx_th.wr_flags = 0;
1445                 if (frmhdr.wi_status & WI_STAT_PCF)
1446                         sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_CFP;
1447                 bpf_ptap(sc->sc_drvbpf, m, &sc->sc_rx_th, sc->sc_rx_th_len);
1448         }
1449
1450         wh = mtod(m, struct ieee80211_frame *);
1451         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1452                 /*
1453                  * WEP is decrypted by hardware. Clear WEP bit
1454                  * header for ieee80211_input().
1455                  */
1456                 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
1457         }
1458
1459         /* synchronize driver's BSSID with firmware's BSSID */
1460         dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
1461         if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS)
1462                 wi_sync_bssid(sc, wh->i_addr3);
1463
1464         /*
1465          * Locate the node for sender, track state, and
1466          * then pass this node (referenced) up to the 802.11
1467          * layer for its use.  We are required to pass
1468          * something so we fallback to ic_bss when this frame
1469          * is from an unknown sender.
1470          */
1471         if (ic->ic_opmode != IEEE80211_M_STA) {
1472                 ni = ieee80211_find_node(ic, wh->i_addr2);
1473                 if (ni == NULL)
1474                         ni = ieee80211_ref_node(ic->ic_bss);
1475         } else
1476                 ni = ieee80211_ref_node(ic->ic_bss);
1477         /*
1478          * Send frame up for processing.
1479          */
1480         ieee80211_input(ifp, m, ni, rssi, rstamp);
1481         /*
1482          * The frame may have caused the node to be marked for
1483          * reclamation (e.g. in response to a DEAUTH message)
1484          * so use free_node here instead of unref_node.
1485          */
1486         if (ni == ic->ic_bss)
1487                 ieee80211_unref_node(&ni);
1488         else
1489                 ieee80211_free_node(ic, ni);
1490 }
1491
1492 static void
1493 wi_tx_ex_intr(struct wi_softc *sc)
1494 {
1495         struct ieee80211com *ic = &sc->sc_ic;
1496         struct ifnet *ifp = &ic->ic_if;
1497         struct wi_frame frmhdr;
1498         int fid;
1499
1500         fid = CSR_READ_2(sc, WI_TX_CMP_FID);
1501         /* Read in the frame header */
1502         if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) == 0) {
1503                 u_int16_t status = le16toh(frmhdr.wi_status);
1504
1505                 /*
1506                  * Spontaneous station disconnects appear as xmit
1507                  * errors.  Don't announce them and/or count them
1508                  * as an output error.
1509                  */
1510                 if ((status & WI_TXSTAT_DISCONNECT) == 0) {
1511                         if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
1512                                 if_printf(ifp, "tx failed");
1513                                 if (status & WI_TXSTAT_RET_ERR)
1514                                         printf(", retry limit exceeded");
1515                                 if (status & WI_TXSTAT_AGED_ERR)
1516                                         printf(", max transmit lifetime exceeded");
1517                                 if (status & WI_TXSTAT_DISCONNECT)
1518                                         printf(", port disconnected");
1519                                 if (status & WI_TXSTAT_FORM_ERR)
1520                                         printf(", invalid format (data len %u src %6D)",
1521                                                 le16toh(frmhdr.wi_dat_len),
1522                                                 frmhdr.wi_ehdr.ether_shost, ":");
1523                                 if (status & ~0xf)
1524                                         printf(", status=0x%x", status);
1525                                 printf("\n");
1526                         }
1527                         ifp->if_oerrors++;
1528                 } else {
1529                         DPRINTF((ifp, "port disconnected\n"));
1530                         ifp->if_collisions++;   /* XXX */
1531                 }
1532         } else
1533                 DPRINTF((ifp, "wi_tx_ex_intr: read fid %x failed\n", fid));
1534         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
1535 }
1536
1537 static void
1538 wi_tx_intr(struct wi_softc *sc)
1539 {
1540         struct ieee80211com *ic = &sc->sc_ic;
1541         struct ifnet *ifp = &ic->ic_if;
1542         int fid, cur;
1543
1544         if (sc->wi_gone)
1545                 return;
1546
1547         fid = CSR_READ_2(sc, WI_ALLOC_FID);
1548         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1549
1550         cur = sc->sc_txcur;
1551         if (sc->sc_txd[cur].d_fid != fid) {
1552                 if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n",
1553                     fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext);
1554                 return;
1555         }
1556         sc->sc_tx_timer = 0;
1557         sc->sc_txd[cur].d_len = 0;
1558         sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
1559         if (sc->sc_txd[cur].d_len == 0)
1560                 ifp->if_flags &= ~IFF_OACTIVE;
1561         else {
1562                 if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
1563                     0, 0)) {
1564                         if_printf(ifp, "xmit failed\n");
1565                         sc->sc_txd[cur].d_len = 0;
1566                 } else {
1567                         sc->sc_tx_timer = 5;
1568                         ifp->if_timer = 1;
1569                 }
1570         }
1571 }
1572
1573 static void
1574 wi_info_intr(struct wi_softc *sc)
1575 {
1576         struct ieee80211com *ic = &sc->sc_ic;
1577         struct ifnet *ifp = &ic->ic_if;
1578         int i, fid, len, off;
1579         u_int16_t ltbuf[2];
1580         u_int16_t stat;
1581         u_int32_t *ptr;
1582
1583         fid = CSR_READ_2(sc, WI_INFO_FID);
1584         wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
1585
1586         switch (le16toh(ltbuf[1])) {
1587
1588         case WI_INFO_LINK_STAT:
1589                 wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
1590                 DPRINTF((ifp, "wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
1591                 switch (le16toh(stat)) {
1592                 case WI_INFO_LINK_STAT_CONNECTED:
1593                         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
1594                         if (ic->ic_state == IEEE80211_S_RUN &&
1595                             ic->ic_opmode != IEEE80211_M_IBSS)
1596                                 break;
1597                         /* FALLTHROUGH */
1598                 case WI_INFO_LINK_STAT_AP_CHG:
1599                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1600                         break;
1601                 case WI_INFO_LINK_STAT_AP_INR:
1602                         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
1603                         break;
1604                 case WI_INFO_LINK_STAT_AP_OOR:
1605                         if (sc->sc_firmware_type == WI_SYMBOL &&
1606                             sc->sc_scan_timer > 0) {
1607                                 if (wi_cmd(sc, WI_CMD_INQUIRE,
1608                                     WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0)
1609                                         sc->sc_scan_timer = 0;
1610                                 break;
1611                         }
1612                         if (ic->ic_opmode == IEEE80211_M_STA)
1613                                 sc->sc_flags |= WI_FLAGS_OUTRANGE;
1614                         break;
1615                 case WI_INFO_LINK_STAT_DISCONNECTED:
1616                 case WI_INFO_LINK_STAT_ASSOC_FAILED:
1617                         if (ic->ic_opmode == IEEE80211_M_STA)
1618                                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1619                         break;
1620                 }
1621                 break;
1622
1623         case WI_INFO_COUNTERS:
1624                 /* some card versions have a larger stats structure */
1625                 len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
1626                 ptr = (u_int32_t *)&sc->sc_stats;
1627                 off = sizeof(ltbuf);
1628                 for (i = 0; i < len; i++, off += 2, ptr++) {
1629                         wi_read_bap(sc, fid, off, &stat, sizeof(stat));
1630 #ifdef WI_HERMES_STATS_WAR
1631                         if (stat & 0xf000)
1632                                 stat = ~stat;
1633 #endif
1634                         *ptr += stat;
1635                 }
1636                 ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
1637                     sc->sc_stats.wi_tx_multi_retries +
1638                     sc->sc_stats.wi_tx_retry_limit;
1639                 break;
1640
1641         case WI_INFO_SCAN_RESULTS:
1642         case WI_INFO_HOST_SCAN_RESULTS:
1643                 wi_scan_result(sc, fid, le16toh(ltbuf[0]));
1644                 break;
1645
1646         default:
1647                 DPRINTF((ifp, "wi_info_intr: got fid %x type %x len %d\n", fid,
1648                     le16toh(ltbuf[1]), le16toh(ltbuf[0])));
1649                 break;
1650         }
1651         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
1652 }
1653
1654 static int
1655 wi_write_multi(struct wi_softc *sc)
1656 {
1657         struct ifnet *ifp = &sc->sc_ic.ic_if;
1658         int n;
1659         struct ifmultiaddr *ifma;
1660         struct wi_mcast mlist;
1661
1662         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1663 allmulti:
1664                 memset(&mlist, 0, sizeof(mlist));
1665                 return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1666                     sizeof(mlist));
1667         }
1668
1669         n = 0;
1670         LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1671                 if (ifma->ifma_addr->sa_family != AF_LINK)
1672                         continue;
1673                 if (n >= 16)
1674                         goto allmulti;
1675                 IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
1676                     (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
1677                 n++;
1678         }
1679         return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1680             IEEE80211_ADDR_LEN * n);
1681 }
1682
1683 static void
1684 wi_read_nicid(struct wi_softc *sc)
1685 {
1686         struct wi_card_ident *id;
1687         char *p;
1688         int len;
1689         u_int16_t ver[4];
1690
1691         /* getting chip identity */
1692         memset(ver, 0, sizeof(ver));
1693         len = sizeof(ver);
1694         wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
1695         if_printf(&sc->sc_ic.ic_if, "using ");
1696
1697         sc->sc_firmware_type = WI_NOTYPE;
1698         for (id = wi_card_ident; id->card_name != NULL; id++) {
1699                 if (le16toh(ver[0]) == id->card_id) {
1700                         printf("%s", id->card_name);
1701                         sc->sc_firmware_type = id->firm_type;
1702                         break;
1703                 }
1704         }
1705         if (sc->sc_firmware_type == WI_NOTYPE) {
1706                 if (le16toh(ver[0]) & 0x8000) {
1707                         printf("Unknown PRISM2 chip");
1708                         sc->sc_firmware_type = WI_INTERSIL;
1709                 } else {
1710                         printf("Unknown Lucent chip");
1711                         sc->sc_firmware_type = WI_LUCENT;
1712                 }
1713         }
1714
1715         /* get primary firmware version (Only Prism chips) */
1716         if (sc->sc_firmware_type != WI_LUCENT) {
1717                 memset(ver, 0, sizeof(ver));
1718                 len = sizeof(ver);
1719                 wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
1720                 sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
1721                     le16toh(ver[3]) * 100 + le16toh(ver[1]);
1722         }
1723
1724         /* get station firmware version */
1725         memset(ver, 0, sizeof(ver));
1726         len = sizeof(ver);
1727         wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
1728         sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
1729             le16toh(ver[3]) * 100 + le16toh(ver[1]);
1730         if (sc->sc_firmware_type == WI_INTERSIL &&
1731             (sc->sc_sta_firmware_ver == 10102 ||
1732              sc->sc_sta_firmware_ver == 20102)) {
1733                 char ident[12];
1734                 memset(ident, 0, sizeof(ident));
1735                 len = sizeof(ident);
1736                 /* value should be the format like "V2.00-11" */
1737                 if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
1738                     *(p = (char *)ident) >= 'A' &&
1739                     p[2] == '.' && p[5] == '-' && p[8] == '\0') {
1740                         sc->sc_firmware_type = WI_SYMBOL;
1741                         sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
1742                             (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
1743                             (p[6] - '0') * 10 + (p[7] - '0');
1744                 }
1745         }
1746         printf("\n");
1747         if_printf(&sc->sc_ic.ic_if, "%s Firmware: ",
1748              sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
1749             (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
1750         if (sc->sc_firmware_type != WI_LUCENT)  /* XXX */
1751                 printf("Primary (%u.%u.%u), ",
1752                     sc->sc_pri_firmware_ver / 10000,
1753                     (sc->sc_pri_firmware_ver % 10000) / 100,
1754                     sc->sc_pri_firmware_ver % 100);
1755         printf("Station (%u.%u.%u)\n",
1756             sc->sc_sta_firmware_ver / 10000,
1757             (sc->sc_sta_firmware_ver % 10000) / 100,
1758             sc->sc_sta_firmware_ver % 100);
1759 }
1760
1761 static int
1762 wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
1763 {
1764         struct wi_ssid ssid;
1765
1766         if (buflen > IEEE80211_NWID_LEN)
1767                 return ENOBUFS;
1768         memset(&ssid, 0, sizeof(ssid));
1769         ssid.wi_len = htole16(buflen);
1770         memcpy(ssid.wi_ssid, buf, buflen);
1771         return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
1772 }
1773
1774 static int
1775 wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
1776 {
1777         struct wi_softc *sc = ifp->if_softc;
1778         struct ieee80211com *ic = &sc->sc_ic;
1779         struct ifreq *ifr = (struct ifreq *)data;
1780         struct wi_req wreq;
1781         struct wi_scan_res *res;
1782         size_t reslen;
1783         int len, n, error, mif, val, off, i;
1784
1785         error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1786         if (error)
1787                 return error;
1788         len = (wreq.wi_len - 1) * 2;
1789         if (len < sizeof(u_int16_t))
1790                 return ENOSPC;
1791         if (len > sizeof(wreq.wi_val))
1792                 len = sizeof(wreq.wi_val);
1793
1794         switch (wreq.wi_type) {
1795
1796         case WI_RID_IFACE_STATS:
1797                 memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
1798                 if (len < sizeof(sc->sc_stats))
1799                         error = ENOSPC;
1800                 else
1801                         len = sizeof(sc->sc_stats);
1802                 break;
1803
1804         case WI_RID_ENCRYPTION:
1805         case WI_RID_TX_CRYPT_KEY:
1806         case WI_RID_DEFLT_CRYPT_KEYS:
1807         case WI_RID_TX_RATE:
1808                 return ieee80211_cfgget(ifp, cmd, data, cr);
1809
1810         case WI_RID_MICROWAVE_OVEN:
1811                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
1812                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1813                             &len);
1814                         break;
1815                 }
1816                 wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
1817                 len = sizeof(u_int16_t);
1818                 break;
1819
1820         case WI_RID_DBM_ADJUST:
1821                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
1822                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1823                             &len);
1824                         break;
1825                 }
1826                 wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
1827                 len = sizeof(u_int16_t);
1828                 break;
1829
1830         case WI_RID_ROAMING_MODE:
1831                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
1832                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1833                             &len);
1834                         break;
1835                 }
1836                 wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
1837                 len = sizeof(u_int16_t);
1838                 break;
1839
1840         case WI_RID_SYSTEM_SCALE:
1841                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
1842                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1843                             &len);
1844                         break;
1845                 }
1846                 wreq.wi_val[0] = htole16(sc->sc_system_scale);
1847                 len = sizeof(u_int16_t);
1848                 break;
1849
1850         case WI_RID_FRAG_THRESH:
1851                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
1852                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1853                             &len);
1854                         break;
1855                 }
1856                 wreq.wi_val[0] = htole16(ic->ic_fragthreshold);
1857                 len = sizeof(u_int16_t);
1858                 break;
1859
1860         case WI_RID_READ_APS:
1861                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1862                         return ieee80211_cfgget(ifp, cmd, data, cr);
1863                 if (sc->sc_scan_timer > 0) {
1864                         error = EINPROGRESS;
1865                         break;
1866                 }
1867                 n = sc->sc_naps;
1868                 if (len < sizeof(n)) {
1869                         error = ENOSPC;
1870                         break;
1871                 }
1872                 if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
1873                         n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
1874                 len = sizeof(n) + sizeof(struct wi_apinfo) * n;
1875                 memcpy(wreq.wi_val, &n, sizeof(n));
1876                 memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps,
1877                     sizeof(struct wi_apinfo) * n);
1878                 break;
1879
1880         case WI_RID_PRISM2:
1881                 wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT;
1882                 len = sizeof(u_int16_t);
1883                 break;
1884
1885         case WI_RID_MIF:
1886                 mif = wreq.wi_val[0];
1887                 error = wi_cmd(sc, WI_CMD_READMIF, mif, 0, 0);
1888                 val = CSR_READ_2(sc, WI_RESP0);
1889                 wreq.wi_val[0] = val;
1890                 len = sizeof(u_int16_t);
1891                 break;
1892
1893         case WI_RID_ZERO_CACHE:
1894         case WI_RID_PROCFRAME:          /* ignore for compatibility */
1895                 /* XXX ??? */
1896                 break;
1897
1898         case WI_RID_READ_CACHE:
1899                 return ieee80211_cfgget(ifp, cmd, data, cr);
1900
1901         case WI_RID_SCAN_RES:           /* compatibility interface */
1902                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1903                         return ieee80211_cfgget(ifp, cmd, data, cr);
1904                 if (sc->sc_scan_timer > 0) {
1905                         error = EINPROGRESS;
1906                         break;
1907                 }
1908                 n = sc->sc_naps;
1909                 if (sc->sc_firmware_type == WI_LUCENT) {
1910                         off = 0;
1911                         reslen = WI_WAVELAN_RES_SIZE;
1912                 } else {
1913                         off = sizeof(struct wi_scan_p2_hdr);
1914                         reslen = WI_PRISM2_RES_SIZE;
1915                 }
1916                 if (len < off + reslen * n)
1917                         n = (len - off) / reslen;
1918                 len = off + reslen * n;
1919                 if (off != 0) {
1920                         struct wi_scan_p2_hdr *p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
1921                         /*
1922                          * Prepend Prism-specific header.
1923                          */
1924                         if (len < sizeof(struct wi_scan_p2_hdr)) {
1925                                 error = ENOSPC;
1926                                 break;
1927                         }
1928                         p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
1929                         p2->wi_rsvd = 0;
1930                         p2->wi_reason = n;      /* XXX */
1931                 }
1932                 for (i = 0; i < n; i++, off += reslen) {
1933                         const struct wi_apinfo *ap = &sc->sc_aps[i];
1934
1935                         res = (struct wi_scan_res *)((char *)wreq.wi_val + off);
1936                         res->wi_chan = ap->channel;
1937                         res->wi_noise = ap->noise;
1938                         res->wi_signal = ap->signal;
1939                         IEEE80211_ADDR_COPY(res->wi_bssid, ap->bssid);
1940                         res->wi_interval = ap->interval;
1941                         res->wi_capinfo = ap->capinfo;
1942                         res->wi_ssid_len = ap->namelen;
1943                         memcpy(res->wi_ssid, ap->name,
1944                                 IEEE80211_NWID_LEN);
1945                         if (sc->sc_firmware_type != WI_LUCENT) {
1946                                 /* XXX not saved from Prism cards */
1947                                 memset(res->wi_srates, 0,
1948                                         sizeof(res->wi_srates));
1949                                 res->wi_rate = ap->rate;
1950                                 res->wi_rsvd = 0;
1951                         }
1952                 }
1953                 break;
1954
1955         default:
1956                 if (sc->sc_enabled) {
1957                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1958                             &len);
1959                         break;
1960                 }
1961                 switch (wreq.wi_type) {
1962                 case WI_RID_MAX_DATALEN:
1963                         wreq.wi_val[0] = htole16(sc->sc_max_datalen);
1964                         len = sizeof(u_int16_t);
1965                         break;
1966                 case WI_RID_RTS_THRESH:
1967                         wreq.wi_val[0] = htole16(ic->ic_rtsthreshold);
1968                         len = sizeof(u_int16_t);
1969                         break;
1970                 case WI_RID_CNFAUTHMODE:
1971                         wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
1972                         len = sizeof(u_int16_t);
1973                         break;
1974                 case WI_RID_NODENAME:
1975                         if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
1976                                 error = ENOSPC;
1977                                 break;
1978                         }
1979                         len = sc->sc_nodelen + sizeof(u_int16_t);
1980                         wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
1981                         memcpy(&wreq.wi_val[1], sc->sc_nodename,
1982                             sc->sc_nodelen);
1983                         break;
1984                 default:
1985                         return ieee80211_cfgget(ifp, cmd, data, cr);
1986                 }
1987                 break;
1988         }
1989         if (error)
1990                 return error;
1991         wreq.wi_len = (len + 1) / 2 + 1;
1992         return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
1993 }
1994
1995 static int
1996 wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
1997 {
1998         struct wi_softc *sc = ifp->if_softc;
1999         struct ieee80211com *ic = &sc->sc_ic;
2000         struct ifreq *ifr = (struct ifreq *)data;
2001         struct wi_req wreq;
2002         struct mbuf *m;
2003         int i, len, error, mif, val;
2004         struct ieee80211_rateset *rs;
2005
2006         error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
2007         if (error)
2008                 return error;
2009         len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0;
2010         switch (wreq.wi_type) {
2011         case WI_RID_DBM_ADJUST:
2012                 return ENODEV;
2013
2014         case WI_RID_NODENAME:
2015                 if (le16toh(wreq.wi_val[0]) * 2 > len ||
2016                     le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
2017                         error = ENOSPC;
2018                         break;
2019                 }
2020                 if (sc->sc_enabled) {
2021                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2022                             len);
2023                         if (error)
2024                                 break;
2025                 }
2026                 sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
2027                 memcpy(sc->sc_nodename, &wreq.wi_val[1], sc->sc_nodelen);
2028                 break;
2029
2030         case WI_RID_MICROWAVE_OVEN:
2031         case WI_RID_ROAMING_MODE:
2032         case WI_RID_SYSTEM_SCALE:
2033         case WI_RID_FRAG_THRESH:
2034                 if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
2035                     (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
2036                         break;
2037                 if (wreq.wi_type == WI_RID_ROAMING_MODE &&
2038                     (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
2039                         break;
2040                 if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
2041                     (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
2042                         break;
2043                 if (wreq.wi_type == WI_RID_FRAG_THRESH &&
2044                     (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
2045                         break;
2046                 /* FALLTHROUGH */
2047         case WI_RID_RTS_THRESH:
2048         case WI_RID_CNFAUTHMODE:
2049         case WI_RID_MAX_DATALEN:
2050                 if (sc->sc_enabled) {
2051                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2052                             sizeof(u_int16_t));
2053                         if (error)
2054                                 break;
2055                 }
2056                 switch (wreq.wi_type) {
2057                 case WI_RID_FRAG_THRESH:
2058                         ic->ic_fragthreshold = le16toh(wreq.wi_val[0]);
2059                         break;
2060                 case WI_RID_RTS_THRESH:
2061                         ic->ic_rtsthreshold = le16toh(wreq.wi_val[0]);
2062                         break;
2063                 case WI_RID_MICROWAVE_OVEN:
2064                         sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
2065                         break;
2066                 case WI_RID_ROAMING_MODE:
2067                         sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
2068                         break;
2069                 case WI_RID_SYSTEM_SCALE:
2070                         sc->sc_system_scale = le16toh(wreq.wi_val[0]);
2071                         break;
2072                 case WI_RID_CNFAUTHMODE:
2073                         sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
2074                         break;
2075                 case WI_RID_MAX_DATALEN:
2076                         sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
2077                         break;
2078                 }
2079                 break;
2080
2081         case WI_RID_TX_RATE:
2082                 switch (le16toh(wreq.wi_val[0])) {
2083                 case 3:
2084                         ic->ic_fixed_rate = -1;
2085                         break;
2086                 default:
2087                         rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
2088                         for (i = 0; i < rs->rs_nrates; i++) {
2089                                 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL)
2090                                     / 2 == le16toh(wreq.wi_val[0]))
2091                                         break;
2092                         }
2093                         if (i == rs->rs_nrates)
2094                                 return EINVAL;
2095                         ic->ic_fixed_rate = i;
2096                 }
2097                 if (sc->sc_enabled)
2098                         error = wi_write_txrate(sc);
2099                 break;
2100
2101         case WI_RID_SCAN_APS:
2102                 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
2103                         error = wi_scan_ap(sc, 0x3fff, 0x000f);
2104                 break;
2105
2106         case WI_RID_SCAN_REQ:           /* compatibility interface */
2107                 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
2108                         error = wi_scan_ap(sc, wreq.wi_val[0], wreq.wi_val[1]);
2109                 break;
2110
2111         case WI_RID_MGMT_XMIT:
2112                 if (!sc->sc_enabled) {
2113                         error = ENETDOWN;
2114                         break;
2115                 }
2116                 if (ic->ic_mgtq.ifq_len > 5) {
2117                         error = EAGAIN;
2118                         break;
2119                 }
2120                 /* XXX wi_len looks in u_int8_t, not in u_int16_t */
2121                 m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0, ifp, NULL);
2122                 if (m == NULL) {
2123                         error = ENOMEM;
2124                         break;
2125                 }
2126                 IF_ENQUEUE(&ic->ic_mgtq, m);
2127                 break;
2128
2129         case WI_RID_MIF:
2130                 mif = wreq.wi_val[0];
2131                 val = wreq.wi_val[1];
2132                 error = wi_cmd(sc, WI_CMD_WRITEMIF, mif, val, 0);
2133                 break;
2134
2135         case WI_RID_PROCFRAME:          /* ignore for compatibility */
2136                 break;
2137
2138         case WI_RID_OWN_SSID:
2139                 if (le16toh(wreq.wi_val[0]) * 2 > len ||
2140                     le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) {
2141                         error = ENOSPC;
2142                         break;
2143                 }
2144                 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
2145                 ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2;
2146                 memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen);
2147                 error = ENETRESET;
2148                 break;
2149
2150         default:
2151                 if (sc->sc_enabled) {
2152                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2153                             len);
2154                         if (error)
2155                                 break;
2156                 }
2157                 error = ieee80211_cfgset(ifp, cmd, data);
2158                 break;
2159         }
2160         return error;
2161 }
2162
2163 static int
2164 wi_write_txrate(struct wi_softc *sc)
2165 {
2166         struct ieee80211com *ic = &sc->sc_ic;
2167         int i;
2168         u_int16_t rate;
2169
2170         if (ic->ic_fixed_rate < 0)
2171                 rate = 0;       /* auto */
2172         else
2173                 rate = (ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ic->ic_fixed_rate] &
2174                     IEEE80211_RATE_VAL) / 2;
2175
2176         /* rate: 0, 1, 2, 5, 11 */
2177
2178         switch (sc->sc_firmware_type) {
2179         case WI_LUCENT:
2180                 switch (rate) {
2181                 case 0:                 /* auto == 11mbps auto */
2182                         rate = 3;
2183                         break;
2184                 /* case 1, 2 map to 1, 2*/
2185                 case 5:                 /* 5.5Mbps -> 4 */
2186                         rate = 4;
2187                         break;
2188                 case 11:                /* 11mbps -> 5 */
2189                         rate = 5;
2190                         break;
2191                 default:
2192                         break;
2193                 }
2194                 break;
2195         default:
2196                 /* Choose a bit according to this table.
2197                  *
2198                  * bit | data rate
2199                  * ----+-------------------
2200                  * 0   | 1Mbps
2201                  * 1   | 2Mbps
2202                  * 2   | 5.5Mbps
2203                  * 3   | 11Mbps
2204                  */
2205                 for (i = 8; i > 0; i >>= 1) {
2206                         if (rate >= i)
2207                                 break;
2208                 }
2209                 if (i == 0)
2210                         rate = 0xf;     /* auto */
2211                 else
2212                         rate = i;
2213                 break;
2214         }
2215         return wi_write_val(sc, WI_RID_TX_RATE, rate);
2216 }
2217
2218 static int
2219 wi_write_wep(struct wi_softc *sc)
2220 {
2221         struct ieee80211com *ic = &sc->sc_ic;
2222         int error = 0;
2223         int i, keylen;
2224         u_int16_t val;
2225         struct wi_key wkey[IEEE80211_WEP_NKID];
2226
2227         switch (sc->sc_firmware_type) {
2228         case WI_LUCENT:
2229                 val = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0;
2230                 error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
2231                 if (error)
2232                         break;
2233                 error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_wep_txkey);
2234                 if (error)
2235                         break;
2236                 memset(wkey, 0, sizeof(wkey));
2237                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2238                         keylen = ic->ic_nw_keys[i].wk_len;
2239                         wkey[i].wi_keylen = htole16(keylen);
2240                         memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
2241                             keylen);
2242                 }
2243                 error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
2244                     wkey, sizeof(wkey));
2245                 break;
2246
2247         case WI_INTERSIL:
2248         case WI_SYMBOL:
2249                 if (ic->ic_flags & IEEE80211_F_WEPON) {
2250                         /*
2251                          * ONLY HWB3163 EVAL-CARD Firmware version
2252                          * less than 0.8 variant2
2253                          *
2254                          *   If promiscuous mode disable, Prism2 chip
2255                          *  does not work with WEP .
2256                          * It is under investigation for details.
2257                          * (ichiro@netbsd.org)
2258                          */
2259                         if (sc->sc_firmware_type == WI_INTERSIL &&
2260                             sc->sc_sta_firmware_ver < 802 ) {
2261                                 /* firm ver < 0.8 variant 2 */
2262                                 wi_write_val(sc, WI_RID_PROMISC, 1);
2263                         }
2264                         wi_write_val(sc, WI_RID_CNFAUTHMODE,
2265                             sc->sc_cnfauthmode);
2266                         val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
2267                         /*
2268                          * Encryption firmware has a bug for HostAP mode.
2269                          */
2270                         if (sc->sc_firmware_type == WI_INTERSIL &&
2271                             ic->ic_opmode == IEEE80211_M_HOSTAP)
2272                                 val |= HOST_ENCRYPT;
2273                 } else {
2274                         wi_write_val(sc, WI_RID_CNFAUTHMODE,
2275                             IEEE80211_AUTH_OPEN);
2276                         val = HOST_ENCRYPT | HOST_DECRYPT;
2277                 }
2278                 error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
2279                 if (error)
2280                         break;
2281                 error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
2282                     ic->ic_wep_txkey);
2283                 if (error)
2284                         break;
2285                 /*
2286                  * It seems that the firmware accept 104bit key only if
2287                  * all the keys have 104bit length.  We get the length of
2288                  * the transmit key and use it for all other keys.
2289                  * Perhaps we should use software WEP for such situation.
2290                  */
2291                 keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len;
2292                 if (keylen > IEEE80211_WEP_KEYLEN)
2293                         keylen = 13;    /* 104bit keys */
2294                 else
2295                         keylen = IEEE80211_WEP_KEYLEN;
2296                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2297                         error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
2298                             ic->ic_nw_keys[i].wk_key, keylen);
2299                         if (error)
2300                                 break;
2301                 }
2302                 break;
2303         }
2304         return error;
2305 }
2306
2307 static int
2308 wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
2309 {
2310         int                     i, s = 0;
2311         static volatile int count  = 0;
2312         
2313         if (sc->wi_gone)
2314                 return (ENODEV);
2315
2316         if (count > 0)
2317                 panic("Hey partner, hold on there!");
2318         count++;
2319
2320         /* wait for the busy bit to clear */
2321         for (i = sc->wi_cmd_count; i > 0; i--) {        /* 500ms */
2322                 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
2323                         break;
2324                 DELAY(1*1000);  /* 1ms */
2325         }
2326         if (i == 0) {
2327                 if_printf(&sc->sc_ic.ic_if, "wi_cmd: busy bit won't clear.\n" );
2328                 sc->wi_gone = 1;
2329                 count--;
2330                 return(ETIMEDOUT);
2331         }
2332
2333         CSR_WRITE_2(sc, WI_PARAM0, val0);
2334         CSR_WRITE_2(sc, WI_PARAM1, val1);
2335         CSR_WRITE_2(sc, WI_PARAM2, val2);
2336         CSR_WRITE_2(sc, WI_COMMAND, cmd);
2337
2338         if (cmd == WI_CMD_INI) {
2339                 /* XXX: should sleep here. */
2340                 DELAY(100*1000);                /* 100ms delay for init */
2341         }
2342         for (i = 0; i < WI_TIMEOUT; i++) {
2343                 /*
2344                  * Wait for 'command complete' bit to be
2345                  * set in the event status register.
2346                  */
2347                 s = CSR_READ_2(sc, WI_EVENT_STAT);
2348                 if (s & WI_EV_CMD) {
2349                         /* Ack the event and read result code. */
2350                         s = CSR_READ_2(sc, WI_STATUS);
2351                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
2352                         if (s & WI_STAT_CMD_RESULT) {
2353                                 count--;
2354                                 return(EIO);
2355                         }
2356                         break;
2357                 }
2358                 DELAY(WI_DELAY);
2359         }
2360
2361         count--;
2362         if (i == WI_TIMEOUT) {
2363                 if_printf(&sc->sc_ic.ic_if,
2364                     "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
2365                 if (s == 0xffff)
2366                         sc->wi_gone = 1;
2367                 return(ETIMEDOUT);
2368         }
2369         return (0);
2370 }
2371
2372 static int
2373 wi_seek_bap(struct wi_softc *sc, int id, int off)
2374 {
2375         int i, status;
2376
2377         CSR_WRITE_2(sc, WI_SEL0, id);
2378         CSR_WRITE_2(sc, WI_OFF0, off);
2379
2380         for (i = 0; ; i++) {
2381                 status = CSR_READ_2(sc, WI_OFF0);
2382                 if ((status & WI_OFF_BUSY) == 0)
2383                         break;
2384                 if (i == WI_TIMEOUT) {
2385                         if_printf(&sc->sc_ic.ic_if,
2386                                   "timeout in wi_seek to %x/%x\n", id, off);
2387                         sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
2388                         if (status == 0xffff)
2389                                 sc->wi_gone = 1;
2390                         return ETIMEDOUT;
2391                 }
2392                 DELAY(1);
2393         }
2394         if (status & WI_OFF_ERR) {
2395                 if_printf(&sc->sc_ic.ic_if, "failed in wi_seek to %x/%x\n",
2396                           id, off);
2397                 sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
2398                 return EIO;
2399         }
2400         sc->sc_bap_id = id;
2401         sc->sc_bap_off = off;
2402         return 0;
2403 }
2404
2405 static int
2406 wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
2407 {
2408         u_int16_t *ptr;
2409         int i, error, cnt;
2410
2411         if (buflen == 0)
2412                 return 0;
2413         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
2414                 if ((error = wi_seek_bap(sc, id, off)) != 0)
2415                         return error;
2416         }
2417         cnt = (buflen + 1) / 2;
2418         ptr = (u_int16_t *)buf;
2419         for (i = 0; i < cnt; i++)
2420                 *ptr++ = CSR_READ_2(sc, WI_DATA0);
2421         sc->sc_bap_off += cnt * 2;
2422         return 0;
2423 }
2424
2425 static int
2426 wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
2427 {
2428         u_int16_t *ptr;
2429         int i, error, cnt;
2430
2431         if (buflen == 0)
2432                 return 0;
2433
2434 #ifdef WI_HERMES_AUTOINC_WAR
2435   again:
2436 #endif
2437         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
2438                 if ((error = wi_seek_bap(sc, id, off)) != 0)
2439                         return error;
2440         }
2441         cnt = (buflen + 1) / 2;
2442         ptr = (u_int16_t *)buf;
2443         for (i = 0; i < cnt; i++)
2444                 CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
2445         sc->sc_bap_off += cnt * 2;
2446
2447 #ifdef WI_HERMES_AUTOINC_WAR
2448         /*
2449          * According to the comments in the HCF Light code, there is a bug
2450          * in the Hermes (or possibly in certain Hermes firmware revisions)
2451          * where the chip's internal autoincrement counter gets thrown off
2452          * during data writes:  the autoincrement is missed, causing one
2453          * data word to be overwritten and subsequent words to be written to
2454          * the wrong memory locations. The end result is that we could end
2455          * up transmitting bogus frames without realizing it. The workaround
2456          * for this is to write a couple of extra guard words after the end
2457          * of the transfer, then attempt to read then back. If we fail to
2458          * locate the guard words where we expect them, we preform the
2459          * transfer over again.
2460          */
2461         if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
2462                 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
2463                 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
2464                 wi_seek_bap(sc, id, sc->sc_bap_off);
2465                 sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
2466                 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
2467                     CSR_READ_2(sc, WI_DATA0) != 0x5678) {
2468                         if_printf(&sc->sc_ic.ic_if,
2469                                   "detect auto increment bug, try again\n");
2470                         goto again;
2471                 }
2472         }
2473 #endif
2474         return 0;
2475 }
2476
2477 static int
2478 wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen)
2479 {
2480         int error, len;
2481         struct mbuf *m;
2482
2483         for (m = m0; m != NULL && totlen > 0; m = m->m_next) {
2484                 if (m->m_len == 0)
2485                         continue;
2486
2487                 len = min(m->m_len, totlen);
2488
2489                 if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) {
2490                         m_copydata(m, 0, totlen, (caddr_t)&sc->sc_txbuf);
2491                         return wi_write_bap(sc, id, off, (caddr_t)&sc->sc_txbuf,
2492                             totlen);
2493                 }
2494
2495                 if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0)
2496                         return error;
2497
2498                 off += m->m_len;
2499                 totlen -= len;
2500         }
2501         return 0;
2502 }
2503
2504 static int
2505 wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
2506 {
2507         int i;
2508
2509         if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
2510                 if_printf(&sc->sc_ic.ic_if,
2511                           "failed to allocate %d bytes on NIC\n", len);
2512                 return ENOMEM;
2513         }
2514
2515         for (i = 0; i < WI_TIMEOUT; i++) {
2516                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
2517                         break;
2518                 if (i == WI_TIMEOUT) {
2519                         if_printf(&sc->sc_ic.ic_if, "timeout in alloc\n");
2520                         return ETIMEDOUT;
2521                 }
2522                 DELAY(1);
2523         }
2524         *idp = CSR_READ_2(sc, WI_ALLOC_FID);
2525         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
2526         return 0;
2527 }
2528
2529 static int
2530 wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
2531 {
2532         int error, len;
2533         u_int16_t ltbuf[2];
2534
2535         /* Tell the NIC to enter record read mode. */
2536         error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
2537         if (error)
2538                 return error;
2539
2540         error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2541         if (error)
2542                 return error;
2543
2544         if (le16toh(ltbuf[1]) != rid) {
2545                 if_printf(&sc->sc_ic.ic_if,
2546                           "record read mismatch, rid=%x, got=%x\n",
2547                           rid, le16toh(ltbuf[1]));
2548                 return EIO;
2549         }
2550         len = (le16toh(ltbuf[0]) - 1) * 2;       /* already got rid */
2551         if (*buflenp < len) {
2552                 if_printf(&sc->sc_ic.ic_if, "record buffer is too small, "
2553                           "rid=%x, size=%d, len=%d\n", rid, *buflenp, len);
2554                 return ENOSPC;
2555         }
2556         *buflenp = len;
2557         return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
2558 }
2559
2560 static int
2561 wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
2562 {
2563         int error;
2564         u_int16_t ltbuf[2];
2565
2566         ltbuf[0] = htole16((buflen + 1) / 2 + 1);        /* includes rid */
2567         ltbuf[1] = htole16(rid);
2568
2569         error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2570         if (error)
2571                 return error;
2572         error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
2573         if (error)
2574                 return error;
2575
2576         return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
2577 }
2578
2579 static int
2580 wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
2581 {
2582         struct ifnet *ifp = &ic->ic_if;
2583         struct wi_softc *sc = ifp->if_softc;
2584         struct ieee80211_node *ni = ic->ic_bss;
2585         int buflen;
2586         u_int16_t val;
2587         struct wi_ssid ssid;
2588         u_int8_t old_bssid[IEEE80211_ADDR_LEN];
2589
2590         DPRINTF((ifp, "%s: %s -> %s\n", __func__,
2591                 ieee80211_state_name[ic->ic_state],
2592                 ieee80211_state_name[nstate]));
2593
2594         switch (nstate) {
2595         case IEEE80211_S_INIT:
2596                 ic->ic_flags &= ~IEEE80211_F_SIBSS;
2597                 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2598                 return (*sc->sc_newstate)(ic, nstate, arg);
2599
2600         case IEEE80211_S_RUN:
2601                 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2602                 buflen = IEEE80211_ADDR_LEN;
2603                 wi_read_rid(sc, WI_RID_CURRENT_BSSID, ni->ni_bssid, &buflen);
2604                 IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid);
2605                 buflen = sizeof(val);
2606                 wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
2607                 /* XXX validate channel */
2608                 ni->ni_chan = &ic->ic_channels[le16toh(val)];
2609                 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2610                         htole16(ni->ni_chan->ic_freq);
2611                 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2612                         htole16(ni->ni_chan->ic_flags);
2613
2614                 if (IEEE80211_ADDR_EQ(old_bssid, ni->ni_bssid))
2615                         sc->sc_false_syns++;
2616                 else
2617                         sc->sc_false_syns = 0;
2618
2619                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
2620                         ni->ni_esslen = ic->ic_des_esslen;
2621                         memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
2622                         ni->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B];
2623                         ni->ni_intval = ic->ic_lintval;
2624                         ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
2625                         if (ic->ic_flags & IEEE80211_F_WEPON)
2626                                 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
2627                 } else {
2628                         /* XXX check return value */
2629                         buflen = sizeof(ssid);
2630                         wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen);
2631                         ni->ni_esslen = le16toh(ssid.wi_len);
2632                         if (ni->ni_esslen > IEEE80211_NWID_LEN)
2633                                 ni->ni_esslen = IEEE80211_NWID_LEN;     /*XXX*/
2634                         memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
2635                 }
2636                 break;
2637
2638         case IEEE80211_S_SCAN:
2639         case IEEE80211_S_AUTH:
2640         case IEEE80211_S_ASSOC:
2641                 break;
2642         }
2643
2644         ic->ic_state = nstate;          /* NB: skip normal ieee80211 handling */
2645         return 0;
2646 }
2647
2648 static int
2649 wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate)
2650 {
2651         int error = 0;
2652         u_int16_t val[2];
2653
2654         if (!sc->sc_enabled)
2655                 return ENXIO;
2656         switch (sc->sc_firmware_type) {
2657         case WI_LUCENT:
2658                 (void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
2659                 break;
2660         case WI_INTERSIL:
2661                 val[0] = chanmask;      /* channel */
2662                 val[1] = txrate;        /* tx rate */
2663                 error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
2664                 break;
2665         case WI_SYMBOL:
2666                 /*
2667                  * XXX only supported on 3.x ?
2668                  */
2669                 val[0] = BSCAN_BCAST | BSCAN_ONETIME;
2670                 error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
2671                     val, sizeof(val[0]));
2672                 break;
2673         }
2674         if (error == 0) {
2675                 sc->sc_scan_timer = WI_SCAN_WAIT;
2676                 sc->sc_ic.ic_if.if_timer = 1;
2677                 DPRINTF((&sc->sc_ic.ic_if, "wi_scan_ap: start scanning, "
2678                         "chamask 0x%x txrate 0x%x\n", chanmask, txrate));
2679         }
2680         return error;
2681 }
2682
2683 static void
2684 wi_scan_result(struct wi_softc *sc, int fid, int cnt)
2685 {
2686 #define N(a)    (sizeof (a) / sizeof (a[0]))
2687         int i, naps, off, szbuf;
2688         struct wi_scan_header ws_hdr;   /* Prism2 header */
2689         struct wi_scan_data_p2 ws_dat;  /* Prism2 scantable*/
2690         struct wi_apinfo *ap;
2691
2692         off = sizeof(u_int16_t) * 2;
2693         memset(&ws_hdr, 0, sizeof(ws_hdr));
2694         switch (sc->sc_firmware_type) {
2695         case WI_INTERSIL:
2696                 wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
2697                 off += sizeof(ws_hdr);
2698                 szbuf = sizeof(struct wi_scan_data_p2);
2699                 break;
2700         case WI_SYMBOL:
2701                 szbuf = sizeof(struct wi_scan_data_p2) + 6;
2702                 break;
2703         case WI_LUCENT:
2704                 szbuf = sizeof(struct wi_scan_data);
2705                 break;
2706         default:
2707                 if_printf(&sc->sc_ic.ic_if,
2708                           "wi_scan_result: unknown firmware type %u\n",
2709                           sc->sc_firmware_type);
2710                 naps = 0;
2711                 goto done;
2712         }
2713         naps = (cnt * 2 + 2 - off) / szbuf;
2714         if (naps > N(sc->sc_aps))
2715                 naps = N(sc->sc_aps);
2716         sc->sc_naps = naps;
2717         /* Read Data */
2718         ap = sc->sc_aps;
2719         memset(&ws_dat, 0, sizeof(ws_dat));
2720         for (i = 0; i < naps; i++, ap++) {
2721                 wi_read_bap(sc, fid, off, &ws_dat,
2722                     (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
2723                 DPRINTF2((&sc->sc_ic.ic_if,
2724                           "wi_scan_result: #%d: off %d bssid %6D\n",
2725                           i, off, ws_dat.wi_bssid, ":"));
2726                 off += szbuf;
2727                 ap->scanreason = le16toh(ws_hdr.wi_reason);
2728                 memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
2729                 ap->channel = le16toh(ws_dat.wi_chid);
2730                 ap->signal  = le16toh(ws_dat.wi_signal);
2731                 ap->noise   = le16toh(ws_dat.wi_noise);
2732                 ap->quality = ap->signal - ap->noise;
2733                 ap->capinfo = le16toh(ws_dat.wi_capinfo);
2734                 ap->interval = le16toh(ws_dat.wi_interval);
2735                 ap->rate    = le16toh(ws_dat.wi_rate);
2736                 ap->namelen = le16toh(ws_dat.wi_namelen);
2737                 if (ap->namelen > sizeof(ap->name))
2738                         ap->namelen = sizeof(ap->name);
2739                 memcpy(ap->name, ws_dat.wi_name, ap->namelen);
2740         }
2741 done:
2742         /* Done scanning */
2743         sc->sc_scan_timer = 0;
2744         DPRINTF((&sc->sc_ic.ic_if, "wi_scan_result: scan complete: ap %d\n",
2745                  naps));
2746 #undef N
2747 }
2748
2749 static void
2750 wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
2751 {
2752         ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
2753             ni ? ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL : -1, rssi);
2754         printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
2755                 le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
2756                 le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
2757         printf(" rx_signal %u rx_rate %u rx_flow %u\n",
2758                 wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow);
2759         printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
2760                 wh->wi_tx_rtry, wh->wi_tx_rate,
2761                 le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len));
2762         printf(" ehdr dst %6D src %6D type 0x%x\n",
2763                 wh->wi_ehdr.ether_dhost, ":", wh->wi_ehdr.ether_shost, ":",
2764                 wh->wi_ehdr.ether_type);
2765 }
2766
2767 int
2768 wi_alloc(device_t dev, int rid)
2769 {
2770         struct wi_softc *sc = device_get_softc(dev);
2771
2772         if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
2773                 sc->iobase_rid = rid;
2774                 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
2775                     &sc->iobase_rid, 0, ~0, (1 << 6),
2776                     rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
2777                 if (!sc->iobase) {
2778                         device_printf(dev, "No I/O space?!\n");
2779                         return (ENXIO);
2780                 }
2781
2782                 sc->wi_io_addr = rman_get_start(sc->iobase);
2783                 sc->wi_btag = rman_get_bustag(sc->iobase);
2784                 sc->wi_bhandle = rman_get_bushandle(sc->iobase);
2785         } else {
2786                 sc->mem_rid = rid;
2787                 sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
2788                     &sc->mem_rid, RF_ACTIVE);
2789
2790                 if (!sc->mem) {
2791                         device_printf(dev, "No Mem space on prism2.5?\n");
2792                         return (ENXIO);
2793                 }
2794
2795                 sc->wi_btag = rman_get_bustag(sc->mem);
2796                 sc->wi_bhandle = rman_get_bushandle(sc->mem);
2797         }
2798
2799
2800         sc->irq_rid = 0;
2801         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
2802             RF_ACTIVE |
2803             ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
2804
2805         if (!sc->irq) {
2806                 wi_free(dev);
2807                 device_printf(dev, "No irq?!\n");
2808                 return (ENXIO);
2809         }
2810
2811         return (0);
2812 }
2813
2814 void
2815 wi_free(device_t dev)
2816 {
2817         struct wi_softc *sc = device_get_softc(dev);
2818
2819         if (sc->wi_intrhand != NULL) {
2820                 bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
2821                 sc->wi_intrhand = NULL;
2822         }
2823         if (sc->iobase != NULL) {
2824                 bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
2825                 sc->iobase = NULL;
2826         }
2827         if (sc->irq != NULL) {
2828                 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
2829                 sc->irq = NULL;
2830         }
2831         if (sc->mem != NULL) {
2832                 bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
2833                 sc->mem = NULL;
2834         }
2835 }
2836
2837 static int
2838 wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
2839 {
2840         int error = 0;
2841
2842         wreq->wi_len = 1;
2843
2844         switch (wreq->wi_type) {
2845         case WI_DEBUG_SLEEP:
2846                 wreq->wi_len++;
2847                 wreq->wi_val[0] = sc->wi_debug.wi_sleep;
2848                 break;
2849         case WI_DEBUG_DELAYSUPP:
2850                 wreq->wi_len++;
2851                 wreq->wi_val[0] = sc->wi_debug.wi_delaysupp;
2852                 break;
2853         case WI_DEBUG_TXSUPP:
2854                 wreq->wi_len++;
2855                 wreq->wi_val[0] = sc->wi_debug.wi_txsupp;
2856                 break;
2857         case WI_DEBUG_MONITOR:
2858                 wreq->wi_len++;
2859                 wreq->wi_val[0] = sc->wi_debug.wi_monitor;
2860                 break;
2861         case WI_DEBUG_LEDTEST:
2862                 wreq->wi_len += 3;
2863                 wreq->wi_val[0] = sc->wi_debug.wi_ledtest;
2864                 wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0;
2865                 wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1;
2866                 break;
2867         case WI_DEBUG_CONTTX:
2868                 wreq->wi_len += 2;
2869                 wreq->wi_val[0] = sc->wi_debug.wi_conttx;
2870                 wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0;
2871                 break;
2872         case WI_DEBUG_CONTRX:
2873                 wreq->wi_len++;
2874                 wreq->wi_val[0] = sc->wi_debug.wi_contrx;
2875                 break;
2876         case WI_DEBUG_SIGSTATE:
2877                 wreq->wi_len += 2;
2878                 wreq->wi_val[0] = sc->wi_debug.wi_sigstate;
2879                 wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0;
2880                 break;
2881         case WI_DEBUG_CONFBITS:
2882                 wreq->wi_len += 2;
2883                 wreq->wi_val[0] = sc->wi_debug.wi_confbits;
2884                 wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0;
2885                 break;
2886         default:
2887                 error = EIO;
2888                 break;
2889         }
2890
2891         return (error);
2892 }
2893
2894 static int
2895 wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
2896 {
2897         int error = 0;
2898         u_int16_t               cmd, param0 = 0, param1 = 0;
2899
2900         switch (wreq->wi_type) {
2901         case WI_DEBUG_RESET:
2902         case WI_DEBUG_INIT:
2903         case WI_DEBUG_CALENABLE:
2904                 break;
2905         case WI_DEBUG_SLEEP:
2906                 sc->wi_debug.wi_sleep = 1;
2907                 break;
2908         case WI_DEBUG_WAKE:
2909                 sc->wi_debug.wi_sleep = 0;
2910                 break;
2911         case WI_DEBUG_CHAN:
2912                 param0 = wreq->wi_val[0];
2913                 break;
2914         case WI_DEBUG_DELAYSUPP:
2915                 sc->wi_debug.wi_delaysupp = 1;
2916                 break;
2917         case WI_DEBUG_TXSUPP:
2918                 sc->wi_debug.wi_txsupp = 1;
2919                 break;
2920         case WI_DEBUG_MONITOR:
2921                 sc->wi_debug.wi_monitor = 1;
2922                 break;
2923         case WI_DEBUG_LEDTEST:
2924                 param0 = wreq->wi_val[0];
2925                 param1 = wreq->wi_val[1];
2926                 sc->wi_debug.wi_ledtest = 1;
2927                 sc->wi_debug.wi_ledtest_param0 = param0;
2928                 sc->wi_debug.wi_ledtest_param1 = param1;
2929                 break;
2930         case WI_DEBUG_CONTTX:
2931                 param0 = wreq->wi_val[0];
2932                 sc->wi_debug.wi_conttx = 1;
2933                 sc->wi_debug.wi_conttx_param0 = param0;
2934                 break;
2935         case WI_DEBUG_STOPTEST:
2936                 sc->wi_debug.wi_delaysupp = 0;
2937                 sc->wi_debug.wi_txsupp = 0;
2938                 sc->wi_debug.wi_monitor = 0;
2939                 sc->wi_debug.wi_ledtest = 0;
2940                 sc->wi_debug.wi_ledtest_param0 = 0;
2941                 sc->wi_debug.wi_ledtest_param1 = 0;
2942                 sc->wi_debug.wi_conttx = 0;
2943                 sc->wi_debug.wi_conttx_param0 = 0;
2944                 sc->wi_debug.wi_contrx = 0;
2945                 sc->wi_debug.wi_sigstate = 0;
2946                 sc->wi_debug.wi_sigstate_param0 = 0;
2947                 break;
2948         case WI_DEBUG_CONTRX:
2949                 sc->wi_debug.wi_contrx = 1;
2950                 break;
2951         case WI_DEBUG_SIGSTATE:
2952                 param0 = wreq->wi_val[0];
2953                 sc->wi_debug.wi_sigstate = 1;
2954                 sc->wi_debug.wi_sigstate_param0 = param0;
2955                 break;
2956         case WI_DEBUG_CONFBITS:
2957                 param0 = wreq->wi_val[0];
2958                 param1 = wreq->wi_val[1];
2959                 sc->wi_debug.wi_confbits = param0;
2960                 sc->wi_debug.wi_confbits_param0 = param1;
2961                 break;
2962         default:
2963                 error = EIO;
2964                 break;
2965         }
2966
2967         if (error)
2968                 return (error);
2969
2970         cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
2971         error = wi_cmd(sc, cmd, param0, param1, 0);
2972
2973         return (error);
2974 }
2975
2976 /*
2977  * Special routines to download firmware for Symbol CF card.
2978  * XXX: This should be modified generic into any PRISM-2 based card.
2979  */
2980
2981 #define WI_SBCF_PDIADDR         0x3100
2982
2983 /* unaligned load little endian */
2984 #define GETLE32(p)      ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
2985 #define GETLE16(p)      ((p)[0] | ((p)[1]<<8))
2986
2987 int
2988 wi_symbol_load_firm(struct wi_softc *sc, const void *primsym, int primlen,
2989     const void *secsym, int seclen)
2990 {
2991         uint8_t ebuf[256];
2992         int i;
2993
2994         /* load primary code and run it */
2995         wi_symbol_set_hcr(sc, WI_HCR_EEHOLD);
2996         if (wi_symbol_write_firm(sc, primsym, primlen, NULL, 0))
2997                 return EIO;
2998         wi_symbol_set_hcr(sc, WI_HCR_RUN);
2999         for (i = 0; ; i++) {
3000                 if (i == 10)
3001                         return ETIMEDOUT;
3002                 tsleep(sc, 0, "wiinit", 1);
3003                 if (CSR_READ_2(sc, WI_CNTL) == WI_CNTL_AUX_ENA_STAT)
3004                         break;
3005                 /* write the magic key value to unlock aux port */
3006                 CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0);
3007                 CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1);
3008                 CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2);
3009                 CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL);
3010         }
3011
3012         /* issue read EEPROM command: XXX copied from wi_cmd() */
3013         CSR_WRITE_2(sc, WI_PARAM0, 0);
3014         CSR_WRITE_2(sc, WI_PARAM1, 0);
3015         CSR_WRITE_2(sc, WI_PARAM2, 0);
3016         CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE);
3017         for (i = 0; i < WI_TIMEOUT; i++) {
3018                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
3019                         break;
3020                 DELAY(1);
3021         }
3022         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
3023
3024         CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ);
3025         CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ);
3026         CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA,
3027             (uint16_t *)ebuf, sizeof(ebuf) / 2);
3028         if (GETLE16(ebuf) > sizeof(ebuf))
3029                 return EIO;
3030         if (wi_symbol_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf)))
3031                 return EIO;
3032         return 0;
3033 }
3034
3035 static int
3036 wi_symbol_write_firm(struct wi_softc *sc, const void *buf, int buflen,
3037     const void *ebuf, int ebuflen)
3038 {
3039         const uint8_t *p, *ep, *q, *eq;
3040         char *tp;
3041         uint32_t addr, id, eid;
3042         int i, len, elen, nblk, pdrlen;
3043
3044         /*
3045          * Parse the header of the firmware image.
3046          */
3047         p = buf;
3048         ep = p + buflen;
3049         while (p < ep && *p++ != ' ');  /* FILE: */
3050         while (p < ep && *p++ != ' ');  /* filename */
3051         while (p < ep && *p++ != ' ');  /* type of the firmware */
3052         nblk = strtoul(p, &tp, 10);
3053         p = tp;
3054         pdrlen = strtoul(p + 1, &tp, 10);
3055         p = tp;
3056         while (p < ep && *p++ != 0x1a); /* skip rest of header */
3057
3058         /*
3059          * Block records: address[4], length[2], data[length];
3060          */
3061         for (i = 0; i < nblk; i++) {
3062                 addr = GETLE32(p);      p += 4;
3063                 len  = GETLE16(p);      p += 2;
3064                 CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
3065                 CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
3066                 CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
3067                     (const uint16_t *)p, len / 2);
3068                 p += len;
3069         }
3070         
3071         /*
3072          * PDR: id[4], address[4], length[4];
3073          */
3074         for (i = 0; i < pdrlen; ) {
3075                 id   = GETLE32(p);      p += 4; i += 4;
3076                 addr = GETLE32(p);      p += 4; i += 4;
3077                 len  = GETLE32(p);      p += 4; i += 4;
3078                 /* replace PDR entry with the values from EEPROM, if any */
3079                 for (q = ebuf, eq = q + ebuflen; q < eq; q += elen * 2) {
3080                         elen = GETLE16(q);      q += 2;
3081                         eid  = GETLE16(q);      q += 2;
3082                         elen--;         /* elen includes eid */
3083                         if (eid == 0)
3084                                 break;
3085                         if (eid != id)
3086                                 continue;
3087                         CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
3088                         CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
3089                         CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
3090                             (const uint16_t *)q, len / 2);
3091                         break;
3092                 }
3093         }
3094         return 0;
3095 }
3096
3097 static int
3098 wi_symbol_set_hcr(struct wi_softc *sc, int mode)
3099 {
3100         uint16_t hcr;
3101
3102         CSR_WRITE_2(sc, WI_COR, WI_COR_RESET);
3103         tsleep(sc, 0, "wiinit", 1);
3104         hcr = CSR_READ_2(sc, WI_HCR);
3105         hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE);
3106         CSR_WRITE_2(sc, WI_HCR, hcr);
3107         tsleep(sc, 0, "wiinit", 1);
3108         CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE);
3109         tsleep(sc, 0, "wiinit", 1);
3110         return 0;
3111 }