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