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