Make all network interrupt service routines MPSAFE part 1/3.
[dragonfly.git] / sys / dev / netif / owi / if_owi.c
1 /*
2  * Copyright (c) 1997, 1998, 1999
3  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Bill Paul.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * $FreeBSD: src/sys/dev/wi/if_wi.c,v 1.103.2.2 2002/08/02 07:11:34 imp Exp $
33  * $DragonFly: src/sys/dev/netif/owi/Attic/if_owi.c,v 1.13 2005/11/28 17:13:43 dillon Exp $
34  */
35
36 /*
37  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD.
38  *
39  * Written by Bill Paul <wpaul@ctr.columbia.edu>
40  * Electrical Engineering Department
41  * Columbia University, New York City
42  */
43
44 /*
45  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
46  * from Lucent. Unlike the older cards, the new ones are programmed
47  * entirely via a firmware-driven controller called the Hermes.
48  * Unfortunately, Lucent will not release the Hermes programming manual
49  * without an NDA (if at all). What they do release is an API library
50  * called the HCF (Hardware Control Functions) which is supposed to
51  * do the device-specific operations of a device driver for you. The
52  * publically available version of the HCF library (the 'HCF Light') is 
53  * a) extremely gross, b) lacks certain features, particularly support
54  * for 802.11 frames, and c) is contaminated by the GNU Public License.
55  *
56  * This driver does not use the HCF or HCF Light at all. Instead, it
57  * programs the Hermes controller directly, using information gleaned
58  * from the HCF Light code and corresponding documentation.
59  *
60  * This driver supports the ISA, PCMCIA and PCI versions of the Lucent
61  * WaveLan cards (based on the Hermes chipset), as well as the newer
62  * Prism 2 chipsets with firmware from Intersil and Symbol.
63  */
64
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/endian.h>
68 #include <sys/sockio.h>
69 #include <sys/mbuf.h>
70 #include <sys/proc.h>
71 #include <sys/kernel.h>
72 #include <sys/socket.h>
73 #include <sys/module.h>
74 #include <sys/bus.h>
75 #include <sys/random.h>
76 #include <sys/syslog.h>
77 #include <sys/sysctl.h>
78 #include <sys/serialize.h>
79 #include <sys/thread2.h>
80
81 #include <machine/bus.h>
82 #include <machine/resource.h>
83 #include <machine/clock.h>
84 #include <sys/rman.h>
85
86 #include <net/if.h>
87 #include <net/ifq_var.h>
88 #include <net/if_arp.h>
89 #include <net/ethernet.h>
90 #include <net/if_dl.h>
91 #include <net/if_media.h>
92 #include <net/if_types.h>
93 #include <netproto/802_11/ieee80211.h>
94 #include <netproto/802_11/ieee80211_ioctl.h>
95 #include <netproto/802_11/if_wavelan_ieee.h>
96
97 #include <netinet/in.h>
98 #include <netinet/in_systm.h>
99 #include <netinet/in_var.h>
100 #include <netinet/ip.h>
101 #include <netinet/if_ether.h>
102
103 #include <net/bpf.h>
104
105 #include "wi_hostap.h"
106 #include "if_wivar.h"
107 #include "if_wireg.h"
108
109 #define WI_CMD_DEBUG            0x0038 /* prism2 debug */
110
111 static void wi_intr(void *);
112 static void wi_reset(struct wi_softc *);
113 static int wi_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
114 static void wi_init(void *);
115 static void wi_start(struct ifnet *);
116 static void wi_stop(struct wi_softc *);
117 static void wi_watchdog(struct ifnet *);
118 static void wi_rxeof(struct wi_softc *);
119 static void wi_txeof(struct wi_softc *, int);
120 static void wi_update_stats(struct wi_softc *);
121 static void wi_setmulti(struct wi_softc *);
122
123 static int wi_cmd(struct wi_softc *, int, int, int, int);
124 static int wi_read_record(struct wi_softc *, struct wi_ltv_gen *);
125 static int wi_write_record(struct wi_softc *, struct wi_ltv_gen *);
126 static int wi_read_data(struct wi_softc *, int, int, caddr_t, int);
127 static int wi_write_data(struct wi_softc *, int, int, caddr_t, int);
128 static int wi_seek(struct wi_softc *, int, int, int);
129 static int wi_alloc_nicmem(struct wi_softc *, int, int *);
130 static void wi_inquire(void *);
131 static void wi_setdef(struct wi_softc *, struct wi_req *);
132
133 #ifdef WICACHE
134 static
135 void wi_cache_store(struct wi_softc *, struct mbuf *, unsigned short);
136 #endif
137
138 static int wi_get_cur_ssid(struct wi_softc *, char *, int *);
139 static void wi_get_id(struct wi_softc *);
140 static int wi_media_change(struct ifnet *);
141 static void wi_media_status(struct ifnet *, struct ifmediareq *);
142
143 static int wi_get_debug(struct wi_softc *, struct wi_req *);
144 static int wi_set_debug(struct wi_softc *, struct wi_req *);
145
146 DECLARE_DUMMY_MODULE(if_wi);
147
148 devclass_t owi_devclass;
149
150 static struct wi_card_ident wi_card_ident[] = {
151         /* CARD_ID                      CARD_NAME               FIRM_TYPE */
152         { WI_NIC_LUCENT_ID,             WI_NIC_LUCENT_STR,      WI_LUCENT },
153         { WI_NIC_SONY_ID,               WI_NIC_SONY_STR,        WI_LUCENT },
154         { WI_NIC_LUCENT_EMB_ID,         WI_NIC_LUCENT_EMB_STR,  WI_LUCENT },
155         { WI_NIC_EVB2_ID,               WI_NIC_EVB2_STR,        WI_INTERSIL },
156         { WI_NIC_HWB3763_ID,            WI_NIC_HWB3763_STR,     WI_INTERSIL },
157         { WI_NIC_HWB3163_ID,            WI_NIC_HWB3163_STR,     WI_INTERSIL },
158         { WI_NIC_HWB3163B_ID,           WI_NIC_HWB3163B_STR,    WI_INTERSIL },
159         { WI_NIC_EVB3_ID,               WI_NIC_EVB3_STR,        WI_INTERSIL },
160         { WI_NIC_HWB1153_ID,            WI_NIC_HWB1153_STR,     WI_INTERSIL },
161         { WI_NIC_P2_SST_ID,             WI_NIC_P2_SST_STR,      WI_INTERSIL },
162         { WI_NIC_EVB2_SST_ID,           WI_NIC_EVB2_SST_STR,    WI_INTERSIL },
163         { WI_NIC_3842_EVA_ID,           WI_NIC_3842_EVA_STR,    WI_INTERSIL },
164         { WI_NIC_3842_PCMCIA_AMD_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
165         { WI_NIC_3842_PCMCIA_SST_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
166         { WI_NIC_3842_PCMCIA_ATM_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
167         { WI_NIC_3842_MINI_AMD_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
168         { WI_NIC_3842_MINI_SST_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
169         { WI_NIC_3842_MINI_ATM_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
170         { WI_NIC_3842_PCI_AMD_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
171         { WI_NIC_3842_PCI_SST_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
172         { WI_NIC_3842_PCI_ATM_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
173         { WI_NIC_P3_PCMCIA_AMD_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
174         { WI_NIC_P3_PCMCIA_SST_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
175         { WI_NIC_P3_MINI_AMD_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
176         { WI_NIC_P3_MINI_SST_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
177         { 0,    NULL,   0 },
178 };
179
180 int
181 owi_generic_detach(dev)
182         device_t                dev;
183 {
184         struct wi_softc *sc = device_get_softc(dev);
185         struct ifnet *ifp = &sc->arpcom.ac_if;
186
187         lwkt_serialize_enter(ifp->if_serializer);
188
189         if (sc->wi_gone) {
190                 device_printf(dev, "already unloaded\n");
191                 lwkt_serialize_exit(ifp->if_serializer);
192                 return(ENODEV);
193         }
194
195         wi_stop(sc);
196
197         /* Delete all remaining media. */
198         ifmedia_removeall(&sc->ifmedia);
199         ether_ifdetach(ifp);
200         bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
201         owi_free(dev);
202         sc->wi_gone = 1;
203
204         lwkt_serialize_exit(ifp->if_serializer);
205         return(0);
206 }
207
208 int
209 owi_generic_attach(device_t dev)
210 {
211         struct wi_softc         *sc;
212         struct wi_ltv_macaddr   mac;
213         struct wi_ltv_gen       gen;
214         struct ifnet            *ifp;
215         int                     error;
216
217         /* XXX maybe we need the splimp stuff here XXX */
218         sc = device_get_softc(dev);
219         ifp = &sc->arpcom.ac_if;
220         callout_init(&sc->wi_stat_timer);
221
222 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
223         mtx_init(&sc->wi_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
224             MTX_DEF | MTX_RECURSE);
225 #endif
226
227         /* Reset the NIC. */
228         wi_reset(sc);
229
230         /*
231          * Read the station address.
232          * And do it twice. I've seen PRISM-based cards that return
233          * an error when trying to read it the first time, which causes
234          * the probe to fail.
235          */
236         mac.wi_type = WI_RID_MAC_NODE;
237         mac.wi_len = 4;
238         wi_read_record(sc, (struct wi_ltv_gen *)&mac);
239         if ((error = wi_read_record(sc, (struct wi_ltv_gen *)&mac)) != 0) {
240                 device_printf(dev, "mac read failed %d\n", error);
241                 owi_free(dev);
242                 return (error);
243         }
244         bcopy((char *)&mac.wi_mac_addr,
245            (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
246
247         wi_get_id(sc);
248
249         ifp->if_softc = sc;
250         if_initname(ifp, "wi", sc->wi_unit);
251         ifp->if_mtu = ETHERMTU;
252         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
253         ifp->if_ioctl = wi_ioctl;
254         ifp->if_start = wi_start;
255         ifp->if_watchdog = wi_watchdog;
256         ifp->if_init = wi_init;
257         ifp->if_baudrate = 10000000;
258         ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
259         ifq_set_ready(&ifp->if_snd);
260
261         bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
262         bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
263             sizeof(WI_DEFAULT_NODENAME) - 1);
264
265         bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
266         bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name,
267             sizeof(WI_DEFAULT_NETNAME) - 1);
268
269         bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
270         bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name,
271             sizeof(WI_DEFAULT_IBSS) - 1);
272
273         sc->wi_portnum = WI_DEFAULT_PORT;
274         sc->wi_ptype = WI_PORTTYPE_BSS;
275         sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
276         sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
277         sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
278         sc->wi_max_data_len = WI_DEFAULT_DATALEN;
279         sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
280         sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
281         sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
282         sc->wi_roaming = WI_DEFAULT_ROAMING;
283         sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
284         sc->wi_authmode = IEEE80211_AUTH_OPEN;
285
286         /*
287          * Read the default channel from the NIC. This may vary
288          * depending on the country where the NIC was purchased, so
289          * we can't hard-code a default and expect it to work for
290          * everyone.
291          */
292         gen.wi_type = WI_RID_OWN_CHNL;
293         gen.wi_len = 2;
294         wi_read_record(sc, &gen);
295         sc->wi_channel = gen.wi_val;
296
297         /*
298          * Set flags based on firmware version.
299          */
300         switch (sc->sc_firmware_type) {
301         case WI_LUCENT:
302                 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
303                 if (sc->sc_sta_firmware_ver >= 60000)
304                         sc->wi_flags |= WI_FLAGS_HAS_MOR;
305                 if (sc->sc_sta_firmware_ver >= 60006) {
306                         sc->wi_flags |= WI_FLAGS_HAS_IBSS;
307                         sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
308                 }
309                 sc->wi_ibss_port = htole16(1);
310                 break;
311         case WI_INTERSIL:
312                 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
313                 if (sc->sc_sta_firmware_ver >= 800) {
314                         sc->wi_flags |= WI_FLAGS_HAS_IBSS;
315                         sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
316                 }
317                 /*
318                  * version 0.8.3 and newer are the only ones that are known
319                  * to currently work.  Earlier versions can be made to work,
320                  * at least according to the Linux driver.
321                  */
322                 if (sc->sc_sta_firmware_ver >= 803)
323                         sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
324                 sc->wi_ibss_port = htole16(0);
325                 break;
326         case WI_SYMBOL:
327                 sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
328                 if (sc->sc_sta_firmware_ver >= 20000)
329                         sc->wi_flags |= WI_FLAGS_HAS_IBSS;
330                 /* Older Symbol firmware does not support IBSS creation. */
331                 if (sc->sc_sta_firmware_ver >= 25000)
332                         sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
333                 sc->wi_ibss_port = htole16(4);
334                 break;
335         }
336
337         /*
338          * Find out if we support WEP on this card.
339          */
340         gen.wi_type = WI_RID_WEP_AVAIL;
341         gen.wi_len = 2;
342         wi_read_record(sc, &gen);
343         sc->wi_has_wep = gen.wi_val;
344
345         if (bootverbose)
346                 device_printf(sc->dev, "wi_has_wep = %d\n", sc->wi_has_wep);
347
348         /* 
349          * Find supported rates.
350          */
351         gen.wi_type = WI_RID_DATA_RATES;
352         gen.wi_len = 2;
353         if (wi_read_record(sc, &gen))
354                 sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
355                     WI_SUPPRATES_5M | WI_SUPPRATES_11M;
356         else
357                 sc->wi_supprates = gen.wi_val;
358
359         bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
360
361         wi_init(sc);
362         wi_stop(sc);
363
364         ifmedia_init(&sc->ifmedia, 0, wi_media_change, wi_media_status);
365 #define ADD(m, c)       ifmedia_add(&sc->ifmedia, (m), (c), NULL)
366         if (sc->wi_supprates & WI_SUPPRATES_1M) {
367                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
368                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
369                     IFM_IEEE80211_ADHOC, 0), 0);
370                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
371                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
372                             IFM_IEEE80211_IBSS, 0), 0);
373                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
374                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
375                             IFM_IEEE80211_IBSSMASTER, 0), 0);
376                 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
377                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
378                             IFM_IEEE80211_HOSTAP, 0), 0);
379         }
380         if (sc->wi_supprates & WI_SUPPRATES_2M) {
381                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
382                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
383                     IFM_IEEE80211_ADHOC, 0), 0);
384                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
385                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
386                             IFM_IEEE80211_IBSS, 0), 0);
387                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
388                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
389                             IFM_IEEE80211_IBSSMASTER, 0), 0);
390                 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
391                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
392                             IFM_IEEE80211_HOSTAP, 0), 0);
393         }
394         if (sc->wi_supprates & WI_SUPPRATES_5M) {
395                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
396                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
397                     IFM_IEEE80211_ADHOC, 0), 0);
398                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
399                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
400                             IFM_IEEE80211_IBSS, 0), 0);
401                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
402                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
403                             IFM_IEEE80211_IBSSMASTER, 0), 0);
404                 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
405                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
406                             IFM_IEEE80211_HOSTAP, 0), 0);
407         }
408         if (sc->wi_supprates & WI_SUPPRATES_11M) {
409                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
410                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
411                     IFM_IEEE80211_ADHOC, 0), 0);
412                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
413                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
414                             IFM_IEEE80211_IBSS, 0), 0);
415                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
416                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
417                             IFM_IEEE80211_IBSSMASTER, 0), 0);
418                 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
419                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
420                             IFM_IEEE80211_HOSTAP, 0), 0);
421                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
422         }
423         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
424         if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
425                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
426                     0), 0);
427         if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
428                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
429                     IFM_IEEE80211_IBSSMASTER, 0), 0);
430         if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
431                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
432                     IFM_IEEE80211_HOSTAP, 0), 0);
433         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
434 #undef ADD
435         ifmedia_set(&sc->ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
436
437         /*
438          * Call MI attach routine.
439          */
440         ether_ifattach(ifp, sc->arpcom.ac_enaddr, NULL);
441
442         error = bus_setup_intr(dev, sc->irq, INTR_NETSAFE,
443                                wi_intr, sc, &sc->wi_intrhand, 
444                                ifp->if_serializer);
445         if (error) {
446                 ether_ifdetach(ifp);
447                 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
448                 owi_free(dev);
449                 return (error);
450         }
451
452         return(0);
453 }
454
455 static void
456 wi_get_id(sc)
457         struct wi_softc *sc;
458 {
459         struct wi_ltv_ver       ver;
460         struct wi_card_ident    *id;
461
462         /* getting chip identity */
463         memset(&ver, 0, sizeof(ver));
464         ver.wi_type = WI_RID_CARD_ID;
465         ver.wi_len = 5;
466         wi_read_record(sc, (struct wi_ltv_gen *)&ver);
467         device_printf(sc->dev, "using ");
468         sc->sc_firmware_type = WI_NOTYPE;
469         for (id = wi_card_ident; id->card_name != NULL; id++) {
470                 if (le16toh(ver.wi_ver[0]) == id->card_id) {
471                         printf("%s", id->card_name);
472                         sc->sc_firmware_type = id->firm_type;
473                         break;
474                 }
475         }
476         if (sc->sc_firmware_type == WI_NOTYPE) {
477                 if (le16toh(ver.wi_ver[0]) & 0x8000) {
478                         printf("Unknown PRISM2 chip");
479                         sc->sc_firmware_type = WI_INTERSIL;
480                 } else {
481                         printf("Unknown Lucent chip");
482                         sc->sc_firmware_type = WI_LUCENT;
483                 }
484         }
485
486         if (sc->sc_firmware_type != WI_LUCENT) {
487                 /* get primary firmware version */
488                 memset(&ver, 0, sizeof(ver));
489                 ver.wi_type = WI_RID_PRI_IDENTITY;
490                 ver.wi_len = 5;
491                 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
492                 ver.wi_ver[1] = le16toh(ver.wi_ver[1]);
493                 ver.wi_ver[2] = le16toh(ver.wi_ver[2]);
494                 ver.wi_ver[3] = le16toh(ver.wi_ver[3]);
495                 sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
496                     ver.wi_ver[3] * 100 + ver.wi_ver[1];
497         }
498
499         /* get station firmware version */
500         memset(&ver, 0, sizeof(ver));
501         ver.wi_type = WI_RID_STA_IDENTITY;
502         ver.wi_len = 5;
503         wi_read_record(sc, (struct wi_ltv_gen *)&ver);
504         ver.wi_ver[1] = le16toh(ver.wi_ver[1]);
505         ver.wi_ver[2] = le16toh(ver.wi_ver[2]);
506         ver.wi_ver[3] = le16toh(ver.wi_ver[3]);
507         sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
508             ver.wi_ver[3] * 100 + ver.wi_ver[1];
509         if (sc->sc_firmware_type == WI_INTERSIL &&
510             (sc->sc_sta_firmware_ver == 10102 || 
511              sc->sc_sta_firmware_ver == 20102)) {
512                 struct wi_ltv_str sver;
513                 char *p;
514
515                 memset(&sver, 0, sizeof(sver));
516                 sver.wi_type = WI_RID_SYMBOL_IDENTITY;
517                 sver.wi_len = 7;
518                 /* value should be the format like "V2.00-11" */
519                 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
520                     *(p = (char *)sver.wi_str) >= 'A' &&
521                     p[2] == '.' && p[5] == '-' && p[8] == '\0') {
522                         sc->sc_firmware_type = WI_SYMBOL;
523                         sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
524                             (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
525                             (p[6] - '0') * 10 + (p[7] - '0');
526                 }
527         }
528         printf("\n");
529         device_printf(sc->dev, "%s Firmware: ",
530              sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
531             (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
532
533         /*
534          * The primary firmware is only valid on Prism based chipsets
535          * (INTERSIL or SYMBOL).
536          */
537         if (sc->sc_firmware_type != WI_LUCENT)
538             printf("Primary %u.%02u.%02u, ", sc->sc_pri_firmware_ver / 10000,
539                     (sc->sc_pri_firmware_ver % 10000) / 100,
540                     sc->sc_pri_firmware_ver % 100);
541         printf("Station %u.%02u.%02u\n",
542             sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
543             sc->sc_sta_firmware_ver % 100);
544         return;
545 }
546
547 static void
548 wi_rxeof(sc)
549         struct wi_softc         *sc;
550 {
551         struct ifnet            *ifp;
552         struct ether_header     *eh;
553         struct mbuf             *m;
554         int                     id;
555
556         ifp = &sc->arpcom.ac_if;
557
558         id = CSR_READ_2(sc, WI_RX_FID);
559
560         /*
561          * if we have the procframe flag set, disregard all this and just
562          * read the data from the device.
563          */
564         if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
565                 struct wi_frame         *rx_frame;
566                 int                     datlen, hdrlen;
567
568                 /* first allocate mbuf for packet storage */
569                 MGETHDR(m, MB_DONTWAIT, MT_DATA);
570                 if (m == NULL) {
571                         ifp->if_ierrors++;
572                         return;
573                 }
574                 MCLGET(m, MB_DONTWAIT);
575                 if (!(m->m_flags & M_EXT)) {
576                         m_freem(m);
577                         ifp->if_ierrors++;
578                         return;
579                 }
580
581                 m->m_pkthdr.rcvif = ifp;
582
583                 /* now read wi_frame first so we know how much data to read */
584                 if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
585                     sizeof(struct wi_frame))) {
586                         m_freem(m);
587                         ifp->if_ierrors++;
588                         return;
589                 }
590
591                 rx_frame = mtod(m, struct wi_frame *);
592
593                 switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {
594                 case 7:
595                         switch (rx_frame->wi_frame_ctl & WI_FCTL_FTYPE) {
596                         case WI_FTYPE_DATA:
597                                 hdrlen = WI_DATA_HDRLEN;
598                                 datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
599                                 break;
600                         case WI_FTYPE_MGMT:
601                                 hdrlen = WI_MGMT_HDRLEN;
602                                 datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
603                                 break;
604                         case WI_FTYPE_CTL:
605                                 /*
606                                  * prism2 cards don't pass control packets
607                                  * down properly or consistently, so we'll only
608                                  * pass down the header.
609                                  */
610                                 hdrlen = WI_CTL_HDRLEN;
611                                 datlen = 0;
612                                 break;
613                         default:
614                                 device_printf(sc->dev, "received packet of "
615                                     "unknown type on port 7\n");
616                                 m_freem(m);
617                                 ifp->if_ierrors++;
618                                 return;
619                         }
620                         break;
621                 case 0:
622                         hdrlen = WI_DATA_HDRLEN;
623                         datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
624                         break;
625                 default:
626                         device_printf(sc->dev, "received packet on invalid "
627                             "port (wi_status=0x%x)\n", rx_frame->wi_status);
628                         m_freem(m);
629                         ifp->if_ierrors++;
630                         return;
631                 }
632
633                 if ((hdrlen + datlen + 2) > MCLBYTES) {
634                         device_printf(sc->dev, "oversized packet received "
635                             "(wi_dat_len=%d, wi_status=0x%x)\n",
636                             datlen, rx_frame->wi_status);
637                         m_freem(m);
638                         ifp->if_ierrors++;
639                         return;
640                 }
641
642                 if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
643                     datlen + 2)) {
644                         m_freem(m);
645                         ifp->if_ierrors++;
646                         return;
647                 }
648
649                 m->m_pkthdr.len = m->m_len = hdrlen + datlen;
650
651                 ifp->if_ipackets++;
652
653                 /* Handle BPF listeners. */
654                 BPF_MTAP(ifp, m);
655
656                 m_freem(m);
657         } else {
658                 struct wi_frame         rx_frame;
659
660                 /* First read in the frame header */
661                 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
662                     sizeof(rx_frame))) {
663                         ifp->if_ierrors++;
664                         return;
665                 }
666
667                 if (rx_frame.wi_status & WI_STAT_ERRSTAT) {
668                         ifp->if_ierrors++;
669                         return;
670                 }
671
672                 MGETHDR(m, MB_DONTWAIT, MT_DATA);
673                 if (m == NULL) {
674                         ifp->if_ierrors++;
675                         return;
676                 }
677                 MCLGET(m, MB_DONTWAIT);
678                 if (!(m->m_flags & M_EXT)) {
679                         m_freem(m);
680                         ifp->if_ierrors++;
681                         return;
682                 }
683
684                 eh = mtod(m, struct ether_header *);
685                 m->m_pkthdr.rcvif = ifp;
686
687                 if (rx_frame.wi_status == WI_STAT_MGMT &&
688                     sc->wi_ptype == WI_PORTTYPE_AP) {
689                         if ((WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len + 2) >
690                             MCLBYTES) {
691                                 device_printf(sc->dev, "oversized mgmt packet "
692                                     "received in hostap mode " 
693                                     "(wi_dat_len=%d, wi_status=0x%x)\n",
694                                     rx_frame.wi_dat_len, rx_frame.wi_status);
695                                 m_freem(m);
696                                 ifp->if_ierrors++;
697                                 return;
698                         }
699
700                         /* Put the whole header in there. */
701                         bcopy(&rx_frame, mtod(m, void *),
702                             sizeof(struct wi_frame));
703                         if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW, 
704                             mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
705                             rx_frame.wi_dat_len + 2)) {
706                                 m_freem(m);
707                                 ifp->if_ierrors++;
708                                 return;
709                         }
710                         m->m_pkthdr.len = m->m_len =
711                             WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len;
712                         /* XXX: consider giving packet to bhp? */
713                         owihap_mgmt_input(sc, &rx_frame, m);
714                         return;
715                 }
716
717                 if (rx_frame.wi_status == WI_STAT_1042 ||
718                     rx_frame.wi_status == WI_STAT_TUNNEL ||
719                     rx_frame.wi_status == WI_STAT_WMP_MSG) {
720                         if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
721                                 device_printf(sc->dev,
722                                     "oversized packet received "
723                                     "(wi_dat_len=%d, wi_status=0x%x)\n",
724                                     rx_frame.wi_dat_len, rx_frame.wi_status);
725                                 m_freem(m);
726                                 ifp->if_ierrors++;
727                                 return;
728                         }
729                         m->m_pkthdr.len = m->m_len =
730                             rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
731
732 #if 0
733                         bcopy((char *)&rx_frame.wi_addr1,
734                             (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
735                         if (sc->wi_ptype == WI_PORTTYPE_ADHOC) {
736                                 bcopy((char *)&rx_frame.wi_addr2,
737                                     (char *)&eh->ether_shost, ETHER_ADDR_LEN);
738                         } else {
739                                 bcopy((char *)&rx_frame.wi_addr3,
740                                     (char *)&eh->ether_shost, ETHER_ADDR_LEN);
741                         }
742 #else
743                         bcopy((char *)&rx_frame.wi_dst_addr,
744                                 (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
745                         bcopy((char *)&rx_frame.wi_src_addr,
746                                 (char *)&eh->ether_shost, ETHER_ADDR_LEN);
747 #endif
748
749                         bcopy((char *)&rx_frame.wi_type,
750                             (char *)&eh->ether_type, ETHER_TYPE_LEN);
751
752                         if (wi_read_data(sc, id, WI_802_11_OFFSET,
753                             mtod(m, caddr_t) + sizeof(struct ether_header),
754                             m->m_len + 2)) {
755                                 m_freem(m);
756                                 ifp->if_ierrors++;
757                                 return;
758                         }
759                 } else {
760                         if((rx_frame.wi_dat_len +
761                             sizeof(struct ether_header)) > MCLBYTES) {
762                                 device_printf(sc->dev,
763                                     "oversized packet received "
764                                     "(wi_dat_len=%d, wi_status=0x%x)\n",
765                                     rx_frame.wi_dat_len, rx_frame.wi_status);
766                                 m_freem(m);
767                                 ifp->if_ierrors++;
768                                 return;
769                         }
770                         m->m_pkthdr.len = m->m_len =
771                             rx_frame.wi_dat_len + sizeof(struct ether_header);
772
773                         if (wi_read_data(sc, id, WI_802_3_OFFSET,
774                             mtod(m, caddr_t), m->m_len + 2)) {
775                                 m_freem(m);
776                                 ifp->if_ierrors++;
777                                 return;
778                         }
779                 }
780
781                 ifp->if_ipackets++;
782
783                 if (sc->wi_ptype == WI_PORTTYPE_AP) {
784                         /* 
785                          * Give host AP code first crack at data
786                          * packets.  If it decides to handle it (or
787                          * drop it), it will return a non-zero.
788                          * Otherwise, it is destined for this host.
789                          */
790                         if (owihap_data_input(sc, &rx_frame, m))
791                                 return;
792                 }
793                 /* Receive packet. */
794 #ifdef WICACHE
795                 wi_cache_store(sc, m, rx_frame.wi_q_info);
796 #endif  
797                 ifp->if_input(ifp, m);
798         }
799 }
800
801 static void
802 wi_txeof(sc, status)
803         struct wi_softc         *sc;
804         int                     status;
805 {
806         struct ifnet            *ifp;
807
808         ifp = &sc->arpcom.ac_if;
809
810         ifp->if_timer = 0;
811         ifp->if_flags &= ~IFF_OACTIVE;
812
813         if (status & WI_EV_TX_EXC)
814                 ifp->if_oerrors++;
815         else
816                 ifp->if_opackets++;
817
818         return;
819 }
820
821 static void
822 wi_inquire(xsc)
823         void                    *xsc;
824 {
825         struct wi_softc *sc = xsc;
826         struct ifnet            *ifp = &sc->arpcom.ac_if;
827
828         lwkt_serialize_enter(ifp->if_serializer);
829
830         callout_reset(&sc->wi_stat_timer, hz* 60, wi_inquire, sc);
831
832         /* Don't do this while we're transmitting */
833         if ((ifp->if_flags & IFF_OACTIVE) == 0) {
834                 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
835         }
836
837         lwkt_serialize_exit(ifp->if_serializer);
838 }
839
840 static void
841 wi_update_stats(sc)
842         struct wi_softc         *sc;
843 {
844         struct wi_ltv_gen       gen;
845         u_int16_t               id;
846         struct ifnet            *ifp;
847         u_int32_t               *ptr;
848         int                     len, i;
849         u_int16_t               t;
850
851         ifp = &sc->arpcom.ac_if;
852
853         id = CSR_READ_2(sc, WI_INFO_FID);
854
855         wi_read_data(sc, id, 0, (char *)&gen, 4);
856
857         /*
858          * if we just got our scan results, copy it over into the scan buffer
859          * so we can return it to anyone that asks for it. (add a little
860          * compatibility with the prism2 scanning mechanism)
861          */
862         if (gen.wi_type == WI_INFO_SCAN_RESULTS)
863         {
864                 sc->wi_scanbuf_len = gen.wi_len;
865                 wi_read_data(sc, id, 4, (char *)sc->wi_scanbuf,
866                     sc->wi_scanbuf_len * 2);
867
868                 return;
869         }
870         else if (gen.wi_type != WI_INFO_COUNTERS)
871                 return;
872
873         len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
874                 gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
875         ptr = (u_int32_t *)&sc->wi_stats;
876
877         for (i = 0; i < len - 1; i++) {
878                 t = CSR_READ_2(sc, WI_DATA1);
879 #ifdef WI_HERMES_STATS_WAR
880                 if (t > 0xF000)
881                         t = ~t & 0xFFFF;
882 #endif
883                 ptr[i] += t;
884         }
885
886         ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
887             sc->wi_stats.wi_tx_multi_retries +
888             sc->wi_stats.wi_tx_retry_limit;
889
890         return;
891 }
892
893 static void
894 wi_intr(xsc)
895         void            *xsc;
896 {
897         struct wi_softc         *sc = xsc;
898         struct ifnet            *ifp = &sc->arpcom.ac_if;
899         u_int16_t               status;
900
901         if (sc->wi_gone || !(ifp->if_flags & IFF_UP)) {
902                 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
903                 CSR_WRITE_2(sc, WI_INT_EN, 0);
904                 return;
905         }
906
907         /* Disable interrupts. */
908         CSR_WRITE_2(sc, WI_INT_EN, 0);
909
910         status = CSR_READ_2(sc, WI_EVENT_STAT);
911         CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
912
913         if (status & WI_EV_RX) {
914                 wi_rxeof(sc);
915                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
916         }
917
918         if (status & WI_EV_TX) {
919                 wi_txeof(sc, status);
920                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
921         }
922
923         if (status & WI_EV_ALLOC) {
924                 int                     id;
925
926                 id = CSR_READ_2(sc, WI_ALLOC_FID);
927                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
928                 if (id == sc->wi_tx_data_id)
929                         wi_txeof(sc, status);
930         }
931
932         if (status & WI_EV_INFO) {
933                 wi_update_stats(sc);
934                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
935         }
936
937         if (status & WI_EV_TX_EXC) {
938                 wi_txeof(sc, status);
939                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
940         }
941
942         if (status & WI_EV_INFO_DROP) {
943                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
944         }
945
946         /* Re-enable interrupts. */
947         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
948
949         if (!ifq_is_empty(&ifp->if_snd)) {
950                 wi_start(ifp);
951         }
952 }
953
954 static int
955 wi_cmd(sc, cmd, val0, val1, val2)
956         struct wi_softc         *sc;
957         int                     cmd;
958         int                     val0;
959         int                     val1;
960         int                     val2;
961 {
962         int                     i, s = 0;
963         static volatile int count  = 0;
964         
965         if (count > 1)
966                 panic("Hey partner, hold on there!");
967         count++;
968
969         /* wait for the busy bit to clear */
970         for (i = 500; i > 0; i--) {     /* 5s */
971                 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
972                         break;
973                 }
974                 DELAY(10*1000); /* 10 m sec */
975         }
976         if (i == 0) {
977                 device_printf(sc->dev, "wi_cmd: busy bit won't clear.\n" );
978                 count--;
979                 return(ETIMEDOUT);
980         }
981
982         CSR_WRITE_2(sc, WI_PARAM0, val0);
983         CSR_WRITE_2(sc, WI_PARAM1, val1);
984         CSR_WRITE_2(sc, WI_PARAM2, val2);
985         CSR_WRITE_2(sc, WI_COMMAND, cmd);
986
987         for (i = 0; i < WI_TIMEOUT; i++) {
988                 /*
989                  * Wait for 'command complete' bit to be
990                  * set in the event status register.
991                  */
992                 s = CSR_READ_2(sc, WI_EVENT_STAT);
993                 if (s & WI_EV_CMD) {
994                         /* Ack the event and read result code. */
995                         s = CSR_READ_2(sc, WI_STATUS);
996                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
997 #ifdef foo
998                         if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))
999                                 return(EIO);
1000 #endif
1001                         if (s & WI_STAT_CMD_RESULT) {
1002                                 count--;
1003                                 return(EIO);
1004                         }
1005                         break;
1006                 }
1007                 DELAY(WI_DELAY);
1008         }
1009
1010         count--;
1011         if (i == WI_TIMEOUT) {
1012                 device_printf(sc->dev,
1013                     "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
1014                 return(ETIMEDOUT);
1015         }
1016         return(0);
1017 }
1018
1019 static void
1020 wi_reset(sc)
1021         struct wi_softc         *sc;
1022 {
1023 #define WI_INIT_TRIES 3
1024         int i;
1025         int tries;
1026         
1027         /* Symbol firmware cannot be initialized more than once */
1028         if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_enabled)
1029                 return;
1030         if (sc->sc_firmware_type == WI_SYMBOL)
1031                 tries = 1;
1032         else
1033                 tries = WI_INIT_TRIES;
1034
1035         for (i = 0; i < tries; i++) {
1036                 if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0) == 0)
1037                         break;
1038                 DELAY(WI_DELAY * 1000);
1039         }
1040         sc->sc_enabled = 1;
1041
1042         if (i == tries) {
1043                 device_printf(sc->dev, "init failed\n");
1044                 return;
1045         }
1046
1047         CSR_WRITE_2(sc, WI_INT_EN, 0);
1048         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
1049
1050         /* Calibrate timer. */
1051         WI_SETVAL(WI_RID_TICK_TIME, 8);
1052
1053         return;
1054 }
1055
1056 /*
1057  * Read an LTV record from the NIC.
1058  */
1059 static int
1060 wi_read_record(sc, ltv)
1061         struct wi_softc         *sc;
1062         struct wi_ltv_gen       *ltv;
1063 {
1064         u_int16_t               *ptr;
1065         int                     i, len, code;
1066         struct wi_ltv_gen       *oltv, p2ltv;
1067
1068         oltv = ltv;
1069         if (sc->sc_firmware_type != WI_LUCENT) {
1070                 switch (ltv->wi_type) {
1071                 case WI_RID_ENCRYPTION:
1072                         p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1073                         p2ltv.wi_len = 2;
1074                         ltv = &p2ltv;
1075                         break;
1076                 case WI_RID_TX_CRYPT_KEY:
1077                         p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1078                         p2ltv.wi_len = 2;
1079                         ltv = &p2ltv;
1080                         break;
1081                 case WI_RID_ROAMING_MODE:
1082                         if (sc->sc_firmware_type == WI_INTERSIL)
1083                                 break;
1084                         /* not supported */
1085                         ltv->wi_len = 1;
1086                         return 0;
1087                 case WI_RID_MICROWAVE_OVEN:
1088                         /* not supported */
1089                         ltv->wi_len = 1;
1090                         return 0;
1091                 }
1092         }
1093
1094         /* Tell the NIC to enter record read mode. */
1095         if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
1096                 return(EIO);
1097
1098         /* Seek to the record. */
1099         if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1100                 return(EIO);
1101
1102         /*
1103          * Read the length and record type and make sure they
1104          * match what we expect (this verifies that we have enough
1105          * room to hold all of the returned data).
1106          */
1107         len = CSR_READ_2(sc, WI_DATA1);
1108         if (len > ltv->wi_len)
1109                 return(ENOSPC);
1110         code = CSR_READ_2(sc, WI_DATA1);
1111         if (code != ltv->wi_type)
1112                 return(EIO);
1113
1114         ltv->wi_len = len;
1115         ltv->wi_type = code;
1116
1117         /* Now read the data. */
1118         ptr = &ltv->wi_val;
1119         for (i = 0; i < ltv->wi_len - 1; i++)
1120                 ptr[i] = CSR_READ_2(sc, WI_DATA1);
1121
1122         if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS
1123             && ltv->wi_val == sc->wi_ibss_port) {
1124                 /*
1125                  * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
1126                  * Since Lucent uses port type 1 for BSS *and* IBSS we
1127                  * have to rely on wi_ptype to distinguish this for us.
1128                  */
1129                 ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
1130         } else if (sc->sc_firmware_type != WI_LUCENT) {
1131                 switch (oltv->wi_type) {
1132                 case WI_RID_TX_RATE:
1133                 case WI_RID_CUR_TX_RATE:
1134                         switch (ltv->wi_val) {
1135                         case 1: oltv->wi_val = 1; break;
1136                         case 2: oltv->wi_val = 2; break;
1137                         case 3: oltv->wi_val = 6; break;
1138                         case 4: oltv->wi_val = 5; break;
1139                         case 7: oltv->wi_val = 7; break;
1140                         case 8: oltv->wi_val = 11; break;
1141                         case 15: oltv->wi_val = 3; break;
1142                         default: oltv->wi_val = 0x100 + ltv->wi_val; break;
1143                         }
1144                         break;
1145                 case WI_RID_ENCRYPTION:
1146                         oltv->wi_len = 2;
1147                         if (ltv->wi_val & 0x01)
1148                                 oltv->wi_val = 1;
1149                         else
1150                                 oltv->wi_val = 0;
1151                         break;
1152                 case WI_RID_TX_CRYPT_KEY:
1153                         oltv->wi_len = 2;
1154                         oltv->wi_val = ltv->wi_val;
1155                         break;
1156                 case WI_RID_CNFAUTHMODE:
1157                         oltv->wi_len = 2;
1158                         if (le16toh(ltv->wi_val) & 0x01)
1159                                 oltv->wi_val = htole16(1);
1160                         else if (le16toh(ltv->wi_val) & 0x02)
1161                                 oltv->wi_val = htole16(2);
1162                         break;
1163                 }
1164         }
1165
1166         return(0);
1167 }
1168
1169 /*
1170  * Same as read, except we inject data instead of reading it.
1171  */
1172 static int
1173 wi_write_record(sc, ltv)
1174         struct wi_softc         *sc;
1175         struct wi_ltv_gen       *ltv;
1176 {
1177         u_int16_t               *ptr;
1178         int                     i;
1179         struct wi_ltv_gen       p2ltv;
1180
1181         if (ltv->wi_type == WI_RID_PORTTYPE &&
1182             le16toh(ltv->wi_val) == WI_PORTTYPE_IBSS) {
1183                 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
1184                 p2ltv.wi_type = WI_RID_PORTTYPE;
1185                 p2ltv.wi_len = 2;
1186                 p2ltv.wi_val = sc->wi_ibss_port;
1187                 ltv = &p2ltv;
1188         } else if (sc->sc_firmware_type != WI_LUCENT) {
1189                 switch (ltv->wi_type) {
1190                 case WI_RID_TX_RATE:
1191                         p2ltv.wi_type = WI_RID_TX_RATE;
1192                         p2ltv.wi_len = 2;
1193                         switch (ltv->wi_val) {
1194                         case 1: p2ltv.wi_val = 1; break;
1195                         case 2: p2ltv.wi_val = 2; break;
1196                         case 3: p2ltv.wi_val = 15; break;
1197                         case 5: p2ltv.wi_val = 4; break;
1198                         case 6: p2ltv.wi_val = 3; break;
1199                         case 7: p2ltv.wi_val = 7; break;
1200                         case 11: p2ltv.wi_val = 8; break;
1201                         default: return EINVAL;
1202                         }
1203                         ltv = &p2ltv;
1204                         break;
1205                 case WI_RID_ENCRYPTION:
1206                         p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1207                         p2ltv.wi_len = 2;
1208                         if (le16toh(ltv->wi_val)) {
1209                                 p2ltv.wi_val =htole16(PRIVACY_INVOKED |
1210                                     EXCLUDE_UNENCRYPTED);
1211                                 if (sc->wi_ptype == WI_PORTTYPE_AP)
1212                                         /* 
1213                                          * Disable tx encryption...
1214                                          * it's broken.
1215                                          */
1216                                         p2ltv.wi_val |= htole16(HOST_ENCRYPT);
1217                         } else
1218                                 p2ltv.wi_val =
1219                                     htole16(HOST_ENCRYPT | HOST_DECRYPT);
1220                         ltv = &p2ltv;
1221                         break;
1222                 case WI_RID_TX_CRYPT_KEY:
1223                         p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1224                         p2ltv.wi_len = 2;
1225                         p2ltv.wi_val = ltv->wi_val;
1226                         ltv = &p2ltv;
1227                         break;
1228                 case WI_RID_DEFLT_CRYPT_KEYS:
1229                     {
1230                         int error;
1231                         int keylen;
1232                         struct wi_ltv_str       ws;
1233                         struct wi_ltv_keys      *wk =
1234                             (struct wi_ltv_keys *)ltv;
1235
1236                         keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1237
1238                         for (i = 0; i < 4; i++) {
1239                                 bzero(&ws, sizeof(ws));
1240                                 ws.wi_len = (keylen > 5) ? 8 : 4;
1241                                 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1242                                 memcpy(ws.wi_str,
1243                                     &wk->wi_keys[i].wi_keydat, keylen);
1244                                 error = wi_write_record(sc,
1245                                     (struct wi_ltv_gen *)&ws);
1246                                 if (error)
1247                                         return error;
1248                         }
1249                         return 0;
1250                     }
1251                 case WI_RID_CNFAUTHMODE:
1252                         p2ltv.wi_type = WI_RID_CNFAUTHMODE;
1253                         p2ltv.wi_len = 2;
1254                         if (le16toh(ltv->wi_val) == 1)
1255                                 p2ltv.wi_val = htole16(0x01);
1256                         else if (le16toh(ltv->wi_val) == 2)
1257                                 p2ltv.wi_val = htole16(0x02);
1258                         ltv = &p2ltv;
1259                         break;
1260                 case WI_RID_ROAMING_MODE:
1261                         if (sc->sc_firmware_type == WI_INTERSIL)
1262                                 break;
1263                         /* not supported */
1264                         return 0;
1265                 case WI_RID_MICROWAVE_OVEN:
1266                         /* not supported */
1267                         return 0;
1268                 }
1269         } else {
1270                 /* LUCENT */
1271                 switch (ltv->wi_type) {  
1272                 case WI_RID_TX_RATE:
1273                         switch (ltv->wi_val) {
1274                         case 1: ltv->wi_val = 1; break;  /* 1Mb/s fixed */
1275                         case 2: ltv->wi_val = 2; break;  /* 2Mb/s fixed */
1276                         case 3: ltv->wi_val = 3; break;  /* 11Mb/s auto */
1277                         case 5: ltv->wi_val = 4; break;  /* 5.5Mb/s fixed */
1278                         case 6: ltv->wi_val = 6; break;  /* 2Mb/s auto */
1279                         case 7: ltv->wi_val = 7; break;  /* 5.5Mb/s auto */
1280                         case 11: ltv->wi_val = 5; break; /* 11Mb/s fixed */
1281                         default: return EINVAL;
1282                         }
1283                 }
1284         }
1285
1286         if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1287                 return(EIO);
1288
1289         CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1290         CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1291
1292         ptr = &ltv->wi_val;
1293         for (i = 0; i < ltv->wi_len - 1; i++)
1294                 CSR_WRITE_2(sc, WI_DATA1, ptr[i]);
1295
1296         if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
1297                 return(EIO);
1298
1299         return(0);
1300 }
1301
1302 static int
1303 wi_seek(sc, id, off, chan)
1304         struct wi_softc         *sc;
1305         int                     id, off, chan;
1306 {
1307         int                     i;
1308         int                     selreg, offreg;
1309         int                     status;
1310
1311         switch (chan) {
1312         case WI_BAP0:
1313                 selreg = WI_SEL0;
1314                 offreg = WI_OFF0;
1315                 break;
1316         case WI_BAP1:
1317                 selreg = WI_SEL1;
1318                 offreg = WI_OFF1;
1319                 break;
1320         default:
1321                 device_printf(sc->dev, "invalid data path: %x\n", chan);
1322                 return(EIO);
1323         }
1324
1325         CSR_WRITE_2(sc, selreg, id);
1326         CSR_WRITE_2(sc, offreg, off);
1327
1328         for (i = 0; i < WI_TIMEOUT; i++) {
1329                 status = CSR_READ_2(sc, offreg);
1330                 if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
1331                         break;
1332                 DELAY(WI_DELAY);
1333         }
1334
1335         if (i == WI_TIMEOUT) {
1336                 device_printf(sc->dev, "timeout in wi_seek to %x/%x; last status %x\n",
1337                         id, off, status);
1338                 return(ETIMEDOUT);
1339         }
1340
1341         return(0);
1342 }
1343
1344 static int
1345 wi_read_data(sc, id, off, buf, len)
1346         struct wi_softc         *sc;
1347         int                     id, off;
1348         caddr_t                 buf;
1349         int                     len;
1350 {
1351         int                     i;
1352         u_int16_t               *ptr;
1353
1354         if (wi_seek(sc, id, off, WI_BAP1))
1355                 return(EIO);
1356
1357         ptr = (u_int16_t *)buf;
1358         for (i = 0; i < len / 2; i++)
1359                 ptr[i] = CSR_READ_2(sc, WI_DATA1);
1360
1361         return(0);
1362 }
1363
1364 /*
1365  * According to the comments in the HCF Light code, there is a bug in
1366  * the Hermes (or possibly in certain Hermes firmware revisions) where
1367  * the chip's internal autoincrement counter gets thrown off during
1368  * data writes: the autoincrement is missed, causing one data word to
1369  * be overwritten and subsequent words to be written to the wrong memory
1370  * locations. The end result is that we could end up transmitting bogus
1371  * frames without realizing it. The workaround for this is to write a
1372  * couple of extra guard words after the end of the transfer, then
1373  * attempt to read then back. If we fail to locate the guard words where
1374  * we expect them, we preform the transfer over again.
1375  */
1376 static int
1377 wi_write_data(sc, id, off, buf, len)
1378         struct wi_softc         *sc;
1379         int                     id, off;
1380         caddr_t                 buf;
1381         int                     len;
1382 {
1383         int                     i;
1384         u_int16_t               *ptr;
1385 #ifdef WI_HERMES_AUTOINC_WAR
1386         int                     retries;
1387
1388         retries = 512;
1389 again:
1390 #endif
1391
1392         if (wi_seek(sc, id, off, WI_BAP0))
1393                 return(EIO);
1394
1395         ptr = (u_int16_t *)buf;
1396         for (i = 0; i < (len / 2); i++)
1397                 CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
1398
1399 #ifdef WI_HERMES_AUTOINC_WAR
1400         CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1401         CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1402
1403         if (wi_seek(sc, id, off + len, WI_BAP0))
1404                 return(EIO);
1405
1406         if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1407             CSR_READ_2(sc, WI_DATA0) != 0x5678) {
1408                 if (--retries >= 0)
1409                         goto again;
1410                 device_printf(sc->dev, "wi_write_data device timeout\n");
1411                 return (EIO);
1412         }
1413 #endif
1414
1415         return(0);
1416 }
1417
1418 /*
1419  * Allocate a region of memory inside the NIC and zero
1420  * it out.
1421  */
1422 static int
1423 wi_alloc_nicmem(sc, len, id)
1424         struct wi_softc         *sc;
1425         int                     len;
1426         int                     *id;
1427 {
1428         int                     i;
1429
1430         if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
1431                 device_printf(sc->dev,
1432                     "failed to allocate %d bytes on NIC\n", len);
1433                 return(ENOMEM);
1434         }
1435
1436         for (i = 0; i < WI_TIMEOUT; i++) {
1437                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1438                         break;
1439                 DELAY(WI_DELAY);
1440         }
1441
1442         if (i == WI_TIMEOUT) {
1443                 device_printf(sc->dev, "time out allocating memory on card\n");
1444                 return(ETIMEDOUT);
1445         }
1446
1447         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1448         *id = CSR_READ_2(sc, WI_ALLOC_FID);
1449
1450         if (wi_seek(sc, *id, 0, WI_BAP0)) {
1451                 device_printf(sc->dev, "seek failed while allocating memory on card\n");
1452                 return(EIO);
1453         }
1454
1455         for (i = 0; i < len / 2; i++)
1456                 CSR_WRITE_2(sc, WI_DATA0, 0);
1457
1458         return(0);
1459 }
1460
1461 static void
1462 wi_setmulti(sc)
1463         struct wi_softc         *sc;
1464 {
1465         struct ifnet            *ifp;
1466         int                     i = 0;
1467         struct ifmultiaddr      *ifma;
1468         struct wi_ltv_mcast     mcast;
1469
1470         ifp = &sc->arpcom.ac_if;
1471
1472         bzero((char *)&mcast, sizeof(mcast));
1473
1474         mcast.wi_type = WI_RID_MCAST_LIST;
1475         mcast.wi_len = (3 * 16) + 1;
1476
1477         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1478                 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1479                 return;
1480         }
1481
1482 #if defined(__DragonFly__) || __FreeBSD_version < 500000
1483         LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1484 #else
1485         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1486 #endif
1487                 if (ifma->ifma_addr->sa_family != AF_LINK)
1488                         continue;
1489                 if (i < 16) {
1490                         bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
1491                             (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
1492                         i++;
1493                 } else {
1494                         bzero((char *)&mcast, sizeof(mcast));
1495                         break;
1496                 }
1497         }
1498
1499         mcast.wi_len = (i * 3) + 1;
1500         wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1501
1502         return;
1503 }
1504
1505 static void
1506 wi_setdef(sc, wreq)
1507         struct wi_softc         *sc;
1508         struct wi_req           *wreq;
1509 {
1510         struct ifnet            *ifp;
1511
1512         ifp = &sc->arpcom.ac_if;
1513
1514         switch(wreq->wi_type) {
1515         case WI_RID_MAC_NODE:
1516                 bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr,
1517                    ETHER_ADDR_LEN);
1518                 bcopy((char *)&wreq->wi_val, IF_LLADDR(ifp), ETHER_ADDR_LEN);
1519                 break;
1520         case WI_RID_PORTTYPE:
1521                 sc->wi_ptype = le16toh(wreq->wi_val[0]);
1522                 break;
1523         case WI_RID_TX_RATE:
1524                 sc->wi_tx_rate = le16toh(wreq->wi_val[0]);
1525                 break;
1526         case WI_RID_MAX_DATALEN:
1527                 sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
1528                 break;
1529         case WI_RID_RTS_THRESH:
1530                 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
1531                 break;
1532         case WI_RID_SYSTEM_SCALE:
1533                 sc->wi_ap_density = le16toh(wreq->wi_val[0]);
1534                 break;
1535         case WI_RID_CREATE_IBSS:
1536                 sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
1537                 break;
1538         case WI_RID_OWN_CHNL:
1539                 sc->wi_channel = le16toh(wreq->wi_val[0]);
1540                 break;
1541         case WI_RID_NODENAME:
1542                 bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
1543                 bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
1544                 break;
1545         case WI_RID_DESIRED_SSID:
1546                 bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
1547                 bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
1548                 break;
1549         case WI_RID_OWN_SSID:
1550                 bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
1551                 bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
1552                 break;
1553         case WI_RID_PM_ENABLED:
1554                 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
1555                 break;
1556         case WI_RID_MICROWAVE_OVEN:
1557                 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
1558                 break;
1559         case WI_RID_MAX_SLEEP:
1560                 sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
1561                 break;
1562         case WI_RID_CNFAUTHMODE:
1563                 sc->wi_authtype = le16toh(wreq->wi_val[0]);
1564                 break;
1565         case WI_RID_ROAMING_MODE:
1566                 sc->wi_roaming = le16toh(wreq->wi_val[0]);
1567                 break;
1568         case WI_RID_ENCRYPTION:
1569                 sc->wi_use_wep = le16toh(wreq->wi_val[0]);
1570                 break;
1571         case WI_RID_TX_CRYPT_KEY:
1572                 sc->wi_tx_key = le16toh(wreq->wi_val[0]);
1573                 break;
1574         case WI_RID_DEFLT_CRYPT_KEYS:
1575                 bcopy((char *)wreq, (char *)&sc->wi_keys,
1576                     sizeof(struct wi_ltv_keys));
1577                 break;
1578         default:
1579                 break;
1580         }
1581
1582         /* Reinitialize WaveLAN. */
1583         wi_init(sc);
1584
1585         return;
1586 }
1587
1588 static int
1589 wi_ioctl(ifp, command, data, cr)
1590         struct ifnet            *ifp;
1591         u_long                  command;
1592         caddr_t                 data;
1593         struct ucred            *cr;
1594 {
1595         int                     error = 0;
1596         int                     len;
1597         u_int8_t                tmpkey[14];
1598         char                    tmpssid[IEEE80211_NWID_LEN];
1599         struct wi_softc         *sc = ifp->if_softc;
1600         struct wi_req           wreq;
1601         struct ifreq            *ifr;
1602         struct ieee80211req     *ireq;
1603         
1604         ifr = (struct ifreq *)data;
1605         ireq = (struct ieee80211req *)data;
1606
1607         if (sc->wi_gone) {
1608                 error = ENODEV;
1609                 goto out;
1610         }
1611
1612         switch(command) {
1613         case SIOCSIFFLAGS:
1614                 /*
1615                  * Can't do promisc and hostap at the same time.  If all that's
1616                  * changing is the promisc flag, try to short-circuit a call to
1617                  * wi_init() by just setting PROMISC in the hardware.
1618                  */
1619                 if (ifp->if_flags & IFF_UP) {
1620                         if (sc->wi_ptype != WI_PORTTYPE_AP &&
1621                             ifp->if_flags & IFF_RUNNING) {
1622                                 if (ifp->if_flags & IFF_PROMISC &&
1623                                     !(sc->wi_if_flags & IFF_PROMISC)) {
1624                                         WI_SETVAL(WI_RID_PROMISC, 1);
1625                                 } else if (!(ifp->if_flags & IFF_PROMISC) &&
1626                                     sc->wi_if_flags & IFF_PROMISC) {
1627                                         WI_SETVAL(WI_RID_PROMISC, 0);
1628                                 } else {
1629                                         wi_init(sc);
1630                                 }
1631                         } else {
1632                                 wi_init(sc);
1633                         }
1634                 } else {
1635                         if (ifp->if_flags & IFF_RUNNING) {
1636                                 wi_stop(sc);
1637                         }
1638                 }
1639                 sc->wi_if_flags = ifp->if_flags;
1640                 error = 0;
1641                 break;
1642         case SIOCSIFMEDIA:
1643         case SIOCGIFMEDIA:
1644                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
1645                 break;
1646         case SIOCADDMULTI:
1647         case SIOCDELMULTI:
1648                 wi_setmulti(sc);
1649                 error = 0;
1650                 break;
1651         case SIOCGWAVELAN:
1652                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1653                 if (error)
1654                         break;
1655                 if (wreq.wi_len > WI_MAX_DATALEN) {
1656                         error = EINVAL;
1657                         break;
1658                 }
1659                 /* Don't show WEP keys to non-root users. */
1660                 if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS &&
1661                     suser_cred(cr, NULL_CRED_OKAY))
1662                         break;
1663                 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1664                         bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1665                             sizeof(sc->wi_stats));
1666                         wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1667                 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
1668                         bcopy((char *)&sc->wi_keys, (char *)&wreq,
1669                             sizeof(struct wi_ltv_keys));
1670                 }
1671 #ifdef WICACHE
1672                 else if (wreq.wi_type == WI_RID_ZERO_CACHE) {
1673                         sc->wi_sigitems = sc->wi_nextitem = 0;
1674                 } else if (wreq.wi_type == WI_RID_READ_CACHE) {
1675                         char *pt = (char *)&wreq.wi_val;
1676                         bcopy((char *)&sc->wi_sigitems,
1677                             (char *)pt, sizeof(int));
1678                         pt += (sizeof (int));
1679                         wreq.wi_len = sizeof(int) / 2;
1680                         bcopy((char *)&sc->wi_sigcache, (char *)pt,
1681                             sizeof(struct wi_sigcache) * sc->wi_sigitems);
1682                         wreq.wi_len += ((sizeof(struct wi_sigcache) *
1683                             sc->wi_sigitems) / 2) + 1;
1684                 }
1685 #endif
1686                 else if (wreq.wi_type == WI_RID_PROCFRAME) {
1687                         wreq.wi_len = 2;
1688                         wreq.wi_val[0] = sc->wi_procframe;
1689                 } else if (wreq.wi_type == WI_RID_PRISM2) {
1690                         wreq.wi_len = 2;
1691                         wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT;
1692                 } else if (wreq.wi_type == WI_RID_SCAN_RES && 
1693                     sc->sc_firmware_type == WI_LUCENT) {
1694                         memcpy((char *)wreq.wi_val, (char *)sc->wi_scanbuf,
1695                             sc->wi_scanbuf_len * 2);
1696                         wreq.wi_len = sc->wi_scanbuf_len;
1697                 } else {
1698                         if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1699                                 error = EINVAL;
1700                                 break;
1701                         }
1702                 }
1703                 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1704                 break;
1705         case SIOCSWAVELAN:
1706                 if ((error = suser_cred(cr, NULL_CRED_OKAY)))
1707                         goto out;
1708                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1709                 if (error)
1710                         break;
1711                 if (wreq.wi_len > WI_MAX_DATALEN) {
1712                         error = EINVAL;
1713                         break;
1714                 }
1715                 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1716                         error = EINVAL;
1717                         break;
1718                 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1719                         error = owi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1720                             wreq.wi_len);
1721                 } else if (wreq.wi_type == WI_RID_PROCFRAME) {
1722                         sc->wi_procframe = wreq.wi_val[0];
1723                 /*
1724                  * if we're getting a scan request from a wavelan card
1725                  * (non-prism2), send out a cmd_inquire to the card to scan
1726                  * results for the scan will be received through the info
1727                  * interrupt handler. otherwise the scan request can be
1728                  * directly handled by a prism2 card's rid interface.
1729                  */
1730                 } else if (wreq.wi_type == WI_RID_SCAN_REQ && 
1731                     sc->sc_firmware_type == WI_LUCENT) {
1732                         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
1733                 } else {
1734                         error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1735                         if (!error)
1736                                 wi_setdef(sc, &wreq);
1737                 }
1738                 break;
1739         case SIOCGPRISM2DEBUG:
1740                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1741                 if (error)
1742                         break;
1743                 if (!(ifp->if_flags & IFF_RUNNING) ||
1744                     sc->sc_firmware_type == WI_LUCENT) {
1745                         error = EIO;
1746                         break;
1747                 }
1748                 error = wi_get_debug(sc, &wreq);
1749                 if (error == 0)
1750                         error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1751                 break;
1752         case SIOCSPRISM2DEBUG:
1753                 if ((error = suser_cred(cr, NULL_CRED_OKAY)))
1754                         goto out;
1755                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1756                 if (error)
1757                         break;
1758                 error = wi_set_debug(sc, &wreq);
1759                 break;
1760         case SIOCG80211:
1761                 switch(ireq->i_type) {
1762                 case IEEE80211_IOC_SSID:
1763                         if(ireq->i_val == -1) {
1764                                 bzero(tmpssid, IEEE80211_NWID_LEN);
1765                                 error = wi_get_cur_ssid(sc, tmpssid, &len);
1766                                 if (error != 0)
1767                                         break;
1768                                 error = copyout(tmpssid, ireq->i_data,
1769                                         IEEE80211_NWID_LEN);
1770                                 ireq->i_len = len;
1771                         } else if (ireq->i_val == 0) {
1772                                 error = copyout(sc->wi_net_name,
1773                                     ireq->i_data,
1774                                     IEEE80211_NWID_LEN);
1775                                 ireq->i_len = IEEE80211_NWID_LEN;
1776                         } else
1777                                 error = EINVAL;
1778                         break;
1779                 case IEEE80211_IOC_NUMSSIDS:
1780                         ireq->i_val = 1;
1781                         break;
1782                 case IEEE80211_IOC_WEP:
1783                         if(!sc->wi_has_wep) {
1784                                 ireq->i_val = IEEE80211_WEP_NOSUP; 
1785                         } else {
1786                                 if(sc->wi_use_wep) {
1787                                         ireq->i_val =
1788                                             IEEE80211_WEP_MIXED;
1789                                 } else {
1790                                         ireq->i_val =
1791                                             IEEE80211_WEP_OFF;
1792                                 }
1793                         }
1794                         break;
1795                 case IEEE80211_IOC_WEPKEY:
1796                         if(!sc->wi_has_wep ||
1797                             ireq->i_val < 0 || ireq->i_val > 3) {
1798                                 error = EINVAL;
1799                                 break;
1800                         }
1801                         len = sc->wi_keys.wi_keys[ireq->i_val].wi_keylen;
1802                         if (suser_cred(cr, NULL_CRED_OKAY))
1803                                 bcopy(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat,
1804                                     tmpkey, len);
1805                         else
1806                                 bzero(tmpkey, len);
1807
1808                         ireq->i_len = len;
1809                         error = copyout(tmpkey, ireq->i_data, len);
1810
1811                         break;
1812                 case IEEE80211_IOC_NUMWEPKEYS:
1813                         if(!sc->wi_has_wep)
1814                                 error = EINVAL;
1815                         else
1816                                 ireq->i_val = 4;
1817                         break;
1818                 case IEEE80211_IOC_WEPTXKEY:
1819                         if(!sc->wi_has_wep)
1820                                 error = EINVAL;
1821                         else
1822                                 ireq->i_val = sc->wi_tx_key;
1823                         break;
1824                 case IEEE80211_IOC_AUTHMODE:
1825                         ireq->i_val = sc->wi_authmode;
1826                         break;
1827                 case IEEE80211_IOC_STATIONNAME:
1828                         error = copyout(sc->wi_node_name,
1829                             ireq->i_data, IEEE80211_NWID_LEN);
1830                         ireq->i_len = IEEE80211_NWID_LEN;
1831                         break;
1832                 case IEEE80211_IOC_CHANNEL:
1833                         wreq.wi_type = WI_RID_CURRENT_CHAN;
1834                         wreq.wi_len = WI_MAX_DATALEN;
1835                         if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
1836                                 error = EINVAL;
1837                         else {
1838                                 ireq->i_val = wreq.wi_val[0];
1839                         }
1840                         break;
1841                 case IEEE80211_IOC_POWERSAVE:
1842                         if(sc->wi_pm_enabled)
1843                                 ireq->i_val = IEEE80211_POWERSAVE_ON;
1844                         else
1845                                 ireq->i_val = IEEE80211_POWERSAVE_OFF;
1846                         break;
1847                 case IEEE80211_IOC_POWERSAVESLEEP:
1848                         ireq->i_val = sc->wi_max_sleep;
1849                         break;
1850                 default:
1851                         error = EINVAL;
1852                 }
1853                 break;
1854         case SIOCS80211:
1855                 if ((error = suser_cred(cr, NULL_CRED_OKAY)))
1856                         goto out;
1857                 switch(ireq->i_type) {
1858                 case IEEE80211_IOC_SSID:
1859                         if (ireq->i_val != 0 ||
1860                             ireq->i_len > IEEE80211_NWID_LEN) {
1861                                 error = EINVAL;
1862                                 break;
1863                         }
1864                         /* We set both of them */
1865                         bzero(sc->wi_net_name, IEEE80211_NWID_LEN);
1866                         error = copyin(ireq->i_data,
1867                             sc->wi_net_name, ireq->i_len);
1868                         bcopy(sc->wi_net_name, sc->wi_ibss_name, IEEE80211_NWID_LEN);
1869                         break;
1870                 case IEEE80211_IOC_WEP:
1871                         /*
1872                          * These cards only support one mode so
1873                          * we just turn wep on what ever is
1874                          * passed in if it's not OFF.
1875                          */
1876                         if (ireq->i_val == IEEE80211_WEP_OFF) {
1877                                 sc->wi_use_wep = 0;
1878                         } else {
1879                                 sc->wi_use_wep = 1;
1880                         }
1881                         break;
1882                 case IEEE80211_IOC_WEPKEY:
1883                         if (ireq->i_val < 0 || ireq->i_val > 3 ||
1884                                 ireq->i_len > 13) {
1885                                 error = EINVAL;
1886                                 break;
1887                         } 
1888                         bzero(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, 13);
1889                         error = copyin(ireq->i_data, 
1890                             sc->wi_keys.wi_keys[ireq->i_val].wi_keydat,
1891                             ireq->i_len);
1892                         if(error)
1893                                 break;
1894                         sc->wi_keys.wi_keys[ireq->i_val].wi_keylen =
1895                                     ireq->i_len;
1896                         break;
1897                 case IEEE80211_IOC_WEPTXKEY:
1898                         if (ireq->i_val < 0 || ireq->i_val > 3) {
1899                                 error = EINVAL;
1900                                 break;
1901                         }
1902                         sc->wi_tx_key = ireq->i_val;
1903                         break;
1904                 case IEEE80211_IOC_AUTHMODE:
1905                         sc->wi_authmode = ireq->i_val;
1906                         break;
1907                 case IEEE80211_IOC_STATIONNAME:
1908                         if (ireq->i_len > 32) {
1909                                 error = EINVAL;
1910                                 break;
1911                         }
1912                         bzero(sc->wi_node_name, 32);
1913                         error = copyin(ireq->i_data,
1914                             sc->wi_node_name, ireq->i_len);
1915                         break;
1916                 case IEEE80211_IOC_CHANNEL:
1917                         /*
1918                          * The actual range is 1-14, but if you
1919                          * set it to 0 you get the default. So
1920                          * we let that work too.
1921                          */
1922                         if (ireq->i_val < 0 || ireq->i_val > 14) {
1923                                 error = EINVAL;
1924                                 break;
1925                         }
1926                         sc->wi_channel = ireq->i_val;
1927                         break;
1928                 case IEEE80211_IOC_POWERSAVE:
1929                         switch (ireq->i_val) {
1930                         case IEEE80211_POWERSAVE_OFF:
1931                                 sc->wi_pm_enabled = 0;
1932                                 break;
1933                         case IEEE80211_POWERSAVE_ON:
1934                                 sc->wi_pm_enabled = 1;
1935                                 break;
1936                         default:
1937                                 error = EINVAL;
1938                                 break;
1939                         }
1940                         break;
1941                 case IEEE80211_IOC_POWERSAVESLEEP:
1942                         if (ireq->i_val < 0) {
1943                                 error = EINVAL;
1944                                 break;
1945                         }
1946                         sc->wi_max_sleep = ireq->i_val;
1947                         break;
1948                 default:
1949                         error = EINVAL;
1950                         break;
1951                 }
1952
1953                 /* Reinitialize WaveLAN. */
1954                 wi_init(sc);
1955
1956         break;
1957         case SIOCHOSTAP_ADD:
1958         case SIOCHOSTAP_DEL:
1959         case SIOCHOSTAP_GET:
1960         case SIOCHOSTAP_GETALL:
1961         case SIOCHOSTAP_GFLAGS:
1962         case SIOCHOSTAP_SFLAGS:
1963                 /* Send all Host AP specific ioctl's to Host AP code. */
1964                 error = owihap_ioctl(sc, command, data);
1965                 break;
1966         default:
1967                 error = ether_ioctl(ifp, command, data);
1968                 break;
1969         }
1970 out:
1971         return(error);
1972 }
1973
1974 static void
1975 wi_init(xsc)
1976         void                    *xsc;
1977 {
1978         struct wi_softc         *sc = xsc;
1979         struct ifnet            *ifp = &sc->arpcom.ac_if;
1980         struct wi_ltv_macaddr   mac;
1981         int                     id = 0;
1982
1983         if (sc->wi_gone)
1984                 return;
1985
1986         if (ifp->if_flags & IFF_RUNNING)
1987                 wi_stop(sc);
1988
1989         wi_reset(sc);
1990
1991         /* Program max data length. */
1992         WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1993
1994         /* Set the port type. */
1995         WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1996
1997         /* Enable/disable IBSS creation. */
1998         WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1999
2000         /* Program the RTS/CTS threshold. */
2001         WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
2002
2003         /* Program the TX rate */
2004         WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
2005
2006         /* Access point density */
2007         WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
2008
2009         /* Power Management Enabled */
2010         WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
2011
2012         /* Power Managment Max Sleep */
2013         WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
2014
2015         /* Roaming type */
2016         WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
2017
2018         /* Specify the IBSS name */
2019         WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
2020
2021         /* Specify the network name */
2022         WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
2023
2024         /* Specify the frequency to use */
2025         WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
2026
2027         /* Program the nodename. */
2028         WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
2029
2030         /* Specify the authentication mode. */
2031         WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authmode);
2032
2033         /* Set our MAC address. */
2034         mac.wi_len = 4;
2035         mac.wi_type = WI_RID_MAC_NODE;
2036         bcopy((char *)&sc->arpcom.ac_enaddr,
2037            (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
2038         wi_write_record(sc, (struct wi_ltv_gen *)&mac);
2039
2040         /*
2041          * Initialize promisc mode.
2042          *      Being in the Host-AP mode causes
2043          *      great deal of pain if promisc mode is set.
2044          *      Therefore we avoid confusing the firmware
2045          *      and always reset promisc mode in Host-AP regime,
2046          *      it shows us all the packets anyway.
2047          */
2048         if (sc->wi_ptype != WI_PORTTYPE_AP && ifp->if_flags & IFF_PROMISC)
2049                 WI_SETVAL(WI_RID_PROMISC, 1);
2050         else
2051                 WI_SETVAL(WI_RID_PROMISC, 0);
2052
2053         /* Configure WEP. */
2054         if (sc->wi_has_wep) {
2055                 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
2056                 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
2057                 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
2058                 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2059                 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
2060                 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
2061                         /*
2062                          * ONLY HWB3163 EVAL-CARD Firmware version
2063                          * less than 0.8 variant2
2064                          *
2065                          * If promiscuous mode disable, Prism2 chip
2066                          * does not work with WEP.
2067                          * It is under investigation for details.
2068                          * (ichiro@netbsd.org)
2069                          *
2070                          * And make sure that we don't need to do it
2071                          * in hostap mode, since it interferes with
2072                          * the above hostap workaround.
2073                          */
2074                         if (sc->wi_ptype != WI_PORTTYPE_AP &&
2075                             sc->sc_firmware_type == WI_INTERSIL &&
2076                             sc->sc_sta_firmware_ver < 802 ) {
2077                                 /* firm ver < 0.8 variant 2 */
2078                                 WI_SETVAL(WI_RID_PROMISC, 1);
2079                         }
2080                         WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
2081                 }
2082         }
2083
2084         /* Set multicast filter. */
2085         wi_setmulti(sc);
2086
2087         /* Enable desired port */
2088         wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
2089
2090         if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2091                 device_printf(sc->dev, "tx buffer allocation failed\n");
2092         sc->wi_tx_data_id = id;
2093
2094         if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2095                 device_printf(sc->dev, "mgmt. buffer allocation failed\n");
2096         sc->wi_tx_mgmt_id = id;
2097
2098         /* enable interrupts */
2099         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
2100
2101         owihap_init(sc);
2102
2103         ifp->if_flags |= IFF_RUNNING;
2104         ifp->if_flags &= ~IFF_OACTIVE;
2105
2106         callout_reset(&sc->wi_stat_timer, hz * 60, wi_inquire, sc);
2107 }
2108
2109 #define RC4STATE 256
2110 #define RC4KEYLEN 16
2111 #define RC4SWAP(x,y) \
2112     do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0)
2113
2114 static void
2115 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2116 {
2117         u_int32_t i, crc, klen;
2118         u_int8_t state[RC4STATE], key[RC4KEYLEN];
2119         u_int8_t x, y, *dat;
2120
2121         if (!sc->wi_icv_flag) {
2122                 sc->wi_icv = arc4random();
2123                 sc->wi_icv_flag++;
2124         } else
2125                 sc->wi_icv++;
2126         /*
2127          * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2128          * (B, 255, N) with 3 <= B < 8
2129          */
2130         if (sc->wi_icv >= 0x03ff00 &&
2131             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2132                 sc->wi_icv += 0x000100;
2133
2134         /* prepend 24bit IV to tx key, byte order does not matter */
2135         key[0] = sc->wi_icv >> 16;
2136         key[1] = sc->wi_icv >> 8;
2137         key[2] = sc->wi_icv;
2138
2139         klen = sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen +
2140             IEEE80211_WEP_IVLEN;
2141         klen = (klen >= RC4KEYLEN) ? RC4KEYLEN : RC4KEYLEN/2;
2142         bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2143             (char *)key + IEEE80211_WEP_IVLEN, klen - IEEE80211_WEP_IVLEN);
2144
2145         /* rc4 keysetup */
2146         x = y = 0;
2147         for (i = 0; i < RC4STATE; i++)
2148                 state[i] = i;
2149         for (i = 0; i < RC4STATE; i++) {
2150                 y = (key[x] + state[i] + y) % RC4STATE;
2151                 RC4SWAP(i, y);
2152                 x = (x + 1) % klen;
2153         }
2154
2155         /* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
2156         dat = buf;
2157         dat[0] = key[0];
2158         dat[1] = key[1];
2159         dat[2] = key[2];
2160         dat[3] = sc->wi_tx_key << 6;            /* pad and keyid */
2161         dat += 4;
2162
2163         /* compute rc4 over data, crc32 over data */
2164         crc = ~0;
2165         x = y = 0;
2166         for (i = 0; i < len; i++) {
2167                 x = (x + 1) % RC4STATE;
2168                 y = (state[x] + y) % RC4STATE;
2169                 RC4SWAP(x, y);
2170                 crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2171                 dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
2172         }
2173         crc = ~crc;
2174         dat += len;
2175
2176         /* append little-endian crc32 and encrypt */
2177         dat[0] = crc;
2178         dat[1] = crc >> 8;
2179         dat[2] = crc >> 16;
2180         dat[3] = crc >> 24;
2181         for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) {
2182                 x = (x + 1) % RC4STATE;
2183                 y = (state[x] + y) % RC4STATE;
2184                 RC4SWAP(x, y);
2185                 dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
2186         }
2187 }
2188
2189 static void
2190 wi_start(ifp)
2191         struct ifnet            *ifp;
2192 {
2193         struct wi_softc         *sc = ifp->if_softc;
2194         struct mbuf             *m0;
2195         struct wi_frame         tx_frame;
2196         struct ether_header     *eh;
2197         int                     id;
2198
2199         if (sc->wi_gone)
2200                 return;
2201
2202         if (ifp->if_flags & IFF_OACTIVE)
2203                 return;
2204
2205 nextpkt:
2206         m0 = ifq_dequeue(&ifp->if_snd, NULL);
2207         if (m0 == NULL)
2208                 return;
2209
2210         bzero((char *)&tx_frame, sizeof(tx_frame));
2211         tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
2212         id = sc->wi_tx_data_id;
2213         eh = mtod(m0, struct ether_header *);
2214
2215         if (sc->wi_ptype == WI_PORTTYPE_AP) {
2216                 if (!owihap_check_tx(&sc->wi_hostap_info,
2217                     eh->ether_dhost, &tx_frame.wi_tx_rate)) {
2218                         if (ifp->if_flags & IFF_DEBUG)
2219                                 printf("wi_start: dropping unassoc "
2220                                        "dst %6D\n", eh->ether_dhost, ":");
2221                         m_freem(m0);
2222                         goto nextpkt;
2223                 }
2224         }
2225         /*
2226          * Use RFC1042 encoding for IP and ARP datagrams,
2227          * 802.3 for anything else.
2228          */
2229         if (ntohs(eh->ether_type) > ETHER_MAX_LEN) {
2230                 bcopy((char *)&eh->ether_dhost,
2231                     (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
2232                 if (sc->wi_ptype == WI_PORTTYPE_AP) {
2233                         tx_frame.wi_tx_ctl = WI_ENC_TX_MGMT; /* XXX */
2234                         tx_frame.wi_frame_ctl |= WI_FCTL_FROMDS;
2235                         if (sc->wi_use_wep)
2236                                 tx_frame.wi_frame_ctl |= WI_FCTL_WEP;
2237                         bcopy((char *)&sc->arpcom.ac_enaddr,
2238                               (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2239                         bcopy((char *)&eh->ether_shost,
2240                               (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
2241                 }
2242                 else
2243                         bcopy((char *)&eh->ether_shost,
2244                             (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2245                 bcopy((char *)&eh->ether_dhost,
2246                     (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
2247                 bcopy((char *)&eh->ether_shost,
2248                     (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
2249
2250                 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
2251                 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
2252                 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
2253                 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
2254                 tx_frame.wi_type = eh->ether_type;
2255
2256                 if (sc->wi_ptype == WI_PORTTYPE_AP && sc->wi_use_wep) {
2257                         /* Do host encryption. */
2258                         bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8);
2259                         m_copydata(m0, sizeof(struct ether_header),
2260                             m0->m_pkthdr.len - sizeof(struct ether_header),
2261                             (caddr_t)&sc->wi_txbuf[12]);
2262                         wi_do_hostencrypt(sc, &sc->wi_txbuf[0],
2263                             tx_frame.wi_dat_len);
2264                         tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
2265                             IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2266                         wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2267                             sizeof(struct wi_frame));
2268                         wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
2269                             (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len -
2270                             sizeof(struct ether_header)) + 18);
2271                 } else {
2272                         m_copydata(m0, sizeof(struct ether_header),
2273                             m0->m_pkthdr.len - sizeof(struct ether_header),
2274                             (caddr_t)&sc->wi_txbuf);
2275                         wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2276                             sizeof(struct wi_frame));
2277                         wi_write_data(sc, id, WI_802_11_OFFSET,
2278                             (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len -
2279                             sizeof(struct ether_header)) + 2);
2280                 }
2281         } else {
2282                 tx_frame.wi_dat_len = m0->m_pkthdr.len;
2283
2284                 if (sc->wi_ptype == WI_PORTTYPE_AP && sc->wi_use_wep) {
2285                         /* Do host encryption. */
2286                         printf( "XXX: host encrypt not implemented for 802.3\n" );
2287                 } else {
2288                         eh->ether_type = htons(m0->m_pkthdr.len -
2289                             WI_SNAPHDR_LEN);
2290                         m_copydata(m0, 0, m0->m_pkthdr.len,
2291                             (caddr_t)&sc->wi_txbuf);
2292
2293                         wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2294                             sizeof(struct wi_frame));
2295                         wi_write_data(sc, id, WI_802_3_OFFSET,
2296                             (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
2297                 }
2298         }
2299
2300         /*
2301          * If there's a BPF listner, bounce a copy of
2302          * this frame to him. Also, don't send this to the bpf sniffer
2303          * if we're in procframe or monitor sniffing mode.
2304          */
2305         if (!(sc->wi_procframe || sc->wi_debug.wi_monitor))
2306                 BPF_MTAP(ifp, m0);
2307
2308         m_freem(m0);
2309
2310         if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
2311                 device_printf(sc->dev, "xmit failed\n");
2312
2313         ifp->if_flags |= IFF_OACTIVE;
2314
2315         /*
2316          * Set a timeout in case the chip goes out to lunch.
2317          */
2318         ifp->if_timer = 5;
2319 }
2320
2321 int
2322 owi_mgmt_xmit(sc, data, len)
2323         struct wi_softc         *sc;
2324         caddr_t                 data;
2325         int                     len;
2326 {
2327         struct wi_frame         tx_frame;
2328         int                     id;
2329         struct wi_80211_hdr     *hdr;
2330         caddr_t                 dptr;
2331
2332         if (sc->wi_gone)
2333                 return(ENODEV);
2334
2335         hdr = (struct wi_80211_hdr *)data;
2336         dptr = data + sizeof(struct wi_80211_hdr);
2337
2338         bzero((char *)&tx_frame, sizeof(tx_frame));
2339         id = sc->wi_tx_mgmt_id;
2340
2341         bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
2342            sizeof(struct wi_80211_hdr));
2343
2344         tx_frame.wi_tx_ctl = WI_ENC_TX_MGMT;
2345         tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2346         tx_frame.wi_len = htons(tx_frame.wi_dat_len);
2347
2348         wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2349         wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2350             len - sizeof(struct wi_80211_hdr) + 2);
2351
2352         if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
2353                 device_printf(sc->dev, "xmit failed\n");
2354                 return(EIO);
2355         }
2356
2357         return(0);
2358 }
2359
2360 static void
2361 wi_stop(sc)
2362         struct wi_softc         *sc;
2363 {
2364         struct ifnet            *ifp;
2365
2366         if (sc->wi_gone)
2367                 return;
2368
2369         owihap_shutdown(sc);
2370
2371         ifp = &sc->arpcom.ac_if;
2372
2373         /*
2374          * If the card is gone and the memory port isn't mapped, we will
2375          * (hopefully) get 0xffff back from the status read, which is not
2376          * a valid status value.
2377          */
2378         if (CSR_READ_2(sc, WI_STATUS) != 0xffff) {
2379                 CSR_WRITE_2(sc, WI_INT_EN, 0);
2380                 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
2381         }
2382
2383         callout_stop(&sc->wi_stat_timer);
2384
2385         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
2386 }
2387
2388 static void
2389 wi_watchdog(ifp)
2390         struct ifnet            *ifp;
2391 {
2392         struct wi_softc         *sc;
2393
2394         sc = ifp->if_softc;
2395
2396         device_printf(sc->dev, "watchdog timeout\n");
2397
2398         wi_init(sc);
2399
2400         ifp->if_oerrors++;
2401
2402         return;
2403 }
2404
2405 int
2406 owi_alloc(dev, rid)
2407         device_t                dev;
2408         int                     rid;
2409 {
2410         struct wi_softc         *sc = device_get_softc(dev);
2411
2412         if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
2413                 sc->iobase_rid = rid;
2414                 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
2415                     &sc->iobase_rid, 0, ~0, (1 << 6),
2416                     rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
2417                 if (!sc->iobase) {
2418                         device_printf(dev, "No I/O space?!\n");
2419                         return (ENXIO);
2420                 }
2421
2422                 sc->wi_io_addr = rman_get_start(sc->iobase);
2423                 sc->wi_btag = rman_get_bustag(sc->iobase);
2424                 sc->wi_bhandle = rman_get_bushandle(sc->iobase);
2425         } else {
2426                 sc->mem_rid = rid;
2427                 sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
2428                     &sc->mem_rid, RF_ACTIVE);
2429
2430                 if (!sc->mem) {
2431                         device_printf(dev, "No Mem space on prism2.5?\n");
2432                         return (ENXIO);
2433                 }
2434
2435                 sc->wi_btag = rman_get_bustag(sc->mem);
2436                 sc->wi_bhandle = rman_get_bushandle(sc->mem);
2437         }
2438
2439
2440         sc->irq_rid = 0;
2441         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
2442             RF_ACTIVE |
2443             ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
2444
2445         if (!sc->irq) {
2446                 owi_free(dev);
2447                 device_printf(dev, "No irq?!\n");
2448                 return (ENXIO);
2449         }
2450
2451         sc->dev = dev;
2452         sc->wi_unit = device_get_unit(dev);
2453
2454         return (0);
2455 }
2456
2457 void
2458 owi_free(dev)
2459         device_t                dev;
2460 {
2461         struct wi_softc         *sc = device_get_softc(dev);
2462
2463         if (sc->iobase != NULL) {
2464                 bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
2465                 sc->iobase = NULL;
2466         }
2467         if (sc->irq != NULL) {
2468                 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
2469                 sc->irq = NULL;
2470         }
2471         if (sc->mem != NULL) {
2472                 bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
2473                 sc->mem = NULL;
2474         }
2475
2476         return;
2477 }
2478
2479 void
2480 owi_shutdown(dev)
2481         device_t                dev;
2482 {
2483         struct wi_softc *sc;
2484         struct ifnet *ifp;
2485
2486         sc = device_get_softc(dev);
2487         ifp = &sc->arpcom.ac_if;
2488         lwkt_serialize_enter(ifp->if_serializer);
2489         wi_stop(sc);
2490         lwkt_serialize_exit(ifp->if_serializer);
2491 }
2492
2493 #ifdef WICACHE
2494 /* wavelan signal strength cache code.
2495  * store signal/noise/quality on per MAC src basis in
2496  * a small fixed cache.  The cache wraps if > MAX slots
2497  * used.  The cache may be zeroed out to start over.
2498  * Two simple filters exist to reduce computation:
2499  * 1. ip only (literally 0x800) which may be used
2500  * to ignore some packets.  It defaults to ip only.
2501  * it could be used to focus on broadcast, non-IP 802.11 beacons.
2502  * 2. multicast/broadcast only.  This may be used to
2503  * ignore unicast packets and only cache signal strength
2504  * for multicast/broadcast packets (beacons); e.g., Mobile-IP
2505  * beacons and not unicast traffic.
2506  *
2507  * The cache stores (MAC src(index), IP src (major clue), signal,
2508  *      quality, noise)
2509  *
2510  * No apologies for storing IP src here.  It's easy and saves much
2511  * trouble elsewhere.  The cache is assumed to be INET dependent, 
2512  * although it need not be.
2513  */
2514
2515 #ifdef documentation
2516
2517 int owi_sigitems;                                /* number of cached entries */
2518 struct wi_sigcache owi_sigcache[MAXWICACHE];  /*  array of cache entries */
2519 int owi_nextitem;                                /*  index/# of entries */
2520
2521
2522 #endif
2523
2524 /* control variables for cache filtering.  Basic idea is
2525  * to reduce cost (e.g., to only Mobile-IP agent beacons
2526  * which are broadcast or multicast).  Still you might
2527  * want to measure signal strength with unicast ping packets
2528  * on a pt. to pt. ant. setup.
2529  */
2530 /* set true if you want to limit cache items to broadcast/mcast 
2531  * only packets (not unicast).  Useful for mobile-ip beacons which
2532  * are broadcast/multicast at network layer.  Default is all packets
2533  * so ping/unicast will work say with pt. to pt. antennae setup.
2534  */
2535 static int wi_cache_mcastonly = 0;
2536 SYSCTL_INT(_machdep, OID_AUTO, owi_cache_mcastonly, CTLFLAG_RW, 
2537         &wi_cache_mcastonly, 0, "");
2538
2539 /* set true if you want to limit cache items to IP packets only
2540 */
2541 static int wi_cache_iponly = 1;
2542 SYSCTL_INT(_machdep, OID_AUTO, owi_cache_iponly, CTLFLAG_RW, 
2543         &wi_cache_iponly, 0, "");
2544
2545 /*
2546  * Original comments:
2547  * -----------------
2548  * wi_cache_store, per rx packet store signal
2549  * strength in MAC (src) indexed cache.
2550  *
2551  * follows linux driver in how signal strength is computed.
2552  * In ad hoc mode, we use the rx_quality field. 
2553  * signal and noise are trimmed to fit in the range from 47..138.
2554  * rx_quality field MSB is signal strength.
2555  * rx_quality field LSB is noise.
2556  * "quality" is (signal - noise) as is log value.
2557  * note: quality CAN be negative.
2558  * 
2559  * In BSS mode, we use the RID for communication quality.
2560  * TBD:  BSS mode is currently untested.
2561  *
2562  * Bill's comments:
2563  * ---------------
2564  * Actually, we use the rx_quality field all the time for both "ad-hoc"
2565  * and BSS modes. Why? Because reading an RID is really, really expensive:
2566  * there's a bunch of PIO operations that have to be done to read a record
2567  * from the NIC, and reading the comms quality RID each time a packet is
2568  * received can really hurt performance. We don't have to do this anyway:
2569  * the comms quality field only reflects the values in the rx_quality field
2570  * anyway. The comms quality RID is only meaningful in infrastructure mode,
2571  * but the values it contains are updated based on the rx_quality from
2572  * frames received from the access point.
2573  *
2574  * Also, according to Lucent, the signal strength and noise level values
2575  * can be converted to dBms by subtracting 149, so I've modified the code
2576  * to do that instead of the scaling it did originally.
2577  */
2578 static void
2579 wi_cache_store(struct wi_softc *sc, struct mbuf *m, unsigned short rx_quality)
2580 {
2581         struct ether_header *eh = mtod(m, struct ether_header *);
2582         struct ip *ip = NULL; 
2583         int i;
2584         static int cache_slot = 0;      /* use this cache entry */
2585         static int wrapindex = 0;       /* next "free" cache entry */
2586         int sig, noise;
2587
2588         /* 
2589          * filters:
2590          * 1. ip only
2591          * 2. configurable filter to throw out unicast packets,
2592          * keep multicast only.
2593          */
2594  
2595         if ((ntohs(eh->ether_type) == ETHERTYPE_IP))
2596                 ip = (struct ip *)(mtod(m, uint8_t *) + ETHER_HDR_LEN);
2597         else if (wi_cache_iponly)
2598                 return;
2599
2600         /*
2601          *  filter for broadcast/multicast only
2602          */
2603         if (wi_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2604                 return;
2605         }
2606
2607 #ifdef SIGDEBUG
2608         printf("wi%d: q value %x (MSB=0x%x, LSB=0x%x) \n", sc->wi_unit,
2609             rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
2610 #endif
2611
2612         
2613         /*
2614          * do a linear search for a matching MAC address 
2615          * in the cache table
2616          * . MAC address is 6 bytes,
2617          * . var w_nextitem holds total number of entries already cached
2618          */
2619         for(i = 0; i < sc->wi_nextitem; i++) {
2620                 if (! bcmp(eh->ether_shost , sc->wi_sigcache[i].macsrc,  6 )) {
2621                         /* 
2622                          * Match!,
2623                          * so we already have this entry,
2624                          * update the data
2625                          */
2626                         break;  
2627                 }
2628         }
2629
2630         /*
2631          *  did we find a matching mac address?
2632          * if yes, then overwrite a previously existing cache entry
2633          */
2634         if (i < sc->wi_nextitem )   {
2635                 cache_slot = i; 
2636         }
2637         /*
2638          * else, have a new address entry,so
2639          * add this new entry,
2640          * if table full, then we need to replace LRU entry
2641          */
2642         else    {                          
2643
2644                 /* 
2645                  * check for space in cache table 
2646                  * note: wi_nextitem also holds number of entries
2647                  * added in the cache table 
2648                  */
2649                 if ( sc->wi_nextitem < MAXWICACHE ) {
2650                         cache_slot = sc->wi_nextitem;
2651                         sc->wi_nextitem++;                 
2652                         sc->wi_sigitems = sc->wi_nextitem;
2653                 }
2654                 /* no space found, so simply wrap with wrap index
2655                  * and "zap" the next entry
2656                  */
2657                 else {
2658                         if (wrapindex == MAXWICACHE) {
2659                                 wrapindex = 0;
2660                         }
2661                         cache_slot = wrapindex++;
2662                 }
2663         }
2664
2665         /* 
2666          * invariant: cache_slot now points at some slot
2667          * in cache.
2668          */
2669         if (cache_slot < 0 || cache_slot >= MAXWICACHE) {
2670                 log(LOG_ERR, "wi_cache_store, bad index: %d of "
2671                     "[0..%d], gross cache error\n",
2672                     cache_slot, MAXWICACHE);
2673                 return;
2674         }
2675
2676         /*
2677          *  store items in cache
2678          *  .ip source address
2679          *  .mac src
2680          *  .signal, etc.
2681          */
2682         if (ip != NULL)
2683                 sc->wi_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
2684         bcopy( eh->ether_shost, sc->wi_sigcache[cache_slot].macsrc,  6);
2685
2686         sig = (rx_quality >> 8) & 0xFF;
2687         noise = rx_quality & 0xFF;
2688         sc->wi_sigcache[cache_slot].signal = sig - 149;
2689         sc->wi_sigcache[cache_slot].noise = noise - 149;
2690         sc->wi_sigcache[cache_slot].quality = sig - noise;
2691
2692         return;
2693 }
2694 #endif
2695
2696 static int
2697 wi_get_cur_ssid(sc, ssid, len)
2698         struct wi_softc         *sc;
2699         char                    *ssid;
2700         int                     *len;
2701 {
2702         int                     error = 0;
2703         struct wi_req           wreq;
2704
2705         wreq.wi_len = WI_MAX_DATALEN;
2706         switch (sc->wi_ptype) {
2707         case WI_PORTTYPE_AP:
2708                 *len = IEEE80211_NWID_LEN;
2709                 bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN);
2710                 break;
2711         case WI_PORTTYPE_ADHOC:
2712                 wreq.wi_type = WI_RID_CURRENT_SSID;
2713                 error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
2714                 if (error != 0)
2715                         break;
2716                 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
2717                         error = EINVAL;
2718                         break;
2719                 }
2720                 *len = wreq.wi_val[0];
2721                 bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN);
2722                 break;
2723         case WI_PORTTYPE_BSS:
2724                 wreq.wi_type = WI_RID_COMMQUAL;
2725                 error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
2726                 if (error != 0)
2727                         break;
2728                 if (wreq.wi_val[0] != 0) /* associated */ {
2729                         wreq.wi_type = WI_RID_CURRENT_SSID;
2730                         wreq.wi_len = WI_MAX_DATALEN;
2731                         error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
2732                         if (error != 0)
2733                                 break;
2734                         if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
2735                                 error = EINVAL;
2736                                 break;
2737                         }
2738                         *len = wreq.wi_val[0];
2739                         bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN);
2740                 } else {
2741                         *len = IEEE80211_NWID_LEN;
2742                         bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN);
2743                 }
2744                 break;
2745         default:
2746                 error = EINVAL;
2747                 break;
2748         }
2749
2750         return error;
2751 }
2752
2753 static int
2754 wi_media_change(ifp)
2755         struct ifnet            *ifp;
2756 {
2757         struct wi_softc         *sc = ifp->if_softc;
2758         int                     otype = sc->wi_ptype;
2759         int                     orate = sc->wi_tx_rate;
2760         int                     ocreate_ibss = sc->wi_create_ibss;
2761
2762         if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
2763             sc->sc_firmware_type != WI_INTERSIL)
2764                 return (EINVAL);
2765
2766         sc->wi_create_ibss = 0;
2767
2768         switch (sc->ifmedia.ifm_cur->ifm_media & IFM_OMASK) {
2769         case 0:
2770                 sc->wi_ptype = WI_PORTTYPE_BSS;
2771                 break;
2772         case IFM_IEEE80211_ADHOC:
2773                 sc->wi_ptype = WI_PORTTYPE_ADHOC;
2774                 break;
2775         case IFM_IEEE80211_HOSTAP:
2776                 sc->wi_ptype = WI_PORTTYPE_AP;
2777                 break;
2778         case IFM_IEEE80211_IBSSMASTER:
2779         case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
2780                 if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
2781                         return (EINVAL);
2782                 sc->wi_create_ibss = 1;
2783                 /* FALLTHROUGH */
2784         case IFM_IEEE80211_IBSS:
2785                 sc->wi_ptype = WI_PORTTYPE_IBSS;
2786                 break;
2787         default:
2788                 /* Invalid combination. */
2789                 return (EINVAL);
2790         }
2791
2792         switch (IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) {
2793         case IFM_IEEE80211_DS1:
2794                 sc->wi_tx_rate = 1;
2795                 break;
2796         case IFM_IEEE80211_DS2:
2797                 sc->wi_tx_rate = 2;
2798                 break;
2799         case IFM_IEEE80211_DS5:
2800                 sc->wi_tx_rate = 5;
2801                 break;
2802         case IFM_IEEE80211_DS11:
2803                 sc->wi_tx_rate = 11;
2804                 break;
2805         case IFM_AUTO:
2806                 sc->wi_tx_rate = 3;
2807                 break;
2808         }
2809
2810         if (ocreate_ibss != sc->wi_create_ibss || otype != sc->wi_ptype ||
2811             orate != sc->wi_tx_rate)
2812                 wi_init(sc);
2813
2814         return(0);
2815 }
2816
2817 static void
2818 wi_media_status(ifp, imr)
2819         struct ifnet            *ifp;
2820         struct ifmediareq       *imr;
2821 {
2822         struct wi_req           wreq;
2823         struct wi_softc         *sc = ifp->if_softc;
2824
2825         if (sc->wi_tx_rate == 3) {
2826                 imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
2827                 if (sc->wi_ptype == WI_PORTTYPE_ADHOC)
2828                         imr->ifm_active |= IFM_IEEE80211_ADHOC;
2829                 else if (sc->wi_ptype == WI_PORTTYPE_AP)
2830                         imr->ifm_active |= IFM_IEEE80211_HOSTAP;
2831                 else if (sc->wi_ptype == WI_PORTTYPE_IBSS) {
2832                         if (sc->wi_create_ibss)
2833                                 imr->ifm_active |= IFM_IEEE80211_IBSSMASTER;
2834                         else
2835                                 imr->ifm_active |= IFM_IEEE80211_IBSS;
2836                 }
2837                 wreq.wi_type = WI_RID_CUR_TX_RATE;
2838                 wreq.wi_len = WI_MAX_DATALEN;
2839                 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
2840                         switch(wreq.wi_val[0]) {
2841                         case 1:
2842                                 imr->ifm_active |= IFM_IEEE80211_DS1;
2843                                 break;
2844                         case 2:
2845                                 imr->ifm_active |= IFM_IEEE80211_DS2;
2846                                 break;
2847                         case 6:
2848                                 imr->ifm_active |= IFM_IEEE80211_DS5;
2849                                 break;
2850                         case 11:
2851                                 imr->ifm_active |= IFM_IEEE80211_DS11;
2852                                 break;
2853                                 }
2854                 }
2855         } else {
2856                 imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media;
2857         }
2858
2859         imr->ifm_status = IFM_AVALID;
2860         if (sc->wi_ptype == WI_PORTTYPE_ADHOC ||
2861             sc->wi_ptype == WI_PORTTYPE_IBSS)
2862                 /*
2863                  * XXX: It would be nice if we could give some actually
2864                  * useful status like whether we joined another IBSS or
2865                  * created one ourselves.
2866                  */
2867                 imr->ifm_status |= IFM_ACTIVE;
2868         else if (sc->wi_ptype == WI_PORTTYPE_AP)
2869                 imr->ifm_status |= IFM_ACTIVE;
2870         else {
2871                 wreq.wi_type = WI_RID_COMMQUAL;
2872                 wreq.wi_len = WI_MAX_DATALEN;
2873                 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2874                     wreq.wi_val[0] != 0)
2875                         imr->ifm_status |= IFM_ACTIVE;
2876         }
2877 }
2878
2879 static int
2880 wi_get_debug(sc, wreq)
2881         struct wi_softc         *sc;
2882         struct wi_req           *wreq;
2883 {
2884         int                     error = 0;
2885
2886         wreq->wi_len = 1;
2887
2888         switch (wreq->wi_type) {
2889         case WI_DEBUG_SLEEP:
2890                 wreq->wi_len++;
2891                 wreq->wi_val[0] = sc->wi_debug.wi_sleep;
2892                 break;
2893         case WI_DEBUG_DELAYSUPP:
2894                 wreq->wi_len++;
2895                 wreq->wi_val[0] = sc->wi_debug.wi_delaysupp;
2896                 break;
2897         case WI_DEBUG_TXSUPP:
2898                 wreq->wi_len++;
2899                 wreq->wi_val[0] = sc->wi_debug.wi_txsupp;
2900                 break;
2901         case WI_DEBUG_MONITOR:
2902                 wreq->wi_len++;
2903                 wreq->wi_val[0] = sc->wi_debug.wi_monitor;
2904                 break;
2905         case WI_DEBUG_LEDTEST:
2906                 wreq->wi_len += 3;
2907                 wreq->wi_val[0] = sc->wi_debug.wi_ledtest;
2908                 wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0;
2909                 wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1;
2910                 break;
2911         case WI_DEBUG_CONTTX:
2912                 wreq->wi_len += 2;
2913                 wreq->wi_val[0] = sc->wi_debug.wi_conttx;
2914                 wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0;
2915                 break;
2916         case WI_DEBUG_CONTRX:
2917                 wreq->wi_len++;
2918                 wreq->wi_val[0] = sc->wi_debug.wi_contrx;
2919                 break;
2920         case WI_DEBUG_SIGSTATE:
2921                 wreq->wi_len += 2;
2922                 wreq->wi_val[0] = sc->wi_debug.wi_sigstate;
2923                 wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0;
2924                 break;
2925         case WI_DEBUG_CONFBITS:
2926                 wreq->wi_len += 2;
2927                 wreq->wi_val[0] = sc->wi_debug.wi_confbits;
2928                 wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0;
2929                 break;
2930         default:
2931                 error = EIO;
2932                 break;
2933         }
2934
2935         return (error);
2936 }
2937
2938 static int
2939 wi_set_debug(sc, wreq)
2940         struct wi_softc         *sc;
2941         struct wi_req           *wreq;
2942 {
2943         int                     error = 0;
2944         u_int16_t               cmd, param0 = 0, param1 = 0;
2945
2946         switch (wreq->wi_type) {
2947         case WI_DEBUG_RESET:
2948         case WI_DEBUG_INIT:
2949         case WI_DEBUG_CALENABLE:
2950                 break;
2951         case WI_DEBUG_SLEEP:
2952                 sc->wi_debug.wi_sleep = 1;
2953                 break;
2954         case WI_DEBUG_WAKE:
2955                 sc->wi_debug.wi_sleep = 0;
2956                 break;
2957         case WI_DEBUG_CHAN:
2958                 param0 = wreq->wi_val[0];
2959                 break;
2960         case WI_DEBUG_DELAYSUPP:
2961                 sc->wi_debug.wi_delaysupp = 1;
2962                 break;
2963         case WI_DEBUG_TXSUPP:
2964                 sc->wi_debug.wi_txsupp = 1;
2965                 break;
2966         case WI_DEBUG_MONITOR:
2967                 sc->wi_debug.wi_monitor = 1;
2968                 break;
2969         case WI_DEBUG_LEDTEST:
2970                 param0 = wreq->wi_val[0];
2971                 param1 = wreq->wi_val[1];
2972                 sc->wi_debug.wi_ledtest = 1;
2973                 sc->wi_debug.wi_ledtest_param0 = param0;
2974                 sc->wi_debug.wi_ledtest_param1 = param1;
2975                 break;
2976         case WI_DEBUG_CONTTX:
2977                 param0 = wreq->wi_val[0];
2978                 sc->wi_debug.wi_conttx = 1;
2979                 sc->wi_debug.wi_conttx_param0 = param0;
2980                 break;
2981         case WI_DEBUG_STOPTEST:
2982                 sc->wi_debug.wi_delaysupp = 0;
2983                 sc->wi_debug.wi_txsupp = 0;
2984                 sc->wi_debug.wi_monitor = 0;
2985                 sc->wi_debug.wi_ledtest = 0;
2986                 sc->wi_debug.wi_ledtest_param0 = 0;
2987                 sc->wi_debug.wi_ledtest_param1 = 0;
2988                 sc->wi_debug.wi_conttx = 0;
2989                 sc->wi_debug.wi_conttx_param0 = 0;
2990                 sc->wi_debug.wi_contrx = 0;
2991                 sc->wi_debug.wi_sigstate = 0;
2992                 sc->wi_debug.wi_sigstate_param0 = 0;
2993                 break;
2994         case WI_DEBUG_CONTRX:
2995                 sc->wi_debug.wi_contrx = 1;
2996                 break;
2997         case WI_DEBUG_SIGSTATE:
2998                 param0 = wreq->wi_val[0];
2999                 sc->wi_debug.wi_sigstate = 1;
3000                 sc->wi_debug.wi_sigstate_param0 = param0;
3001                 break;
3002         case WI_DEBUG_CONFBITS:
3003                 param0 = wreq->wi_val[0];
3004                 param1 = wreq->wi_val[1];
3005                 sc->wi_debug.wi_confbits = param0;
3006                 sc->wi_debug.wi_confbits_param0 = param1;
3007                 break;
3008         default:
3009                 error = EIO;
3010                 break;
3011         }
3012
3013         if (error)
3014                 return (error);
3015
3016         cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3017         error = wi_cmd(sc, cmd, param0, param1, 0);
3018
3019         return (error);
3020 }