1 /* $NetBSD: wi.c,v 1.109 2003/01/09 08:52:19 dyoung Exp $ */
4 * Copyright (c) 1997, 1998, 1999
5 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
34 * $FreeBSD: src/sys/dev/wi/if_wi.c,v 1.180.2.7 2005/10/05 13:16:29 avatar Exp $
35 * $DragonFly: src/sys/dev/netif/wi/if_wi.c,v 1.41 2008/05/14 11:59:22 sephe Exp $
39 * Lucent WaveLAN/IEEE 802.11 PCMCIA driver.
41 * Original FreeBSD driver written by Bill Paul <wpaul@ctr.columbia.edu>
42 * Electrical Engineering Department
43 * Columbia University, New York City
47 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
48 * from Lucent. Unlike the older cards, the new ones are programmed
49 * entirely via a firmware-driven controller called the Hermes.
50 * Unfortunately, Lucent will not release the Hermes programming manual
51 * without an NDA (if at all). What they do release is an API library
52 * called the HCF (Hardware Control Functions) which is supposed to
53 * do the device-specific operations of a device driver for you. The
54 * publically available version of the HCF library (the 'HCF Light') is
55 * a) extremely gross, b) lacks certain features, particularly support
56 * for 802.11 frames, and c) is contaminated by the GNU Public License.
58 * This driver does not use the HCF or HCF Light at all. Instead, it
59 * programs the Hermes controller directly, using information gleaned
60 * from the HCF Light code and corresponding documentation.
62 * This driver supports the ISA, PCMCIA and PCI versions of the Lucent
63 * WaveLan cards (based on the Hermes chipset), as well as the newer
64 * Prism 2 chipsets with firmware from Intersil and Symbol.
67 #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
68 #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
70 #include "opt_polling.h"
72 #include <sys/param.h>
73 #include <sys/endian.h>
74 #include <sys/systm.h>
75 #include <sys/sockio.h>
79 #include <sys/kernel.h>
80 #include <sys/socket.h>
81 #include <sys/module.h>
83 #include <sys/random.h>
84 #include <sys/syslog.h>
85 #include <sys/sysctl.h>
86 #include <sys/serialize.h>
88 #include <sys/thread2.h>
89 #include <sys/interrupt.h>
91 #include <machine/atomic.h>
94 #include <net/if_arp.h>
95 #include <net/ethernet.h>
96 #include <net/if_dl.h>
97 #include <net/if_media.h>
98 #include <net/if_types.h>
99 #include <net/ifq_var.h>
101 #include <netproto/802_11/ieee80211_var.h>
102 #include <netproto/802_11/ieee80211_ioctl.h>
103 #include <netproto/802_11/ieee80211_radiotap.h>
104 #include <netproto/802_11/if_wavelan_ieee.h>
106 #include <netinet/in.h>
107 #include <netinet/in_systm.h>
108 #include <netinet/in_var.h>
109 #include <netinet/ip.h>
110 #include <netinet/if_ether.h>
114 #include <dev/netif/wi/if_wireg.h>
115 #include <dev/netif/wi/if_wivar.h>
117 static void wi_start(struct ifnet
*);
118 static int wi_reset(struct wi_softc
*);
119 static void wi_watchdog(struct ifnet
*);
120 static int wi_ioctl(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
121 static int wi_media_change(struct ifnet
*);
122 static void wi_media_status(struct ifnet
*, struct ifmediareq
*);
124 static void wi_rx_intr(struct wi_softc
*);
125 static void wi_tx_intr(struct wi_softc
*);
126 static void wi_tx_ex_intr(struct wi_softc
*);
127 static void wi_info_intr(struct wi_softc
*);
129 static int wi_get_cfg(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
130 static int wi_set_cfg(struct ifnet
*, u_long
, caddr_t
);
131 static int wi_write_txrate(struct wi_softc
*);
132 static int wi_write_wep(struct wi_softc
*);
133 static int wi_write_multi(struct wi_softc
*);
134 static int wi_alloc_fid(struct wi_softc
*, int, int *);
135 static void wi_read_nicid(struct wi_softc
*);
136 static int wi_write_ssid(struct wi_softc
*, int, u_int8_t
*, int);
138 static int wi_cmd(struct wi_softc
*, int, int, int, int);
139 static int wi_seek_bap(struct wi_softc
*, int, int);
140 static int wi_read_bap(struct wi_softc
*, int, int, void *, int);
141 static int wi_write_bap(struct wi_softc
*, int, int, void *, int);
142 static int wi_mwrite_bap(struct wi_softc
*, int, int, struct mbuf
*, int);
143 static int wi_read_rid(struct wi_softc
*, int, void *, int *);
144 static int wi_write_rid(struct wi_softc
*, int, void *, int);
146 static int wi_key_alloc(struct ieee80211com
*, const struct ieee80211_key
*,
147 ieee80211_keyix
*, ieee80211_keyix
*);
148 static int wi_newstate(struct ieee80211com
*, enum ieee80211_state
, int);
150 static int wi_scan_ap(struct wi_softc
*, u_int16_t
, u_int16_t
);
151 static void wi_scan_result(struct wi_softc
*, int, int);
153 static void wi_dump_pkt(struct wi_frame
*, struct ieee80211_node
*, int rssi
);
155 static int wi_get_debug(struct wi_softc
*, struct wi_req
*);
156 static int wi_set_debug(struct wi_softc
*, struct wi_req
*);
158 /* support to download firmware for symbol CF card */
159 static int wi_symbol_write_firm(struct wi_softc
*, const void *, int,
161 static int wi_symbol_set_hcr(struct wi_softc
*, int);
162 #ifdef DEVICE_POLLING
163 static void wi_poll(struct ifnet
*ifp
, enum poll_cmd cmd
, int count
);
167 wi_write_val(struct wi_softc
*sc
, int rid
, u_int16_t val
)
171 return wi_write_rid(sc
, rid
, &val
, sizeof(val
));
174 SYSCTL_NODE(_hw
, OID_AUTO
, wi
, CTLFLAG_RD
, 0, "Wireless driver parameters");
176 static struct timeval lasttxerror
; /* time of last tx error msg */
177 static int curtxeps
; /* current tx error msgs/sec */
178 static int wi_txerate
= 0; /* tx error rate: max msgs/sec */
179 SYSCTL_INT(_hw_wi
, OID_AUTO
, txerate
, CTLFLAG_RW
, &wi_txerate
,
180 0, "max tx error msgs/sec; 0 to disable msgs");
184 static int wi_debug
= 0;
185 SYSCTL_INT(_hw_wi
, OID_AUTO
, debug
, CTLFLAG_RW
, &wi_debug
,
186 0, "control debugging kprintfs");
188 #define DPRINTF(X) if (wi_debug) if_printf X
189 #define DPRINTF2(X) if (wi_debug > 1) if_printf X
190 #define IFF_DUMPPKTS(_ifp) \
191 (((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
195 #define IFF_DUMPPKTS(_ifp) 0
198 #define WI_INTRS (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO)
200 struct wi_card_ident wi_card_ident
[] = {
201 /* CARD_ID CARD_NAME FIRM_TYPE */
202 { WI_NIC_LUCENT_ID
, WI_NIC_LUCENT_STR
, WI_LUCENT
},
203 { WI_NIC_SONY_ID
, WI_NIC_SONY_STR
, WI_LUCENT
},
204 { WI_NIC_LUCENT_EMB_ID
, WI_NIC_LUCENT_EMB_STR
, WI_LUCENT
},
205 { WI_NIC_EVB2_ID
, WI_NIC_EVB2_STR
, WI_INTERSIL
},
206 { WI_NIC_HWB3763_ID
, WI_NIC_HWB3763_STR
, WI_INTERSIL
},
207 { WI_NIC_HWB3163_ID
, WI_NIC_HWB3163_STR
, WI_INTERSIL
},
208 { WI_NIC_HWB3163B_ID
, WI_NIC_HWB3163B_STR
, WI_INTERSIL
},
209 { WI_NIC_EVB3_ID
, WI_NIC_EVB3_STR
, WI_INTERSIL
},
210 { WI_NIC_HWB1153_ID
, WI_NIC_HWB1153_STR
, WI_INTERSIL
},
211 { WI_NIC_P2_SST_ID
, WI_NIC_P2_SST_STR
, WI_INTERSIL
},
212 { WI_NIC_EVB2_SST_ID
, WI_NIC_EVB2_SST_STR
, WI_INTERSIL
},
213 { WI_NIC_3842_EVA_ID
, WI_NIC_3842_EVA_STR
, WI_INTERSIL
},
214 { WI_NIC_3842_PCMCIA_AMD_ID
, WI_NIC_3842_PCMCIA_STR
, WI_INTERSIL
},
215 { WI_NIC_3842_PCMCIA_SST_ID
, WI_NIC_3842_PCMCIA_STR
, WI_INTERSIL
},
216 { WI_NIC_3842_PCMCIA_ATL_ID
, WI_NIC_3842_PCMCIA_STR
, WI_INTERSIL
},
217 { WI_NIC_3842_PCMCIA_ATS_ID
, WI_NIC_3842_PCMCIA_STR
, WI_INTERSIL
},
218 { WI_NIC_3842_MINI_AMD_ID
, WI_NIC_3842_MINI_STR
, WI_INTERSIL
},
219 { WI_NIC_3842_MINI_SST_ID
, WI_NIC_3842_MINI_STR
, WI_INTERSIL
},
220 { WI_NIC_3842_MINI_ATL_ID
, WI_NIC_3842_MINI_STR
, WI_INTERSIL
},
221 { WI_NIC_3842_MINI_ATS_ID
, WI_NIC_3842_MINI_STR
, WI_INTERSIL
},
222 { WI_NIC_3842_PCI_AMD_ID
, WI_NIC_3842_PCI_STR
, WI_INTERSIL
},
223 { WI_NIC_3842_PCI_SST_ID
, WI_NIC_3842_PCI_STR
, WI_INTERSIL
},
224 { WI_NIC_3842_PCI_ATS_ID
, WI_NIC_3842_PCI_STR
, WI_INTERSIL
},
225 { WI_NIC_3842_PCI_ATL_ID
, WI_NIC_3842_PCI_STR
, WI_INTERSIL
},
226 { WI_NIC_P3_PCMCIA_AMD_ID
, WI_NIC_P3_PCMCIA_STR
, WI_INTERSIL
},
227 { WI_NIC_P3_PCMCIA_SST_ID
, WI_NIC_P3_PCMCIA_STR
, WI_INTERSIL
},
228 { WI_NIC_P3_PCMCIA_ATL_ID
, WI_NIC_P3_PCMCIA_STR
, WI_INTERSIL
},
229 { WI_NIC_P3_PCMCIA_ATS_ID
, WI_NIC_P3_PCMCIA_STR
, WI_INTERSIL
},
230 { WI_NIC_P3_MINI_AMD_ID
, WI_NIC_P3_MINI_STR
, WI_INTERSIL
},
231 { WI_NIC_P3_MINI_SST_ID
, WI_NIC_P3_MINI_STR
, WI_INTERSIL
},
232 { WI_NIC_P3_MINI_ATL_ID
, WI_NIC_P3_MINI_STR
, WI_INTERSIL
},
233 { WI_NIC_P3_MINI_ATS_ID
, WI_NIC_P3_MINI_STR
, WI_INTERSIL
},
237 devclass_t wi_devclass
;
240 wi_attach(device_t dev
)
242 struct wi_softc
*sc
= device_get_softc(dev
);
243 struct ieee80211com
*ic
= &sc
->sc_ic
;
244 struct ifnet
*ifp
= &ic
->ic_if
;
245 int i
, nrates
, buflen
;
247 u_int8_t ratebuf
[2 + IEEE80211_RATE_SIZE
];
248 struct ieee80211_rateset
*rs
;
249 static const u_int8_t empty_macaddr
[IEEE80211_ADDR_LEN
] = {
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
255 if_initname(ifp
, device_get_name(dev
), device_get_unit(dev
));
257 sc
->sc_firmware_type
= WI_NOTYPE
;
258 sc
->wi_cmd_count
= 500;
261 error
= wi_reset(sc
);
266 * Read the station address.
267 * And do it twice. I've seen PRISM-based cards that return
268 * an error when trying to read it the first time, which causes
271 buflen
= IEEE80211_ADDR_LEN
;
272 error
= wi_read_rid(sc
, WI_RID_MAC_NODE
, ic
->ic_myaddr
, &buflen
);
274 buflen
= IEEE80211_ADDR_LEN
;
275 error
= wi_read_rid(sc
, WI_RID_MAC_NODE
, ic
->ic_myaddr
, &buflen
);
278 device_printf(dev
, "mac read failed %d\n", error
);
281 if (IEEE80211_ADDR_EQ(ic
->ic_myaddr
, empty_macaddr
)) {
282 device_printf(dev
, "mac read failed (all zeros)\n");
287 /* Read NIC identification */
290 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
291 ifp
->if_ioctl
= wi_ioctl
;
292 ifp
->if_start
= wi_start
;
293 ifp
->if_watchdog
= wi_watchdog
;
294 ifp
->if_init
= wi_init
;
295 ifq_set_maxlen(&ifp
->if_snd
, IFQ_MAXLEN
);
296 ifq_set_ready(&ifp
->if_snd
);
297 #ifdef DEVICE_POLLING
298 ifp
->if_poll
= wi_poll
;
300 ifp
->if_capenable
= ifp
->if_capabilities
;
302 ic
->ic_phytype
= IEEE80211_T_DS
;
303 ic
->ic_opmode
= IEEE80211_M_STA
;
304 ic
->ic_caps
= IEEE80211_C_PMGT
|
307 ic
->ic_state
= IEEE80211_S_INIT
;
308 ic
->ic_max_aid
= WI_MAX_AID
;
311 * Query the card for available channels and setup the
312 * channel table. We assume these are all 11b channels.
314 buflen
= sizeof(val
);
315 if (wi_read_rid(sc
, WI_RID_CHANNEL_LIST
, &val
, &buflen
) != 0)
316 val
= htole16(0x1fff); /* assume 1-11 */
317 KASSERT(val
!= 0, ("wi_attach: no available channels listed!"));
319 val
<<= 1; /* shift for base 1 indices */
320 for (i
= 1; i
< 16; i
++) {
321 if (isset((u_int8_t
*)&val
, i
)) {
322 ic
->ic_channels
[i
].ic_freq
=
323 ieee80211_ieee2mhz(i
, IEEE80211_CHAN_B
);
324 ic
->ic_channels
[i
].ic_flags
= IEEE80211_CHAN_B
;
329 * Read the default channel from the NIC. This may vary
330 * depending on the country where the NIC was purchased, so
331 * we can't hard-code a default and expect it to work for
334 * If no channel is specified, let the 802.11 code select.
336 buflen
= sizeof(val
);
337 if (wi_read_rid(sc
, WI_RID_OWN_CHNL
, &val
, &buflen
) == 0) {
339 KASSERT(val
< IEEE80211_CHAN_MAX
&&
340 ic
->ic_channels
[val
].ic_flags
!= 0,
341 ("wi_attach: invalid own channel %u!", val
));
342 ic
->ic_ibss_chan
= &ic
->ic_channels
[val
];
345 "WI_RID_OWN_CHNL failed, using first channel!\n");
346 ic
->ic_ibss_chan
= &ic
->ic_channels
[0];
350 * Set flags based on firmware version.
352 switch (sc
->sc_firmware_type
) {
355 sc
->sc_flags
|= WI_FLAGS_HAS_SYSSCALE
;
356 #ifdef WI_HERMES_AUTOINC_WAR
357 /* XXX: not confirmed, but never seen for recent firmware */
358 if (sc
->sc_sta_firmware_ver
< 40000) {
359 sc
->sc_flags
|= WI_FLAGS_BUG_AUTOINC
;
362 if (sc
->sc_sta_firmware_ver
>= 60000)
363 sc
->sc_flags
|= WI_FLAGS_HAS_MOR
;
364 if (sc
->sc_sta_firmware_ver
>= 60006) {
365 ic
->ic_caps
|= IEEE80211_C_IBSS
;
366 ic
->ic_caps
|= IEEE80211_C_MONITOR
;
368 sc
->sc_ibss_port
= htole16(1);
370 sc
->sc_min_rssi
= WI_LUCENT_MIN_RSSI
;
371 sc
->sc_max_rssi
= WI_LUCENT_MAX_RSSI
;
372 sc
->sc_dbm_offset
= WI_LUCENT_DBM_OFFSET
;
376 sc
->sc_ntxbuf
= WI_NTXBUF
;
377 sc
->sc_flags
|= WI_FLAGS_HAS_FRAGTHR
;
378 sc
->sc_flags
|= WI_FLAGS_HAS_ROAMING
;
379 sc
->sc_flags
|= WI_FLAGS_HAS_SYSSCALE
;
381 * Old firmware are slow, so give peace a chance.
383 if (sc
->sc_sta_firmware_ver
< 10000)
384 sc
->wi_cmd_count
= 5000;
385 if (sc
->sc_sta_firmware_ver
> 10101)
386 sc
->sc_flags
|= WI_FLAGS_HAS_DBMADJUST
;
387 if (sc
->sc_sta_firmware_ver
>= 800) {
388 ic
->ic_caps
|= IEEE80211_C_IBSS
;
389 ic
->ic_caps
|= IEEE80211_C_MONITOR
;
392 * version 0.8.3 and newer are the only ones that are known
393 * to currently work. Earlier versions can be made to work,
394 * at least according to the Linux driver.
396 if (sc
->sc_sta_firmware_ver
>= 803)
397 ic
->ic_caps
|= IEEE80211_C_HOSTAP
;
398 sc
->sc_ibss_port
= htole16(0);
400 sc
->sc_min_rssi
= WI_PRISM_MIN_RSSI
;
401 sc
->sc_max_rssi
= WI_PRISM_MAX_RSSI
;
402 sc
->sc_dbm_offset
= WI_PRISM_DBM_OFFSET
;
407 sc
->sc_flags
|= WI_FLAGS_HAS_DIVERSITY
;
408 if (sc
->sc_sta_firmware_ver
>= 25000)
409 ic
->ic_caps
|= IEEE80211_C_IBSS
;
410 sc
->sc_ibss_port
= htole16(4);
412 sc
->sc_min_rssi
= WI_PRISM_MIN_RSSI
;
413 sc
->sc_max_rssi
= WI_PRISM_MAX_RSSI
;
414 sc
->sc_dbm_offset
= WI_PRISM_DBM_OFFSET
;
419 * Find out if we support WEP on this card.
421 buflen
= sizeof(val
);
422 if (wi_read_rid(sc
, WI_RID_WEP_AVAIL
, &val
, &buflen
) == 0 &&
424 ic
->ic_caps
|= IEEE80211_C_WEP
;
426 /* Find supported rates. */
427 buflen
= sizeof(ratebuf
);
428 rs
= &ic
->ic_sup_rates
[IEEE80211_MODE_11B
];
429 if (wi_read_rid(sc
, WI_RID_DATA_RATES
, ratebuf
, &buflen
) == 0) {
430 nrates
= le16toh(*(u_int16_t
*)ratebuf
);
431 if (nrates
> IEEE80211_RATE_MAXSIZE
)
432 nrates
= IEEE80211_RATE_MAXSIZE
;
434 for (i
= 0; i
< nrates
; i
++)
436 rs
->rs_rates
[rs
->rs_nrates
++] = ratebuf
[2+i
];
438 /* XXX fallback on error? */
442 buflen
= sizeof(val
);
443 if ((sc
->sc_flags
& WI_FLAGS_HAS_DBMADJUST
) &&
444 wi_read_rid(sc
, WI_RID_DBM_ADJUST
, &val
, &buflen
) == 0) {
445 sc
->sc_dbm_offset
= le16toh(val
);
448 sc
->sc_max_datalen
= 2304;
449 sc
->sc_system_scale
= 1;
450 sc
->sc_cnfauthmode
= IEEE80211_AUTH_OPEN
;
451 sc
->sc_roaming_mode
= 1;
453 sc
->sc_portnum
= WI_DEFAULT_PORT
;
454 sc
->sc_authtype
= WI_DEFAULT_AUTHTYPE
;
456 bzero(sc
->sc_nodename
, sizeof(sc
->sc_nodename
));
457 sc
->sc_nodelen
= sizeof(WI_DEFAULT_NODENAME
) - 1;
458 bcopy(WI_DEFAULT_NODENAME
, sc
->sc_nodename
, sc
->sc_nodelen
);
460 bzero(sc
->sc_net_name
, sizeof(sc
->sc_net_name
));
461 bcopy(WI_DEFAULT_NETNAME
, sc
->sc_net_name
,
462 sizeof(WI_DEFAULT_NETNAME
) - 1);
465 * Call MI attach routine.
467 ieee80211_ifattach(ic
);
468 /* override state transition method */
469 sc
->sc_newstate
= ic
->ic_newstate
;
470 sc
->sc_key_alloc
= ic
->ic_crypto
.cs_key_alloc
;
471 ic
->ic_crypto
.cs_key_alloc
= wi_key_alloc
;
472 ic
->ic_newstate
= wi_newstate
;
473 ieee80211_media_init(ic
, wi_media_change
, wi_media_status
);
475 bpfattach_dlt(ifp
, DLT_IEEE802_11_RADIO
,
476 sizeof(struct ieee80211_frame
) + sizeof(sc
->sc_tx_th
),
479 * Initialize constant fields.
480 * XXX make header lengths a multiple of 32-bits so subsequent
481 * headers are properly aligned; this is a kludge to keep
482 * certain applications happy.
484 * NB: the channel is setup each time we transition to the
485 * RUN state to avoid filling it in for each frame.
487 sc
->sc_tx_th_len
= roundup(sizeof(sc
->sc_tx_th
), sizeof(u_int32_t
));
488 sc
->sc_tx_th
.wt_ihdr
.it_len
= htole16(sc
->sc_tx_th_len
);
489 sc
->sc_tx_th
.wt_ihdr
.it_present
= htole32(WI_TX_RADIOTAP_PRESENT
);
491 sc
->sc_rx_th_len
= roundup(sizeof(sc
->sc_rx_th
), sizeof(u_int32_t
));
492 sc
->sc_rx_th
.wr_ihdr
.it_len
= htole16(sc
->sc_rx_th_len
);
493 sc
->sc_rx_th
.wr_ihdr
.it_present
= htole32(WI_RX_RADIOTAP_PRESENT
);
495 error
= bus_setup_intr(dev
, sc
->irq
, INTR_MPSAFE
,
496 wi_intr
, sc
, &sc
->wi_intrhand
,
500 ieee80211_ifdetach(ic
);
501 device_printf(dev
, "bus_setup_intr() failed! (%d)\n", error
);
505 ifp
->if_cpuid
= ithread_cpuid(rman_get_start(sc
->irq
));
506 KKASSERT(ifp
->if_cpuid
>= 0 && ifp
->if_cpuid
< ncpus
);
509 ieee80211_announce(ic
);
519 wi_detach(device_t dev
)
521 struct wi_softc
*sc
= device_get_softc(dev
);
522 struct ifnet
*ifp
= &sc
->sc_ic
.ic_if
;
524 lwkt_serialize_enter(ifp
->if_serializer
);
526 /* check if device was removed */
527 sc
->wi_gone
|= !bus_child_present(dev
);
529 bus_teardown_intr(dev
, sc
->irq
, sc
->wi_intrhand
);
531 lwkt_serialize_exit(ifp
->if_serializer
);
534 ieee80211_ifdetach(&sc
->sc_ic
);
540 wi_shutdown(device_t dev
)
542 struct wi_softc
*sc
= device_get_softc(dev
);
543 struct ifnet
*ifp
= &sc
->sc_if
;
545 lwkt_serialize_enter(ifp
->if_serializer
);
547 lwkt_serialize_exit(ifp
->if_serializer
);
550 #ifdef DEVICE_POLLING
553 wi_poll(struct ifnet
*ifp
, enum poll_cmd cmd
, int count
)
555 struct wi_softc
*sc
= ifp
->if_softc
;
560 /* disable interruptds */
561 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
563 case POLL_DEREGISTER
:
564 /* enable interrupts */
565 CSR_WRITE_2(sc
, WI_INT_EN
, WI_INTRS
);
568 status
= CSR_READ_2(sc
, WI_EVENT_STAT
);
570 if (status
& WI_EV_RX
)
572 if (status
& WI_EV_ALLOC
)
574 if (status
& WI_EV_INFO
)
577 if (cmd
== POLL_AND_CHECK_STATUS
) {
578 if (status
& WI_EV_INFO
)
582 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0 &&
583 (sc
->sc_flags
& WI_FLAGS_OUTRANGE
) == 0)
588 #endif /* DEVICE_POLLING */
593 struct wi_softc
*sc
= arg
;
594 struct ifnet
*ifp
= &sc
->sc_ic
.ic_if
;
597 if (sc
->wi_gone
|| !sc
->sc_enabled
|| (ifp
->if_flags
& IFF_UP
) == 0) {
598 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
599 CSR_WRITE_2(sc
, WI_EVENT_ACK
, 0xFFFF);
603 /* Disable interrupts. */
604 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
606 status
= CSR_READ_2(sc
, WI_EVENT_STAT
);
607 if (status
& WI_EV_RX
)
609 if (status
& WI_EV_ALLOC
)
611 if (status
& WI_EV_TX_EXC
)
613 if (status
& WI_EV_INFO
)
615 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0 &&
616 (sc
->sc_flags
& WI_FLAGS_OUTRANGE
) == 0)
619 /* Re-enable interrupts. */
620 CSR_WRITE_2(sc
, WI_INT_EN
, WI_INTRS
);
626 struct wi_softc
*sc
= arg
;
627 struct ifnet
*ifp
= &sc
->sc_if
;
628 struct ieee80211com
*ic
= &sc
->sc_ic
;
629 struct wi_joinreq join
;
631 int error
= 0, wasenabled
;
636 if ((wasenabled
= sc
->sc_enabled
))
640 /* common 802.11 configuration */
641 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
642 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
643 switch (ic
->ic_opmode
) {
644 case IEEE80211_M_STA
:
645 wi_write_val(sc
, WI_RID_PORTTYPE
, WI_PORTTYPE_BSS
);
647 case IEEE80211_M_IBSS
:
648 wi_write_val(sc
, WI_RID_PORTTYPE
, sc
->sc_ibss_port
);
649 ic
->ic_flags
|= IEEE80211_F_IBSSON
;
651 case IEEE80211_M_AHDEMO
:
652 wi_write_val(sc
, WI_RID_PORTTYPE
, WI_PORTTYPE_ADHOC
);
654 case IEEE80211_M_HOSTAP
:
656 * For PRISM cards, override the empty SSID, because in
657 * HostAP mode the controller will lock up otherwise.
659 if (sc
->sc_firmware_type
== WI_INTERSIL
&&
660 ic
->ic_des_esslen
== 0) {
661 ic
->ic_des_essid
[0] = ' ';
662 ic
->ic_des_esslen
= 1;
664 wi_write_val(sc
, WI_RID_PORTTYPE
, WI_PORTTYPE_HOSTAP
);
666 case IEEE80211_M_MONITOR
:
667 if (sc
->sc_firmware_type
== WI_LUCENT
)
668 wi_write_val(sc
, WI_RID_PORTTYPE
, WI_PORTTYPE_ADHOC
);
669 wi_cmd(sc
, WI_CMD_DEBUG
| (WI_TEST_MONITOR
<< 8), 0, 0, 0);
673 /* Intersil interprets this RID as joining ESS even in IBSS mode */
674 if (sc
->sc_firmware_type
== WI_LUCENT
&&
675 (ic
->ic_flags
& IEEE80211_F_IBSSON
) && ic
->ic_des_esslen
> 0)
676 wi_write_val(sc
, WI_RID_CREATE_IBSS
, 1);
678 wi_write_val(sc
, WI_RID_CREATE_IBSS
, 0);
679 wi_write_val(sc
, WI_RID_MAX_SLEEP
, ic
->ic_lintval
);
680 wi_write_ssid(sc
, WI_RID_DESIRED_SSID
, ic
->ic_des_essid
,
682 wi_write_val(sc
, WI_RID_OWN_CHNL
,
683 ieee80211_chan2ieee(ic
, ic
->ic_ibss_chan
));
684 wi_write_ssid(sc
, WI_RID_OWN_SSID
, ic
->ic_des_essid
, ic
->ic_des_esslen
);
686 IEEE80211_ADDR_COPY(ic
->ic_myaddr
, IF_LLADDR(ifp
));
687 wi_write_rid(sc
, WI_RID_MAC_NODE
, ic
->ic_myaddr
, IEEE80211_ADDR_LEN
);
689 if (ic
->ic_caps
& IEEE80211_C_PMGT
) {
690 wi_write_val(sc
, WI_RID_PM_ENABLED
,
691 (ic
->ic_flags
& IEEE80211_F_PMGTON
) ? 1 : 0);
694 /* not yet common 802.11 configuration */
695 wi_write_val(sc
, WI_RID_MAX_DATALEN
, sc
->sc_max_datalen
);
696 wi_write_val(sc
, WI_RID_RTS_THRESH
, ic
->ic_rtsthreshold
);
697 if (sc
->sc_flags
& WI_FLAGS_HAS_FRAGTHR
)
698 wi_write_val(sc
, WI_RID_FRAG_THRESH
, ic
->ic_fragthreshold
);
700 /* driver specific 802.11 configuration */
701 if (sc
->sc_flags
& WI_FLAGS_HAS_SYSSCALE
)
702 wi_write_val(sc
, WI_RID_SYSTEM_SCALE
, sc
->sc_system_scale
);
703 if (sc
->sc_flags
& WI_FLAGS_HAS_ROAMING
)
704 wi_write_val(sc
, WI_RID_ROAMING_MODE
, sc
->sc_roaming_mode
);
705 if (sc
->sc_flags
& WI_FLAGS_HAS_MOR
)
706 wi_write_val(sc
, WI_RID_MICROWAVE_OVEN
, sc
->sc_microwave_oven
);
708 wi_write_ssid(sc
, WI_RID_NODENAME
, sc
->sc_nodename
, sc
->sc_nodelen
);
710 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
711 sc
->sc_firmware_type
== WI_INTERSIL
) {
712 wi_write_val(sc
, WI_RID_OWN_BEACON_INT
, ic
->ic_bintval
);
713 wi_write_val(sc
, WI_RID_BASIC_RATE
, 0x03); /* 1, 2 */
714 wi_write_val(sc
, WI_RID_SUPPORT_RATE
, 0x0f); /* 1, 2, 5.5, 11 */
715 wi_write_val(sc
, WI_RID_DTIM_PERIOD
, ic
->ic_dtim_period
);
719 * Initialize promisc mode.
720 * Being in the Host-AP mode causes a great
721 * deal of pain if primisc mode is set.
722 * Therefore we avoid confusing the firmware
723 * and always reset promisc mode in Host-AP
724 * mode. Host-AP sees all the packets anyway.
726 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
727 (ifp
->if_flags
& IFF_PROMISC
) != 0) {
728 wi_write_val(sc
, WI_RID_PROMISC
, 1);
730 wi_write_val(sc
, WI_RID_PROMISC
, 0);
734 if (ic
->ic_caps
& IEEE80211_C_WEP
) {
735 sc
->sc_cnfauthmode
= ic
->ic_bss
->ni_authmode
;
738 sc
->sc_encryption
= 0;
741 /* Set multicast filter. */
744 /* Allocate fids for the card */
745 if (sc
->sc_firmware_type
!= WI_SYMBOL
|| !wasenabled
) {
746 sc
->sc_buflen
= IEEE80211_MAX_LEN
+ sizeof(struct wi_frame
);
747 if (sc
->sc_firmware_type
== WI_SYMBOL
)
748 sc
->sc_buflen
= 1585; /* XXX */
749 for (i
= 0; i
< sc
->sc_ntxbuf
; i
++) {
750 error
= wi_alloc_fid(sc
, sc
->sc_buflen
,
751 &sc
->sc_txd
[i
].d_fid
);
754 "tx buffer allocation failed (error %u)\n",
758 sc
->sc_txd
[i
].d_len
= 0;
761 sc
->sc_txcur
= sc
->sc_txnext
= 0;
763 /* Enable desired port */
764 wi_cmd(sc
, WI_CMD_ENABLE
| sc
->sc_portnum
, 0, 0, 0);
767 ifp
->if_flags
|= IFF_RUNNING
;
768 ifp
->if_flags
&= ~IFF_OACTIVE
;
769 if (ic
->ic_opmode
== IEEE80211_M_AHDEMO
||
770 ic
->ic_opmode
== IEEE80211_M_IBSS
||
771 ic
->ic_opmode
== IEEE80211_M_MONITOR
||
772 ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
773 ieee80211_create_ibss(ic
, ic
->ic_ibss_chan
);
775 /* Enable interrupts if not polling */
776 #ifdef DEVICE_POLLING
777 if ((ifp
->if_flags
& IFF_POLLING
) == 0)
779 CSR_WRITE_2(sc
, WI_INT_EN
, WI_INTRS
);
782 ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
783 sc
->sc_firmware_type
== WI_INTERSIL
) {
784 /* XXX: some card need to be re-enabled for hostap */
785 wi_cmd(sc
, WI_CMD_DISABLE
| WI_PORT0
, 0, 0, 0);
786 wi_cmd(sc
, WI_CMD_ENABLE
| WI_PORT0
, 0, 0, 0);
789 if (ic
->ic_opmode
== IEEE80211_M_STA
&&
790 ((ic
->ic_flags
& IEEE80211_F_DESBSSID
) ||
791 ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
)) {
792 memset(&join
, 0, sizeof(join
));
793 if (ic
->ic_flags
& IEEE80211_F_DESBSSID
)
794 IEEE80211_ADDR_COPY(&join
.wi_bssid
, ic
->ic_des_bssid
);
795 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
)
796 join
.wi_chan
= htole16(
797 ieee80211_chan2ieee(ic
, ic
->ic_des_chan
));
798 /* Lucent firmware does not support the JOIN RID. */
799 if (sc
->sc_firmware_type
!= WI_LUCENT
)
800 wi_write_rid(sc
, WI_RID_JOIN_REQ
, &join
, sizeof(join
));
805 if_printf(ifp
, "interface not running\n");
809 DPRINTF((ifp
, "wi_init: return %d\n", error
));
814 wi_stop(struct ifnet
*ifp
, int disable
)
816 struct ieee80211com
*ic
= (struct ieee80211com
*) ifp
;
817 struct wi_softc
*sc
= ifp
->if_softc
;
821 ieee80211_new_state(ic
, IEEE80211_S_INIT
, -1);
822 if (sc
->sc_enabled
&& !sc
->wi_gone
) {
823 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
824 wi_cmd(sc
, WI_CMD_DISABLE
| sc
->sc_portnum
, 0, 0, 0);
828 (*sc
->sc_disable
)(sc
);
832 } else if (sc
->wi_gone
&& disable
) /* gone --> not enabled */
836 sc
->sc_scan_timer
= 0;
837 sc
->sc_false_syns
= 0;
839 ifp
->if_flags
&= ~(IFF_OACTIVE
| IFF_RUNNING
);
844 wi_start(struct ifnet
*ifp
)
846 struct wi_softc
*sc
= ifp
->if_softc
;
847 struct ieee80211com
*ic
= &sc
->sc_ic
;
848 struct ieee80211_node
*ni
;
849 struct ieee80211_frame
*wh
;
851 struct wi_frame frmhdr
;
852 int cur
, fid
, off
, error
;
854 if (sc
->wi_gone
|| (sc
->sc_flags
& WI_FLAGS_OUTRANGE
)) {
855 ieee80211_drain_mgtq(&ic
->ic_mgtq
);
856 ifq_purge(&ifp
->if_snd
);
860 memset(&frmhdr
, 0, sizeof(frmhdr
));
863 IF_POLL(&ic
->ic_mgtq
, m0
);
865 if (sc
->sc_txd
[cur
].d_len
!= 0) {
866 ifp
->if_flags
|= IFF_OACTIVE
;
869 IF_DEQUEUE(&ic
->ic_mgtq
, m0
);
871 * Hack! The referenced node pointer is in the
872 * rcvif field of the packet header. This is
873 * placed there by ieee80211_mgmt_output because
874 * we need to hold the reference with the frame
875 * and there's no other way (other than packet
876 * tags which we consider too expensive to use)
879 ni
= (struct ieee80211_node
*) m0
->m_pkthdr
.rcvif
;
880 m0
->m_pkthdr
.rcvif
= NULL
;
882 m_copydata(m0
, 4, ETHER_ADDR_LEN
* 2,
883 (caddr_t
)&frmhdr
.wi_ehdr
);
884 frmhdr
.wi_ehdr
.ether_type
= 0;
885 wh
= mtod(m0
, struct ieee80211_frame
*);
887 struct ether_header
*eh
;
889 if (ic
->ic_state
!= IEEE80211_S_RUN
) {
890 ifq_purge(&ifp
->if_snd
);
894 if (sc
->sc_txd
[cur
].d_len
!= 0) {
895 ifp
->if_flags
|= IFF_OACTIVE
;
899 m0
= ifq_dequeue(&ifp
->if_snd
, NULL
);
903 if (m0
->m_len
< sizeof(struct ether_header
)) {
904 m0
= m_pullup(m0
, sizeof(struct ether_header
));
911 eh
= mtod(m0
, struct ether_header
*);
912 ni
= ieee80211_find_txnode(ic
, eh
->ether_dhost
);
920 m_copydata(m0
, 0, ETHER_HDR_LEN
,
921 (caddr_t
)&frmhdr
.wi_ehdr
);
924 m0
= ieee80211_encap(ic
, m0
, ni
);
926 ieee80211_free_node(ni
);
930 wh
= mtod(m0
, struct ieee80211_frame
*);
933 if (ic
->ic_rawbpf
!= NULL
)
934 bpf_mtap(ic
->ic_rawbpf
, m0
);
936 frmhdr
.wi_tx_ctl
= htole16(WI_ENC_TX_802_11
|WI_TXCNTL_TX_EX
);
937 /* XXX check key for SWCRYPT instead of using operating mode */
938 if ((wh
->i_fc
[1] & IEEE80211_FC1_WEP
) &&
939 (sc
->sc_encryption
& HOST_ENCRYPT
)) {
940 if (ieee80211_crypto_encap(ic
, ni
, m0
) == NULL
) {
941 ieee80211_free_node(ni
);
946 frmhdr
.wi_tx_ctl
|= htole16(WI_TXCNTL_NOCRYPT
);
950 sc
->sc_tx_th
.wt_rate
=
951 ni
->ni_rates
.rs_rates
[ni
->ni_txrate
];
952 bpf_ptap(sc
->sc_drvbpf
, m0
, &sc
->sc_tx_th
,
956 m_copydata(m0
, 0, sizeof(struct ieee80211_frame
),
957 (caddr_t
)&frmhdr
.wi_whdr
);
958 m_adj(m0
, sizeof(struct ieee80211_frame
));
959 frmhdr
.wi_dat_len
= htole16(m0
->m_pkthdr
.len
);
960 if (IFF_DUMPPKTS(ifp
))
961 wi_dump_pkt(&frmhdr
, NULL
, -1);
962 fid
= sc
->sc_txd
[cur
].d_fid
;
963 off
= sizeof(frmhdr
);
964 error
= wi_write_bap(sc
, fid
, 0, &frmhdr
, sizeof(frmhdr
)) != 0
965 || wi_mwrite_bap(sc
, fid
, off
, m0
, m0
->m_pkthdr
.len
) != 0;
967 ieee80211_free_node(ni
);
972 sc
->sc_txd
[cur
].d_len
= off
;
973 if (sc
->sc_txcur
== cur
) {
974 if (wi_cmd(sc
, WI_CMD_TX
| WI_RECLAIM
, fid
, 0, 0)) {
975 if_printf(ifp
, "xmit failed\n");
976 sc
->sc_txd
[cur
].d_len
= 0;
982 sc
->sc_txnext
= cur
= (cur
+ 1) % sc
->sc_ntxbuf
;
987 wi_reset(struct wi_softc
*sc
)
989 struct ieee80211com
*ic
= &sc
->sc_ic
;
990 struct ifnet
*ifp
= &ic
->ic_if
;
991 #define WI_INIT_TRIES 3
996 /* Symbol firmware cannot be initialized more than once */
997 if (sc
->sc_firmware_type
== WI_SYMBOL
&& sc
->sc_reset
)
999 if (sc
->sc_firmware_type
== WI_SYMBOL
)
1002 tries
= WI_INIT_TRIES
;
1004 for (i
= 0; i
< tries
; i
++) {
1005 if ((error
= wi_cmd(sc
, WI_CMD_INI
, 0, 0, 0)) == 0)
1007 DELAY(WI_DELAY
* 1000);
1012 if_printf(ifp
, "init failed\n");
1016 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
1017 CSR_WRITE_2(sc
, WI_EVENT_ACK
, 0xFFFF);
1019 /* Calibrate timer. */
1020 wi_write_val(sc
, WI_RID_TICK_TIME
, 8);
1023 #undef WI_INIT_TRIES
1027 wi_watchdog(struct ifnet
*ifp
)
1029 struct wi_softc
*sc
= ifp
->if_softc
;
1032 if (!sc
->sc_enabled
)
1035 if (sc
->sc_tx_timer
) {
1036 if (--sc
->sc_tx_timer
== 0) {
1037 if_printf(ifp
, "device timeout\n");
1039 wi_init(ifp
->if_softc
);
1045 if (sc
->sc_scan_timer
) {
1046 if (--sc
->sc_scan_timer
<= WI_SCAN_WAIT
- WI_SCAN_INQWAIT
&&
1047 sc
->sc_firmware_type
== WI_INTERSIL
) {
1048 DPRINTF((ifp
, "wi_watchdog: inquire scan\n"));
1049 wi_cmd(sc
, WI_CMD_INQUIRE
, WI_INFO_SCAN_RESULTS
, 0, 0);
1051 if (sc
->sc_scan_timer
)
1055 /* TODO: rate control */
1056 ieee80211_watchdog(&sc
->sc_ic
);
1060 wi_ioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
1062 struct wi_softc
*sc
= ifp
->if_softc
;
1063 struct ieee80211com
*ic
= &sc
->sc_ic
;
1064 struct ifreq
*ifr
= (struct ifreq
*)data
;
1065 struct ieee80211req
*ireq
;
1066 u_int8_t nodename
[IEEE80211_NWID_LEN
];
1078 * Can't do promisc and hostap at the same time. If all that's
1079 * changing is the promisc flag, try to short-circuit a call to
1080 * wi_init() by just setting PROMISC in the hardware.
1082 if (ifp
->if_flags
& IFF_UP
) {
1083 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
1084 ifp
->if_flags
& IFF_RUNNING
) {
1085 if (ifp
->if_flags
& IFF_PROMISC
&&
1086 !(sc
->sc_if_flags
& IFF_PROMISC
)) {
1087 wi_write_val(sc
, WI_RID_PROMISC
, 1);
1088 } else if (!(ifp
->if_flags
& IFF_PROMISC
) &&
1089 sc
->sc_if_flags
& IFF_PROMISC
) {
1090 wi_write_val(sc
, WI_RID_PROMISC
, 0);
1098 if (ifp
->if_flags
& IFF_RUNNING
) {
1103 sc
->sc_if_flags
= ifp
->if_flags
;
1108 error
= wi_write_multi(sc
);
1110 case SIOCGIFGENERIC
:
1111 error
= wi_get_cfg(ifp
, cmd
, data
, cr
);
1113 case SIOCSIFGENERIC
:
1114 error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
);
1117 error
= wi_set_cfg(ifp
, cmd
, data
);
1119 case SIOCGPRISM2DEBUG
:
1120 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
1123 if (!(ifp
->if_flags
& IFF_RUNNING
) ||
1124 sc
->sc_firmware_type
== WI_LUCENT
) {
1128 error
= wi_get_debug(sc
, &wreq
);
1130 error
= copyout(&wreq
, ifr
->ifr_data
, sizeof(wreq
));
1132 case SIOCSPRISM2DEBUG
:
1133 if ((error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
)))
1135 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
1138 error
= wi_set_debug(sc
, &wreq
);
1141 ireq
= (struct ieee80211req
*) data
;
1142 switch (ireq
->i_type
) {
1143 case IEEE80211_IOC_STATIONNAME
:
1144 ireq
->i_len
= sc
->sc_nodelen
+ 1;
1145 error
= copyout(sc
->sc_nodename
, ireq
->i_data
,
1149 error
= ieee80211_ioctl(ic
, cmd
, data
, cr
);
1154 error
= priv_check_cred(cr
, PRIV_ROOT
, NULL_CRED_OKAY
);
1157 ireq
= (struct ieee80211req
*) data
;
1158 switch (ireq
->i_type
) {
1159 case IEEE80211_IOC_STATIONNAME
:
1160 if (ireq
->i_val
!= 0 ||
1161 ireq
->i_len
> IEEE80211_NWID_LEN
) {
1165 memset(nodename
, 0, IEEE80211_NWID_LEN
);
1166 error
= copyin(ireq
->i_data
, nodename
, ireq
->i_len
);
1169 if (sc
->sc_enabled
) {
1170 error
= wi_write_ssid(sc
, WI_RID_NODENAME
,
1171 nodename
, ireq
->i_len
);
1175 memcpy(sc
->sc_nodename
, nodename
, IEEE80211_NWID_LEN
);
1176 sc
->sc_nodelen
= ireq
->i_len
;
1179 error
= ieee80211_ioctl(ic
, cmd
, data
, cr
);
1184 if (ifp
->if_flags
& IFF_RUNNING
)
1188 error
= ieee80211_ioctl(ic
, cmd
, data
, cr
);
1191 if (error
== ENETRESET
) {
1193 wi_init(sc
); /* XXX no error return */
1201 wi_media_change(struct ifnet
*ifp
)
1203 struct wi_softc
*sc
= ifp
->if_softc
;
1206 error
= ieee80211_media_change(ifp
);
1207 if (error
== ENETRESET
) {
1209 wi_init(sc
); /* XXX no error return */
1216 wi_media_status(struct ifnet
*ifp
, struct ifmediareq
*imr
)
1218 struct wi_softc
*sc
= ifp
->if_softc
;
1219 struct ieee80211com
*ic
= &sc
->sc_ic
;
1223 if (sc
->wi_gone
) { /* hardware gone (e.g. ejected) */
1224 imr
->ifm_active
= IFM_IEEE80211
| IFM_NONE
;
1225 imr
->ifm_status
= 0;
1229 imr
->ifm_status
= IFM_AVALID
;
1230 imr
->ifm_active
= IFM_IEEE80211
;
1231 if (!sc
->sc_enabled
) { /* port !enabled, have no status */
1232 imr
->ifm_active
|= IFM_NONE
;
1235 if (ic
->ic_state
== IEEE80211_S_RUN
&&
1236 (sc
->sc_flags
& WI_FLAGS_OUTRANGE
) == 0)
1237 imr
->ifm_status
|= IFM_ACTIVE
;
1239 if (wi_read_rid(sc
, WI_RID_CUR_TX_RATE
, &val
, &len
) == 0 &&
1240 len
== sizeof(val
)) {
1241 /* convert to 802.11 rate */
1244 if (sc
->sc_firmware_type
== WI_LUCENT
) {
1246 rate
= 11; /* 5.5Mbps */
1249 rate
= 11; /* 5.5Mbps */
1250 else if (rate
== 8*2)
1251 rate
= 22; /* 11Mbps */
1256 imr
->ifm_active
|= ieee80211_rate2media(ic
, rate
, IEEE80211_MODE_11B
);
1257 switch (ic
->ic_opmode
) {
1258 case IEEE80211_M_STA
:
1260 case IEEE80211_M_IBSS
:
1261 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
;
1263 case IEEE80211_M_AHDEMO
:
1264 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
| IFM_FLAG0
;
1266 case IEEE80211_M_HOSTAP
:
1267 imr
->ifm_active
|= IFM_IEEE80211_HOSTAP
;
1269 case IEEE80211_M_MONITOR
:
1270 imr
->ifm_active
|= IFM_IEEE80211_MONITOR
;
1276 wi_sync_bssid(struct wi_softc
*sc
, u_int8_t new_bssid
[IEEE80211_ADDR_LEN
])
1278 struct ieee80211com
*ic
= &sc
->sc_ic
;
1279 struct ieee80211_node
*ni
= ic
->ic_bss
;
1280 struct ifnet
*ifp
= &ic
->ic_if
;
1282 if (IEEE80211_ADDR_EQ(new_bssid
, ni
->ni_bssid
))
1285 DPRINTF((ifp
, "wi_sync_bssid: bssid %6D -> %6D ?\n", ni
->ni_bssid
, ":",
1288 /* In promiscuous mode, the BSSID field is not a reliable
1289 * indicator of the firmware's BSSID. Damp spurious
1290 * change-of-BSSID indications.
1292 if ((ifp
->if_flags
& IFF_PROMISC
) != 0 &&
1293 !ppsratecheck(&sc
->sc_last_syn
, &sc
->sc_false_syns
,
1297 sc
->sc_false_syns
= MAX(0, sc
->sc_false_syns
- 1);
1299 * XXX hack; we should create a new node with the new bssid
1300 * and replace the existing ic_bss with it but since we don't
1301 * process management frames to collect state we cheat by
1302 * reusing the existing node as we know wi_newstate will be
1303 * called and it will overwrite the node state.
1305 ieee80211_sta_join(ic
, ieee80211_ref_node(ni
));
1309 wi_rx_monitor(struct wi_softc
*sc
, int fid
)
1311 struct ieee80211com
*ic
= &sc
->sc_ic
;
1312 struct ifnet
*ifp
= &ic
->ic_if
;
1313 struct wi_frame
*rx_frame
;
1317 /* first allocate mbuf for packet storage */
1318 m
= m_getcl(MB_DONTWAIT
, MT_DATA
, 0);
1324 m
->m_pkthdr
.rcvif
= ifp
;
1326 /* now read wi_frame first so we know how much data to read */
1327 if (wi_read_bap(sc
, fid
, 0, mtod(m
, caddr_t
), sizeof(*rx_frame
))) {
1332 rx_frame
= mtod(m
, struct wi_frame
*);
1334 switch ((rx_frame
->wi_status
& WI_STAT_MAC_PORT
) >> 8) {
1336 switch (rx_frame
->wi_whdr
.i_fc
[0] & IEEE80211_FC0_TYPE_MASK
) {
1337 case IEEE80211_FC0_TYPE_DATA
:
1338 hdrlen
= WI_DATA_HDRLEN
;
1339 datlen
= rx_frame
->wi_dat_len
+ WI_FCS_LEN
;
1341 case IEEE80211_FC0_TYPE_MGT
:
1342 hdrlen
= WI_MGMT_HDRLEN
;
1343 datlen
= rx_frame
->wi_dat_len
+ WI_FCS_LEN
;
1345 case IEEE80211_FC0_TYPE_CTL
:
1347 * prism2 cards don't pass control packets
1348 * down properly or consistently, so we'll only
1349 * pass down the header.
1351 hdrlen
= WI_CTL_HDRLEN
;
1355 if_printf(ifp
, "received packet of unknown type "
1362 hdrlen
= WI_DATA_HDRLEN
;
1363 datlen
= rx_frame
->wi_dat_len
+ WI_FCS_LEN
;
1366 if_printf(ifp
, "received packet on invalid "
1367 "port (wi_status=0x%x)\n", rx_frame
->wi_status
);
1372 if (hdrlen
+ datlen
+ 2 > MCLBYTES
) {
1373 if_printf(ifp
, "oversized packet received "
1374 "(wi_dat_len=%d, wi_status=0x%x)\n",
1375 datlen
, rx_frame
->wi_status
);
1380 if (wi_read_bap(sc
, fid
, hdrlen
, mtod(m
, caddr_t
) + hdrlen
,
1382 m
->m_pkthdr
.len
= m
->m_len
= hdrlen
+ datlen
;
1384 BPF_MTAP(ifp
, m
); /* Handle BPF listeners. */
1392 wi_rx_intr(struct wi_softc
*sc
)
1394 struct ieee80211com
*ic
= &sc
->sc_ic
;
1395 struct ifnet
*ifp
= &ic
->ic_if
;
1396 struct wi_frame frmhdr
;
1398 struct ieee80211_frame
*wh
;
1399 struct ieee80211_node
*ni
;
1400 int fid
, len
, off
, rssi
;
1405 fid
= CSR_READ_2(sc
, WI_RX_FID
);
1407 if (sc
->wi_debug
.wi_monitor
) {
1409 * If we are in monitor mode just
1410 * read the data from the device.
1412 wi_rx_monitor(sc
, fid
);
1413 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_RX
);
1417 /* First read in the frame header */
1418 if (wi_read_bap(sc
, fid
, 0, &frmhdr
, sizeof(frmhdr
))) {
1419 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_RX
);
1421 DPRINTF((ifp
, "wi_rx_intr: read fid %x failed\n", fid
));
1425 if (IFF_DUMPPKTS(ifp
))
1426 wi_dump_pkt(&frmhdr
, NULL
, frmhdr
.wi_rx_signal
);
1429 * Drop undecryptable or packets with receive errors here
1431 status
= le16toh(frmhdr
.wi_status
);
1432 if (status
& WI_STAT_ERRSTAT
) {
1433 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_RX
);
1435 DPRINTF((ifp
, "wi_rx_intr: fid %x error status %x\n",
1439 rssi
= frmhdr
.wi_rx_signal
;
1440 rstamp
= (le16toh(frmhdr
.wi_rx_tstamp0
) << 16) |
1441 le16toh(frmhdr
.wi_rx_tstamp1
);
1443 len
= le16toh(frmhdr
.wi_dat_len
);
1444 off
= ALIGN(sizeof(struct ieee80211_frame
));
1447 * Sometimes the PRISM2.x returns bogusly large frames. Except
1448 * in monitor mode, just throw them away.
1450 if (off
+ len
> MCLBYTES
) {
1451 if (ic
->ic_opmode
!= IEEE80211_M_MONITOR
) {
1452 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_RX
);
1454 DPRINTF((ifp
, "wi_rx_intr: oversized packet\n"));
1460 m
= m_getl(off
+ len
, MB_DONTWAIT
, MT_DATA
, M_PKTHDR
, NULL
);
1462 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_RX
);
1464 DPRINTF((ifp
, "wi_rx_intr: m_getl failed\n"));
1468 m
->m_data
+= off
- sizeof(struct ieee80211_frame
);
1469 memcpy(m
->m_data
, &frmhdr
.wi_whdr
, sizeof(struct ieee80211_frame
));
1470 wi_read_bap(sc
, fid
, sizeof(frmhdr
),
1471 m
->m_data
+ sizeof(struct ieee80211_frame
), len
);
1472 m
->m_pkthdr
.len
= m
->m_len
= sizeof(struct ieee80211_frame
) + len
;
1473 m
->m_pkthdr
.rcvif
= ifp
;
1475 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_RX
);
1477 wh
= mtod(m
, struct ieee80211_frame
*);
1478 if (wh
->i_fc
[1] & IEEE80211_FC1_WEP
) {
1480 * WEP is decrypted by hardware and the IV
1481 * is stripped. Clear WEP bit so we don't
1482 * try to process it in ieee80211_input.
1483 * XXX fix for TKIP, et. al.
1485 wh
->i_fc
[1] &= ~IEEE80211_FC1_WEP
;
1488 if (sc
->sc_drvbpf
) {
1489 /* XXX replace divide by table */
1490 sc
->sc_rx_th
.wr_rate
= frmhdr
.wi_rx_rate
/ 5;
1491 sc
->sc_rx_th
.wr_antsignal
= frmhdr
.wi_rx_signal
;
1492 sc
->sc_rx_th
.wr_antnoise
= frmhdr
.wi_rx_silence
;
1493 sc
->sc_rx_th
.wr_flags
= 0;
1494 if (frmhdr
.wi_status
& WI_STAT_PCF
)
1495 sc
->sc_rx_th
.wr_flags
|= IEEE80211_RADIOTAP_F_CFP
;
1496 bpf_ptap(sc
->sc_drvbpf
, m
, &sc
->sc_rx_th
, sc
->sc_rx_th_len
);
1499 /* synchronize driver's BSSID with firmware's BSSID */
1500 dir
= wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
;
1501 if (ic
->ic_opmode
== IEEE80211_M_IBSS
&& dir
== IEEE80211_FC1_DIR_NODS
)
1502 wi_sync_bssid(sc
, wh
->i_addr3
);
1505 * Locate the node for sender, track state, and
1506 * then pass this node (referenced) up to the 802.11
1507 * layer for its use.
1509 ni
= ieee80211_find_rxnode(ic
, (struct ieee80211_frame_min
*) wh
);
1511 * Send frame up for processing.
1513 ieee80211_input(ic
, m
, ni
, rssi
, rstamp
);
1515 * The frame may have caused the node to be marked for
1516 * reclamation (e.g. in response to a DEAUTH message)
1517 * so use free_node here instead of unref_node.
1519 ieee80211_free_node(ni
);
1523 wi_tx_ex_intr(struct wi_softc
*sc
)
1525 struct ieee80211com
*ic
= &sc
->sc_ic
;
1526 struct ifnet
*ifp
= &ic
->ic_if
;
1527 struct wi_frame frmhdr
;
1530 fid
= CSR_READ_2(sc
, WI_TX_CMP_FID
);
1531 /* Read in the frame header */
1532 if (wi_read_bap(sc
, fid
, 0, &frmhdr
, sizeof(frmhdr
)) == 0) {
1533 u_int16_t status
= le16toh(frmhdr
.wi_status
);
1536 * Spontaneous station disconnects appear as xmit
1537 * errors. Don't announce them and/or count them
1538 * as an output error.
1540 if ((status
& WI_TXSTAT_DISCONNECT
) == 0) {
1541 if (ppsratecheck(&lasttxerror
, &curtxeps
, wi_txerate
)) {
1542 if_printf(ifp
, "tx failed");
1543 if (status
& WI_TXSTAT_RET_ERR
)
1544 kprintf(", retry limit exceeded");
1545 if (status
& WI_TXSTAT_AGED_ERR
)
1546 kprintf(", max transmit lifetime exceeded");
1547 if (status
& WI_TXSTAT_DISCONNECT
)
1548 kprintf(", port disconnected");
1549 if (status
& WI_TXSTAT_FORM_ERR
)
1550 kprintf(", invalid format (data len %u src %6D)",
1551 le16toh(frmhdr
.wi_dat_len
),
1552 frmhdr
.wi_ehdr
.ether_shost
, ":");
1554 kprintf(", status=0x%x", status
);
1559 DPRINTF((ifp
, "port disconnected\n"));
1560 ifp
->if_collisions
++; /* XXX */
1563 DPRINTF((ifp
, "wi_tx_ex_intr: read fid %x failed\n", fid
));
1564 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_TX_EXC
);
1568 wi_tx_intr(struct wi_softc
*sc
)
1570 struct ieee80211com
*ic
= &sc
->sc_ic
;
1571 struct ifnet
*ifp
= &ic
->ic_if
;
1577 fid
= CSR_READ_2(sc
, WI_ALLOC_FID
);
1578 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_ALLOC
);
1581 if (sc
->sc_txd
[cur
].d_fid
!= fid
) {
1582 if_printf(ifp
, "bad alloc %x != %x, cur %d nxt %d\n",
1583 fid
, sc
->sc_txd
[cur
].d_fid
, cur
, sc
->sc_txnext
);
1586 sc
->sc_tx_timer
= 0;
1587 sc
->sc_txd
[cur
].d_len
= 0;
1588 sc
->sc_txcur
= cur
= (cur
+ 1) % sc
->sc_ntxbuf
;
1589 if (sc
->sc_txd
[cur
].d_len
== 0)
1590 ifp
->if_flags
&= ~IFF_OACTIVE
;
1592 if (wi_cmd(sc
, WI_CMD_TX
| WI_RECLAIM
, sc
->sc_txd
[cur
].d_fid
,
1594 if_printf(ifp
, "xmit failed\n");
1595 sc
->sc_txd
[cur
].d_len
= 0;
1597 sc
->sc_tx_timer
= 5;
1604 wi_info_intr(struct wi_softc
*sc
)
1606 struct ieee80211com
*ic
= &sc
->sc_ic
;
1607 struct ifnet
*ifp
= &ic
->ic_if
;
1608 int i
, fid
, len
, off
;
1613 fid
= CSR_READ_2(sc
, WI_INFO_FID
);
1614 wi_read_bap(sc
, fid
, 0, ltbuf
, sizeof(ltbuf
));
1616 switch (le16toh(ltbuf
[1])) {
1618 case WI_INFO_LINK_STAT
:
1619 wi_read_bap(sc
, fid
, sizeof(ltbuf
), &stat
, sizeof(stat
));
1620 DPRINTF((ifp
, "wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat
)));
1621 switch (le16toh(stat
)) {
1622 case WI_INFO_LINK_STAT_CONNECTED
:
1623 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
1624 if (ic
->ic_state
== IEEE80211_S_RUN
&&
1625 ic
->ic_opmode
!= IEEE80211_M_IBSS
)
1628 case WI_INFO_LINK_STAT_AP_CHG
:
1629 ieee80211_new_state(ic
, IEEE80211_S_RUN
, -1);
1631 case WI_INFO_LINK_STAT_AP_INR
:
1632 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
1634 case WI_INFO_LINK_STAT_AP_OOR
:
1635 if (sc
->sc_firmware_type
== WI_SYMBOL
&&
1636 sc
->sc_scan_timer
> 0) {
1637 if (wi_cmd(sc
, WI_CMD_INQUIRE
,
1638 WI_INFO_HOST_SCAN_RESULTS
, 0, 0) != 0)
1639 sc
->sc_scan_timer
= 0;
1642 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1643 sc
->sc_flags
|= WI_FLAGS_OUTRANGE
;
1645 case WI_INFO_LINK_STAT_DISCONNECTED
:
1646 case WI_INFO_LINK_STAT_ASSOC_FAILED
:
1647 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1648 ieee80211_new_state(ic
, IEEE80211_S_INIT
, -1);
1653 case WI_INFO_COUNTERS
:
1654 /* some card versions have a larger stats structure */
1655 len
= min(le16toh(ltbuf
[0]) - 1, sizeof(sc
->sc_stats
) / 4);
1656 ptr
= (u_int32_t
*)&sc
->sc_stats
;
1657 off
= sizeof(ltbuf
);
1658 for (i
= 0; i
< len
; i
++, off
+= 2, ptr
++) {
1659 wi_read_bap(sc
, fid
, off
, &stat
, sizeof(stat
));
1660 #ifdef WI_HERMES_STATS_WAR
1666 ifp
->if_collisions
= sc
->sc_stats
.wi_tx_single_retries
+
1667 sc
->sc_stats
.wi_tx_multi_retries
+
1668 sc
->sc_stats
.wi_tx_retry_limit
;
1671 case WI_INFO_SCAN_RESULTS
:
1672 case WI_INFO_HOST_SCAN_RESULTS
:
1673 wi_scan_result(sc
, fid
, le16toh(ltbuf
[0]));
1677 DPRINTF((ifp
, "wi_info_intr: got fid %x type %x len %d\n", fid
,
1678 le16toh(ltbuf
[1]), le16toh(ltbuf
[0])));
1681 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_INFO
);
1685 wi_write_multi(struct wi_softc
*sc
)
1687 struct ifnet
*ifp
= &sc
->sc_ic
.ic_if
;
1689 struct ifmultiaddr
*ifma
;
1690 struct wi_mcast mlist
;
1692 if (ifp
->if_flags
& IFF_ALLMULTI
|| ifp
->if_flags
& IFF_PROMISC
) {
1694 memset(&mlist
, 0, sizeof(mlist
));
1695 return wi_write_rid(sc
, WI_RID_MCAST_LIST
, &mlist
,
1700 LIST_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
1701 if (ifma
->ifma_addr
->sa_family
!= AF_LINK
)
1705 IEEE80211_ADDR_COPY(&mlist
.wi_mcast
[n
],
1706 (LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
)));
1709 return wi_write_rid(sc
, WI_RID_MCAST_LIST
, &mlist
,
1710 IEEE80211_ADDR_LEN
* n
);
1714 wi_read_nicid(struct wi_softc
*sc
)
1716 struct wi_card_ident
*id
;
1721 /* getting chip identity */
1722 memset(ver
, 0, sizeof(ver
));
1724 wi_read_rid(sc
, WI_RID_CARD_ID
, ver
, &len
);
1725 if_printf(&sc
->sc_ic
.ic_if
, "using ");
1727 sc
->sc_firmware_type
= WI_NOTYPE
;
1728 for (id
= wi_card_ident
; id
->card_name
!= NULL
; id
++) {
1729 if (le16toh(ver
[0]) == id
->card_id
) {
1730 kprintf("%s", id
->card_name
);
1731 sc
->sc_firmware_type
= id
->firm_type
;
1735 if (sc
->sc_firmware_type
== WI_NOTYPE
) {
1736 if (le16toh(ver
[0]) & 0x8000) {
1737 kprintf("Unknown PRISM2 chip");
1738 sc
->sc_firmware_type
= WI_INTERSIL
;
1740 kprintf("Unknown Lucent chip");
1741 sc
->sc_firmware_type
= WI_LUCENT
;
1745 /* get primary firmware version (Only Prism chips) */
1746 if (sc
->sc_firmware_type
!= WI_LUCENT
) {
1747 memset(ver
, 0, sizeof(ver
));
1749 wi_read_rid(sc
, WI_RID_PRI_IDENTITY
, ver
, &len
);
1750 sc
->sc_pri_firmware_ver
= le16toh(ver
[2]) * 10000 +
1751 le16toh(ver
[3]) * 100 + le16toh(ver
[1]);
1754 /* get station firmware version */
1755 memset(ver
, 0, sizeof(ver
));
1757 wi_read_rid(sc
, WI_RID_STA_IDENTITY
, ver
, &len
);
1758 sc
->sc_sta_firmware_ver
= le16toh(ver
[2]) * 10000 +
1759 le16toh(ver
[3]) * 100 + le16toh(ver
[1]);
1760 if (sc
->sc_firmware_type
== WI_INTERSIL
&&
1761 (sc
->sc_sta_firmware_ver
== 10102 ||
1762 sc
->sc_sta_firmware_ver
== 20102)) {
1764 memset(ident
, 0, sizeof(ident
));
1765 len
= sizeof(ident
);
1766 /* value should be the format like "V2.00-11" */
1767 if (wi_read_rid(sc
, WI_RID_SYMBOL_IDENTITY
, ident
, &len
) == 0 &&
1768 *(p
= (char *)ident
) >= 'A' &&
1769 p
[2] == '.' && p
[5] == '-' && p
[8] == '\0') {
1770 sc
->sc_firmware_type
= WI_SYMBOL
;
1771 sc
->sc_sta_firmware_ver
= (p
[1] - '0') * 10000 +
1772 (p
[3] - '0') * 1000 + (p
[4] - '0') * 100 +
1773 (p
[6] - '0') * 10 + (p
[7] - '0');
1777 if_printf(&sc
->sc_ic
.ic_if
, "%s Firmware: ",
1778 sc
->sc_firmware_type
== WI_LUCENT
? "Lucent" :
1779 (sc
->sc_firmware_type
== WI_SYMBOL
? "Symbol" : "Intersil"));
1780 if (sc
->sc_firmware_type
!= WI_LUCENT
) /* XXX */
1781 kprintf("Primary (%u.%u.%u), ",
1782 sc
->sc_pri_firmware_ver
/ 10000,
1783 (sc
->sc_pri_firmware_ver
% 10000) / 100,
1784 sc
->sc_pri_firmware_ver
% 100);
1785 kprintf("Station (%u.%u.%u)\n",
1786 sc
->sc_sta_firmware_ver
/ 10000,
1787 (sc
->sc_sta_firmware_ver
% 10000) / 100,
1788 sc
->sc_sta_firmware_ver
% 100);
1792 wi_write_ssid(struct wi_softc
*sc
, int rid
, u_int8_t
*buf
, int buflen
)
1794 struct wi_ssid ssid
;
1796 if (buflen
> IEEE80211_NWID_LEN
)
1798 memset(&ssid
, 0, sizeof(ssid
));
1799 ssid
.wi_len
= htole16(buflen
);
1800 memcpy(ssid
.wi_ssid
, buf
, buflen
);
1801 return wi_write_rid(sc
, rid
, &ssid
, sizeof(ssid
));
1805 wi_get_cfg(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
1807 struct wi_softc
*sc
= ifp
->if_softc
;
1808 struct ieee80211com
*ic
= &sc
->sc_ic
;
1809 struct ifreq
*ifr
= (struct ifreq
*)data
;
1811 struct wi_scan_res
*res
;
1813 int len
, n
, error
, mif
, val
, off
, i
;
1815 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
1818 len
= (wreq
.wi_len
- 1) * 2;
1819 if (len
< sizeof(u_int16_t
))
1821 if (len
> sizeof(wreq
.wi_val
))
1822 len
= sizeof(wreq
.wi_val
);
1824 switch (wreq
.wi_type
) {
1826 case WI_RID_IFACE_STATS
:
1827 memcpy(wreq
.wi_val
, &sc
->sc_stats
, sizeof(sc
->sc_stats
));
1828 if (len
< sizeof(sc
->sc_stats
))
1831 len
= sizeof(sc
->sc_stats
);
1834 case WI_RID_ENCRYPTION
:
1835 case WI_RID_TX_CRYPT_KEY
:
1836 case WI_RID_DEFLT_CRYPT_KEYS
:
1837 case WI_RID_TX_RATE
:
1838 return ieee80211_cfgget(ic
, cmd
, data
, cr
);
1840 case WI_RID_MICROWAVE_OVEN
:
1841 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_MOR
)) {
1842 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
1846 wreq
.wi_val
[0] = htole16(sc
->sc_microwave_oven
);
1847 len
= sizeof(u_int16_t
);
1850 case WI_RID_DBM_ADJUST
:
1851 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_DBMADJUST
)) {
1852 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
1856 wreq
.wi_val
[0] = htole16(sc
->sc_dbm_offset
);
1857 len
= sizeof(u_int16_t
);
1860 case WI_RID_ROAMING_MODE
:
1861 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_ROAMING
)) {
1862 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
1866 wreq
.wi_val
[0] = htole16(sc
->sc_roaming_mode
);
1867 len
= sizeof(u_int16_t
);
1870 case WI_RID_SYSTEM_SCALE
:
1871 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_SYSSCALE
)) {
1872 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
1876 wreq
.wi_val
[0] = htole16(sc
->sc_system_scale
);
1877 len
= sizeof(u_int16_t
);
1880 case WI_RID_FRAG_THRESH
:
1881 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_FRAGTHR
)) {
1882 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
1886 wreq
.wi_val
[0] = htole16(ic
->ic_fragthreshold
);
1887 len
= sizeof(u_int16_t
);
1890 case WI_RID_READ_APS
:
1891 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
1892 return ieee80211_cfgget(ic
, cmd
, data
, cr
);
1893 if (sc
->sc_scan_timer
> 0) {
1894 error
= EINPROGRESS
;
1898 if (len
< sizeof(n
)) {
1902 if (len
< sizeof(n
) + sizeof(struct wi_apinfo
) * n
)
1903 n
= (len
- sizeof(n
)) / sizeof(struct wi_apinfo
);
1904 len
= sizeof(n
) + sizeof(struct wi_apinfo
) * n
;
1905 memcpy(wreq
.wi_val
, &n
, sizeof(n
));
1906 memcpy((caddr_t
)wreq
.wi_val
+ sizeof(n
), sc
->sc_aps
,
1907 sizeof(struct wi_apinfo
) * n
);
1911 wreq
.wi_val
[0] = sc
->sc_firmware_type
!= WI_LUCENT
;
1912 len
= sizeof(u_int16_t
);
1916 mif
= wreq
.wi_val
[0];
1917 error
= wi_cmd(sc
, WI_CMD_READMIF
, mif
, 0, 0);
1918 val
= CSR_READ_2(sc
, WI_RESP0
);
1919 wreq
.wi_val
[0] = val
;
1920 len
= sizeof(u_int16_t
);
1923 case WI_RID_ZERO_CACHE
:
1924 case WI_RID_PROCFRAME
: /* ignore for compatibility */
1928 case WI_RID_READ_CACHE
:
1929 return ieee80211_cfgget(ic
, cmd
, data
, cr
);
1931 case WI_RID_SCAN_RES
: /* compatibility interface */
1932 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
1933 return ieee80211_cfgget(ic
, cmd
, data
, cr
);
1934 if (sc
->sc_scan_timer
> 0) {
1935 error
= EINPROGRESS
;
1939 if (sc
->sc_firmware_type
== WI_LUCENT
) {
1941 reslen
= WI_WAVELAN_RES_SIZE
;
1943 off
= sizeof(struct wi_scan_p2_hdr
);
1944 reslen
= WI_PRISM2_RES_SIZE
;
1946 if (len
< off
+ reslen
* n
)
1947 n
= (len
- off
) / reslen
;
1948 len
= off
+ reslen
* n
;
1950 struct wi_scan_p2_hdr
*p2
;
1952 * Prepend Prism-specific header.
1954 if (len
< sizeof(struct wi_scan_p2_hdr
)) {
1958 p2
= (struct wi_scan_p2_hdr
*)wreq
.wi_val
;
1960 p2
->wi_reason
= n
; /* XXX */
1962 for (i
= 0; i
< n
; i
++, off
+= reslen
) {
1963 const struct wi_apinfo
*ap
= &sc
->sc_aps
[i
];
1965 res
= (struct wi_scan_res
*)((char *)wreq
.wi_val
+ off
);
1966 res
->wi_chan
= ap
->channel
;
1967 res
->wi_noise
= ap
->noise
;
1968 res
->wi_signal
= ap
->signal
;
1969 IEEE80211_ADDR_COPY(res
->wi_bssid
, ap
->bssid
);
1970 res
->wi_interval
= ap
->interval
;
1971 res
->wi_capinfo
= ap
->capinfo
;
1972 res
->wi_ssid_len
= ap
->namelen
;
1973 memcpy(res
->wi_ssid
, ap
->name
,
1974 IEEE80211_NWID_LEN
);
1975 if (sc
->sc_firmware_type
!= WI_LUCENT
) {
1976 /* XXX not saved from Prism cards */
1977 memset(res
->wi_srates
, 0,
1978 sizeof(res
->wi_srates
));
1979 res
->wi_rate
= ap
->rate
;
1986 if (sc
->sc_enabled
) {
1987 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
1991 switch (wreq
.wi_type
) {
1992 case WI_RID_MAX_DATALEN
:
1993 wreq
.wi_val
[0] = htole16(sc
->sc_max_datalen
);
1994 len
= sizeof(u_int16_t
);
1996 case WI_RID_RTS_THRESH
:
1997 wreq
.wi_val
[0] = htole16(ic
->ic_rtsthreshold
);
1998 len
= sizeof(u_int16_t
);
2000 case WI_RID_CNFAUTHMODE
:
2001 wreq
.wi_val
[0] = htole16(sc
->sc_cnfauthmode
);
2002 len
= sizeof(u_int16_t
);
2004 case WI_RID_NODENAME
:
2005 if (len
< sc
->sc_nodelen
+ sizeof(u_int16_t
)) {
2009 len
= sc
->sc_nodelen
+ sizeof(u_int16_t
);
2010 wreq
.wi_val
[0] = htole16((sc
->sc_nodelen
+ 1) / 2);
2011 memcpy(&wreq
.wi_val
[1], sc
->sc_nodename
,
2015 return ieee80211_cfgget(ic
, cmd
, data
, cr
);
2021 wreq
.wi_len
= (len
+ 1) / 2 + 1;
2022 return copyout(&wreq
, ifr
->ifr_data
, (wreq
.wi_len
+ 1) * 2);
2026 wi_set_cfg(struct ifnet
*ifp
, u_long cmd
, caddr_t data
)
2028 struct wi_softc
*sc
= ifp
->if_softc
;
2029 struct ieee80211com
*ic
= &sc
->sc_ic
;
2030 struct ifreq
*ifr
= (struct ifreq
*)data
;
2033 int i
, len
, error
, mif
, val
;
2034 struct ieee80211_rateset
*rs
;
2036 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
2039 len
= wreq
.wi_len
? (wreq
.wi_len
- 1) * 2 : 0;
2040 switch (wreq
.wi_type
) {
2041 case WI_RID_DBM_ADJUST
:
2044 case WI_RID_NODENAME
:
2045 if (le16toh(wreq
.wi_val
[0]) * 2 > len
||
2046 le16toh(wreq
.wi_val
[0]) > sizeof(sc
->sc_nodename
)) {
2050 if (sc
->sc_enabled
) {
2051 error
= wi_write_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2056 sc
->sc_nodelen
= le16toh(wreq
.wi_val
[0]) * 2;
2057 memcpy(sc
->sc_nodename
, &wreq
.wi_val
[1], sc
->sc_nodelen
);
2060 case WI_RID_MICROWAVE_OVEN
:
2061 case WI_RID_ROAMING_MODE
:
2062 case WI_RID_SYSTEM_SCALE
:
2063 case WI_RID_FRAG_THRESH
:
2064 if (wreq
.wi_type
== WI_RID_MICROWAVE_OVEN
&&
2065 (sc
->sc_flags
& WI_FLAGS_HAS_MOR
) == 0)
2067 if (wreq
.wi_type
== WI_RID_ROAMING_MODE
&&
2068 (sc
->sc_flags
& WI_FLAGS_HAS_ROAMING
) == 0)
2070 if (wreq
.wi_type
== WI_RID_SYSTEM_SCALE
&&
2071 (sc
->sc_flags
& WI_FLAGS_HAS_SYSSCALE
) == 0)
2073 if (wreq
.wi_type
== WI_RID_FRAG_THRESH
&&
2074 (sc
->sc_flags
& WI_FLAGS_HAS_FRAGTHR
) == 0)
2077 case WI_RID_RTS_THRESH
:
2078 case WI_RID_CNFAUTHMODE
:
2079 case WI_RID_MAX_DATALEN
:
2080 if (sc
->sc_enabled
) {
2081 error
= wi_write_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2086 switch (wreq
.wi_type
) {
2087 case WI_RID_FRAG_THRESH
:
2088 ic
->ic_fragthreshold
= le16toh(wreq
.wi_val
[0]);
2090 case WI_RID_RTS_THRESH
:
2091 ic
->ic_rtsthreshold
= le16toh(wreq
.wi_val
[0]);
2093 case WI_RID_MICROWAVE_OVEN
:
2094 sc
->sc_microwave_oven
= le16toh(wreq
.wi_val
[0]);
2096 case WI_RID_ROAMING_MODE
:
2097 sc
->sc_roaming_mode
= le16toh(wreq
.wi_val
[0]);
2099 case WI_RID_SYSTEM_SCALE
:
2100 sc
->sc_system_scale
= le16toh(wreq
.wi_val
[0]);
2102 case WI_RID_CNFAUTHMODE
:
2103 sc
->sc_cnfauthmode
= le16toh(wreq
.wi_val
[0]);
2105 case WI_RID_MAX_DATALEN
:
2106 sc
->sc_max_datalen
= le16toh(wreq
.wi_val
[0]);
2111 case WI_RID_TX_RATE
:
2112 switch (le16toh(wreq
.wi_val
[0])) {
2114 ic
->ic_fixed_rate
= IEEE80211_FIXED_RATE_NONE
;
2117 rs
= &ic
->ic_sup_rates
[IEEE80211_MODE_11B
];
2118 for (i
= 0; i
< rs
->rs_nrates
; i
++) {
2119 if ((rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
)
2120 / 2 == le16toh(wreq
.wi_val
[0]))
2123 if (i
== rs
->rs_nrates
)
2125 ic
->ic_fixed_rate
= i
;
2128 error
= wi_write_txrate(sc
);
2131 case WI_RID_SCAN_APS
:
2132 if (sc
->sc_enabled
&& ic
->ic_opmode
!= IEEE80211_M_HOSTAP
)
2133 error
= wi_scan_ap(sc
, 0x3fff, 0x000f);
2136 case WI_RID_SCAN_REQ
: /* compatibility interface */
2137 if (sc
->sc_enabled
&& ic
->ic_opmode
!= IEEE80211_M_HOSTAP
)
2138 error
= wi_scan_ap(sc
, wreq
.wi_val
[0], wreq
.wi_val
[1]);
2141 case WI_RID_MGMT_XMIT
:
2142 if (!sc
->sc_enabled
) {
2146 if (ic
->ic_mgtq
.ifq_len
> 5) {
2150 /* XXX wi_len looks in u_int8_t, not in u_int16_t */
2151 m
= m_devget((char *)&wreq
.wi_val
, wreq
.wi_len
, 0, ifp
, NULL
);
2156 IF_ENQUEUE(&ic
->ic_mgtq
, m
);
2160 mif
= wreq
.wi_val
[0];
2161 val
= wreq
.wi_val
[1];
2162 error
= wi_cmd(sc
, WI_CMD_WRITEMIF
, mif
, val
, 0);
2165 case WI_RID_PROCFRAME
: /* ignore for compatibility */
2168 case WI_RID_OWN_SSID
:
2169 if (le16toh(wreq
.wi_val
[0]) * 2 > len
||
2170 le16toh(wreq
.wi_val
[0]) > IEEE80211_NWID_LEN
) {
2174 memset(ic
->ic_des_essid
, 0, IEEE80211_NWID_LEN
);
2175 ic
->ic_des_esslen
= le16toh(wreq
.wi_val
[0]) * 2;
2176 memcpy(ic
->ic_des_essid
, &wreq
.wi_val
[1], ic
->ic_des_esslen
);
2181 if (sc
->sc_enabled
) {
2182 error
= wi_write_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2187 error
= ieee80211_cfgset(ic
, cmd
, data
);
2194 wi_write_txrate(struct wi_softc
*sc
)
2196 struct ieee80211com
*ic
= &sc
->sc_ic
;
2200 if (ic
->ic_fixed_rate
== IEEE80211_FIXED_RATE_NONE
)
2201 rate
= 0; /* auto */
2203 rate
= (ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_rates
[ic
->ic_fixed_rate
] &
2204 IEEE80211_RATE_VAL
) / 2;
2206 /* rate: 0, 1, 2, 5, 11 */
2208 switch (sc
->sc_firmware_type
) {
2211 case 0: /* auto == 11mbps auto */
2214 /* case 1, 2 map to 1, 2*/
2215 case 5: /* 5.5Mbps -> 4 */
2218 case 11: /* 11mbps -> 5 */
2226 /* Choose a bit according to this table.
2229 * ----+-------------------
2235 for (i
= 8; i
> 0; i
>>= 1) {
2240 rate
= 0xf; /* auto */
2245 return wi_write_val(sc
, WI_RID_TX_RATE
, rate
);
2249 wi_key_alloc(struct ieee80211com
*ic
, const struct ieee80211_key
*k
,
2250 ieee80211_keyix
*keyix
, ieee80211_keyix
*rxkeyix
)
2252 struct wi_softc
*sc
= ic
->ic_ifp
->if_softc
;
2255 * When doing host encryption of outbound frames fail requests
2256 * for keys that are not marked w/ the SWCRYPT flag so the
2257 * net80211 layer falls back to s/w crypto. Note that we also
2258 * fixup existing keys below to handle mode changes.
2260 if ((sc
->sc_encryption
& HOST_ENCRYPT
) &&
2261 (k
->wk_flags
& IEEE80211_KEY_SWCRYPT
) == 0)
2263 return sc
->sc_key_alloc(ic
, k
, keyix
, rxkeyix
);
2267 wi_write_wep(struct wi_softc
*sc
)
2269 struct ieee80211com
*ic
= &sc
->sc_ic
;
2273 struct wi_key wkey
[IEEE80211_WEP_NKID
];
2275 switch (sc
->sc_firmware_type
) {
2277 val
= (ic
->ic_flags
& IEEE80211_F_PRIVACY
) ? 1 : 0;
2278 error
= wi_write_val(sc
, WI_RID_ENCRYPTION
, val
);
2281 if (!(ic
->ic_flags
& IEEE80211_F_PRIVACY
))
2283 error
= wi_write_val(sc
, WI_RID_TX_CRYPT_KEY
, ic
->ic_def_txkey
);
2286 memset(wkey
, 0, sizeof(wkey
));
2287 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
2288 keylen
= ic
->ic_nw_keys
[i
].wk_keylen
;
2289 wkey
[i
].wi_keylen
= htole16(keylen
);
2290 memcpy(wkey
[i
].wi_keydat
, ic
->ic_nw_keys
[i
].wk_key
,
2293 error
= wi_write_rid(sc
, WI_RID_DEFLT_CRYPT_KEYS
,
2294 wkey
, sizeof(wkey
));
2295 sc
->sc_encryption
= 0;
2300 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
) {
2302 * ONLY HWB3163 EVAL-CARD Firmware version
2303 * less than 0.8 variant2
2305 * If promiscuous mode disable, Prism2 chip
2306 * does not work with WEP .
2307 * It is under investigation for details.
2308 * (ichiro@netbsd.org)
2310 if (sc
->sc_firmware_type
== WI_INTERSIL
&&
2311 sc
->sc_sta_firmware_ver
< 802 ) {
2312 /* firm ver < 0.8 variant 2 */
2313 wi_write_val(sc
, WI_RID_PROMISC
, 1);
2315 wi_write_val(sc
, WI_RID_CNFAUTHMODE
,
2316 sc
->sc_cnfauthmode
);
2317 /* XXX should honor IEEE80211_F_DROPUNENC */
2318 val
= PRIVACY_INVOKED
| EXCLUDE_UNENCRYPTED
;
2320 * Encryption firmware has a bug for HostAP mode.
2322 if (sc
->sc_firmware_type
== WI_INTERSIL
&&
2323 ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
2324 val
|= HOST_ENCRYPT
;
2326 wi_write_val(sc
, WI_RID_CNFAUTHMODE
,
2327 IEEE80211_AUTH_OPEN
);
2328 val
= HOST_ENCRYPT
| HOST_DECRYPT
;
2330 error
= wi_write_val(sc
, WI_RID_P2_ENCRYPTION
, val
);
2333 sc
->sc_encryption
= val
;
2334 if ((val
& PRIVACY_INVOKED
) == 0)
2336 error
= wi_write_val(sc
, WI_RID_P2_TX_CRYPT_KEY
,
2340 if (val
& HOST_DECRYPT
)
2343 * It seems that the firmware accept 104bit key only if
2344 * all the keys have 104bit length. We get the length of
2345 * the transmit key and use it for all other keys.
2346 * Perhaps we should use software WEP for such situation.
2348 if (ic
->ic_def_txkey
!= IEEE80211_KEYIX_NONE
)
2349 keylen
= ic
->ic_nw_keys
[ic
->ic_def_txkey
].wk_keylen
;
2350 else /* XXX should not hapen */
2351 keylen
= IEEE80211_WEP_KEYLEN
;
2352 if (keylen
> IEEE80211_WEP_KEYLEN
)
2353 keylen
= 13; /* 104bit keys */
2355 keylen
= IEEE80211_WEP_KEYLEN
;
2356 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
2357 error
= wi_write_rid(sc
, WI_RID_P2_CRYPT_KEY0
+ i
,
2358 ic
->ic_nw_keys
[i
].wk_key
, keylen
);
2365 * XXX horrible hack; insure pre-existing keys are
2366 * setup properly to do s/w crypto.
2368 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
2369 struct ieee80211_key
*k
= &ic
->ic_nw_keys
[i
];
2370 if (k
->wk_flags
& IEEE80211_KEY_XMIT
) {
2371 if (sc
->sc_encryption
& HOST_ENCRYPT
)
2372 k
->wk_flags
|= IEEE80211_KEY_SWCRYPT
;
2374 k
->wk_flags
&= ~IEEE80211_KEY_SWCRYPT
;
2381 wi_cmd(struct wi_softc
*sc
, int cmd
, int val0
, int val1
, int val2
)
2388 /* wait for the busy bit to clear */
2389 for (i
= sc
->wi_cmd_count
; i
> 0; i
--) { /* 500ms */
2390 if (!(CSR_READ_2(sc
, WI_COMMAND
) & WI_CMD_BUSY
))
2392 DELAY(1*1000); /* 1ms */
2395 if_printf(&sc
->sc_ic
.ic_if
, "wi_cmd: busy bit won't clear.\n" );
2400 CSR_WRITE_2(sc
, WI_PARAM0
, val0
);
2401 CSR_WRITE_2(sc
, WI_PARAM1
, val1
);
2402 CSR_WRITE_2(sc
, WI_PARAM2
, val2
);
2403 CSR_WRITE_2(sc
, WI_COMMAND
, cmd
);
2405 if (cmd
== WI_CMD_INI
) {
2406 /* XXX: should sleep here. */
2407 DELAY(100*1000); /* 100ms delay for init */
2409 for (i
= 0; i
< WI_TIMEOUT
; i
++) {
2411 * Wait for 'command complete' bit to be
2412 * set in the event status register.
2414 s
= CSR_READ_2(sc
, WI_EVENT_STAT
);
2415 if (s
& WI_EV_CMD
) {
2416 /* Ack the event and read result code. */
2417 s
= CSR_READ_2(sc
, WI_STATUS
);
2418 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_CMD
);
2419 if (s
& WI_STAT_CMD_RESULT
) {
2427 if (i
== WI_TIMEOUT
) {
2428 if_printf(&sc
->sc_ic
.ic_if
,
2429 "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd
, s
);
2438 wi_seek_bap(struct wi_softc
*sc
, int id
, int off
)
2442 CSR_WRITE_2(sc
, WI_SEL0
, id
);
2443 CSR_WRITE_2(sc
, WI_OFF0
, off
);
2445 for (i
= 0; ; i
++) {
2446 status
= CSR_READ_2(sc
, WI_OFF0
);
2447 if ((status
& WI_OFF_BUSY
) == 0)
2449 if (i
== WI_TIMEOUT
) {
2450 if_printf(&sc
->sc_ic
.ic_if
,
2451 "timeout in wi_seek to %x/%x\n", id
, off
);
2452 sc
->sc_bap_off
= WI_OFF_ERR
; /* invalidate */
2453 if (status
== 0xffff)
2459 if (status
& WI_OFF_ERR
) {
2460 if_printf(&sc
->sc_ic
.ic_if
, "failed in wi_seek to %x/%x\n",
2462 sc
->sc_bap_off
= WI_OFF_ERR
; /* invalidate */
2466 sc
->sc_bap_off
= off
;
2471 wi_read_bap(struct wi_softc
*sc
, int id
, int off
, void *buf
, int buflen
)
2478 if (id
!= sc
->sc_bap_id
|| off
!= sc
->sc_bap_off
) {
2479 if ((error
= wi_seek_bap(sc
, id
, off
)) != 0)
2482 cnt
= (buflen
+ 1) / 2;
2483 ptr
= (u_int16_t
*)buf
;
2484 for (i
= 0; i
< cnt
; i
++)
2485 *ptr
++ = CSR_READ_2(sc
, WI_DATA0
);
2486 sc
->sc_bap_off
+= cnt
* 2;
2491 wi_write_bap(struct wi_softc
*sc
, int id
, int off
, void *buf
, int buflen
)
2499 #ifdef WI_HERMES_AUTOINC_WAR
2502 if (id
!= sc
->sc_bap_id
|| off
!= sc
->sc_bap_off
) {
2503 if ((error
= wi_seek_bap(sc
, id
, off
)) != 0)
2506 cnt
= (buflen
+ 1) / 2;
2507 ptr
= (u_int16_t
*)buf
;
2508 for (i
= 0; i
< cnt
; i
++)
2509 CSR_WRITE_2(sc
, WI_DATA0
, ptr
[i
]);
2510 sc
->sc_bap_off
+= cnt
* 2;
2512 #ifdef WI_HERMES_AUTOINC_WAR
2514 * According to the comments in the HCF Light code, there is a bug
2515 * in the Hermes (or possibly in certain Hermes firmware revisions)
2516 * where the chip's internal autoincrement counter gets thrown off
2517 * during data writes: the autoincrement is missed, causing one
2518 * data word to be overwritten and subsequent words to be written to
2519 * the wrong memory locations. The end result is that we could end
2520 * up transmitting bogus frames without realizing it. The workaround
2521 * for this is to write a couple of extra guard words after the end
2522 * of the transfer, then attempt to read then back. If we fail to
2523 * locate the guard words where we expect them, we preform the
2524 * transfer over again.
2526 if ((sc
->sc_flags
& WI_FLAGS_BUG_AUTOINC
) && (id
& 0xf000) == 0) {
2527 CSR_WRITE_2(sc
, WI_DATA0
, 0x1234);
2528 CSR_WRITE_2(sc
, WI_DATA0
, 0x5678);
2529 wi_seek_bap(sc
, id
, sc
->sc_bap_off
);
2530 sc
->sc_bap_off
= WI_OFF_ERR
; /* invalidate */
2531 if (CSR_READ_2(sc
, WI_DATA0
) != 0x1234 ||
2532 CSR_READ_2(sc
, WI_DATA0
) != 0x5678) {
2533 if_printf(&sc
->sc_ic
.ic_if
,
2534 "detect auto increment bug, try again\n");
2543 wi_mwrite_bap(struct wi_softc
*sc
, int id
, int off
, struct mbuf
*m0
, int totlen
)
2548 for (m
= m0
; m
!= NULL
&& totlen
> 0; m
= m
->m_next
) {
2552 len
= min(m
->m_len
, totlen
);
2554 if (((u_long
)m
->m_data
) % 2 != 0 || len
% 2 != 0) {
2555 m_copydata(m
, 0, totlen
, (caddr_t
)&sc
->sc_txbuf
);
2556 return wi_write_bap(sc
, id
, off
, (caddr_t
)&sc
->sc_txbuf
,
2560 if ((error
= wi_write_bap(sc
, id
, off
, m
->m_data
, len
)) != 0)
2570 wi_alloc_fid(struct wi_softc
*sc
, int len
, int *idp
)
2574 if (wi_cmd(sc
, WI_CMD_ALLOC_MEM
, len
, 0, 0)) {
2575 if_printf(&sc
->sc_ic
.ic_if
,
2576 "failed to allocate %d bytes on NIC\n", len
);
2580 for (i
= 0; i
< WI_TIMEOUT
; i
++) {
2581 if (CSR_READ_2(sc
, WI_EVENT_STAT
) & WI_EV_ALLOC
)
2585 if (i
== WI_TIMEOUT
) {
2586 if_printf(&sc
->sc_ic
.ic_if
, "timeout in alloc\n");
2589 *idp
= CSR_READ_2(sc
, WI_ALLOC_FID
);
2590 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_ALLOC
);
2595 wi_read_rid(struct wi_softc
*sc
, int rid
, void *buf
, int *buflenp
)
2600 /* Tell the NIC to enter record read mode. */
2601 error
= wi_cmd(sc
, WI_CMD_ACCESS
| WI_ACCESS_READ
, rid
, 0, 0);
2605 error
= wi_read_bap(sc
, rid
, 0, ltbuf
, sizeof(ltbuf
));
2609 if (le16toh(ltbuf
[1]) != rid
) {
2610 if_printf(&sc
->sc_ic
.ic_if
,
2611 "record read mismatch, rid=%x, got=%x\n",
2612 rid
, le16toh(ltbuf
[1]));
2615 len
= (le16toh(ltbuf
[0]) - 1) * 2; /* already got rid */
2616 if (*buflenp
< len
) {
2617 if_printf(&sc
->sc_ic
.ic_if
, "record buffer is too small, "
2618 "rid=%x, size=%d, len=%d\n", rid
, *buflenp
, len
);
2622 return wi_read_bap(sc
, rid
, sizeof(ltbuf
), buf
, len
);
2626 wi_write_rid(struct wi_softc
*sc
, int rid
, void *buf
, int buflen
)
2631 ltbuf
[0] = htole16((buflen
+ 1) / 2 + 1); /* includes rid */
2632 ltbuf
[1] = htole16(rid
);
2634 error
= wi_write_bap(sc
, rid
, 0, ltbuf
, sizeof(ltbuf
));
2637 error
= wi_write_bap(sc
, rid
, sizeof(ltbuf
), buf
, buflen
);
2641 return wi_cmd(sc
, WI_CMD_ACCESS
| WI_ACCESS_WRITE
, rid
, 0, 0);
2645 wi_newstate(struct ieee80211com
*ic
, enum ieee80211_state nstate
, int arg
)
2647 struct ifnet
*ifp
= &ic
->ic_if
;
2648 struct wi_softc
*sc
= ifp
->if_softc
;
2649 struct ieee80211_node
*ni
= ic
->ic_bss
;
2652 struct wi_ssid ssid
;
2653 u_int8_t old_bssid
[IEEE80211_ADDR_LEN
];
2655 DPRINTF((ifp
, "%s: %s -> %s\n", __func__
,
2656 ieee80211_state_name
[ic
->ic_state
],
2657 ieee80211_state_name
[nstate
]));
2660 * Internal to the driver the INIT and RUN states are used
2661 * so bypass the net80211 state machine for other states.
2662 * Beware however that this requires use to net80211 state
2663 * management that otherwise would be handled for us.
2666 case IEEE80211_S_INIT
:
2667 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
2668 return sc
->sc_newstate(ic
, nstate
, arg
);
2670 case IEEE80211_S_RUN
:
2671 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
2672 buflen
= IEEE80211_ADDR_LEN
;
2673 IEEE80211_ADDR_COPY(old_bssid
, ni
->ni_bssid
);
2674 wi_read_rid(sc
, WI_RID_CURRENT_BSSID
, ni
->ni_bssid
, &buflen
);
2675 IEEE80211_ADDR_COPY(ni
->ni_macaddr
, ni
->ni_bssid
);
2676 buflen
= sizeof(val
);
2677 wi_read_rid(sc
, WI_RID_CURRENT_CHAN
, &val
, &buflen
);
2678 /* XXX validate channel */
2679 ni
->ni_chan
= &ic
->ic_channels
[le16toh(val
)];
2680 ic
->ic_curchan
= ni
->ni_chan
;
2681 ic
->ic_ibss_chan
= ni
->ni_chan
;
2683 sc
->sc_tx_th
.wt_chan_freq
= sc
->sc_rx_th
.wr_chan_freq
=
2684 htole16(ni
->ni_chan
->ic_freq
);
2685 sc
->sc_tx_th
.wt_chan_flags
= sc
->sc_rx_th
.wr_chan_flags
=
2686 htole16(ni
->ni_chan
->ic_flags
);
2689 * XXX hack; unceremoniously clear
2690 * IEEE80211_F_DROPUNENC when operating with
2691 * wep enabled so we don't drop unencoded frames
2692 * at the 802.11 layer. This is necessary because
2693 * we must strip the WEP bit from the 802.11 header
2694 * before passing frames to ieee80211_input because
2695 * the card has already stripped the WEP crypto
2696 * header from the packet.
2698 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
)
2699 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
2700 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
) {
2701 /* XXX check return value */
2702 buflen
= sizeof(ssid
);
2703 wi_read_rid(sc
, WI_RID_CURRENT_SSID
, &ssid
, &buflen
);
2704 ni
->ni_esslen
= le16toh(ssid
.wi_len
);
2705 if (ni
->ni_esslen
> IEEE80211_NWID_LEN
)
2706 ni
->ni_esslen
= IEEE80211_NWID_LEN
; /*XXX*/
2707 memcpy(ni
->ni_essid
, ssid
.wi_ssid
, ni
->ni_esslen
);
2709 return sc
->sc_newstate(ic
, nstate
, arg
);
2711 case IEEE80211_S_SCAN
:
2712 case IEEE80211_S_AUTH
:
2713 case IEEE80211_S_ASSOC
:
2717 ic
->ic_state
= nstate
; /* NB: skip normal ieee80211 handling */
2722 wi_scan_ap(struct wi_softc
*sc
, u_int16_t chanmask
, u_int16_t txrate
)
2727 if (!sc
->sc_enabled
)
2729 switch (sc
->sc_firmware_type
) {
2731 wi_cmd(sc
, WI_CMD_INQUIRE
, WI_INFO_SCAN_RESULTS
, 0, 0);
2734 val
[0] = htole16(chanmask
); /* channel */
2735 val
[1] = htole16(txrate
); /* tx rate */
2736 error
= wi_write_rid(sc
, WI_RID_SCAN_REQ
, val
, sizeof(val
));
2740 * XXX only supported on 3.x ?
2742 val
[0] = BSCAN_BCAST
| BSCAN_ONETIME
;
2743 error
= wi_write_rid(sc
, WI_RID_BCAST_SCAN_REQ
,
2744 val
, sizeof(val
[0]));
2748 sc
->sc_scan_timer
= WI_SCAN_WAIT
;
2749 sc
->sc_ic
.ic_if
.if_timer
= 1;
2750 DPRINTF((&sc
->sc_ic
.ic_if
, "wi_scan_ap: start scanning, "
2751 "chamask 0x%x txrate 0x%x\n", chanmask
, txrate
));
2757 wi_scan_result(struct wi_softc
*sc
, int fid
, int cnt
)
2759 #define N(a) (sizeof (a) / sizeof (a[0]))
2760 int i
, naps
, off
, szbuf
;
2761 struct wi_scan_header ws_hdr
; /* Prism2 header */
2762 struct wi_scan_data_p2 ws_dat
; /* Prism2 scantable*/
2763 struct wi_apinfo
*ap
;
2765 off
= sizeof(u_int16_t
) * 2;
2766 memset(&ws_hdr
, 0, sizeof(ws_hdr
));
2767 switch (sc
->sc_firmware_type
) {
2769 wi_read_bap(sc
, fid
, off
, &ws_hdr
, sizeof(ws_hdr
));
2770 off
+= sizeof(ws_hdr
);
2771 szbuf
= sizeof(struct wi_scan_data_p2
);
2774 szbuf
= sizeof(struct wi_scan_data_p2
) + 6;
2777 szbuf
= sizeof(struct wi_scan_data
);
2780 if_printf(&sc
->sc_ic
.ic_if
,
2781 "wi_scan_result: unknown firmware type %u\n",
2782 sc
->sc_firmware_type
);
2786 naps
= (cnt
* 2 + 2 - off
) / szbuf
;
2787 if (naps
> N(sc
->sc_aps
))
2788 naps
= N(sc
->sc_aps
);
2792 memset(&ws_dat
, 0, sizeof(ws_dat
));
2793 for (i
= 0; i
< naps
; i
++, ap
++) {
2794 wi_read_bap(sc
, fid
, off
, &ws_dat
,
2795 (sizeof(ws_dat
) < szbuf
? sizeof(ws_dat
) : szbuf
));
2796 DPRINTF2((&sc
->sc_ic
.ic_if
,
2797 "wi_scan_result: #%d: off %d bssid %6D\n",
2798 i
, off
, ws_dat
.wi_bssid
, ":"));
2800 ap
->scanreason
= le16toh(ws_hdr
.wi_reason
);
2801 memcpy(ap
->bssid
, ws_dat
.wi_bssid
, sizeof(ap
->bssid
));
2802 ap
->channel
= le16toh(ws_dat
.wi_chid
);
2803 ap
->signal
= le16toh(ws_dat
.wi_signal
);
2804 ap
->noise
= le16toh(ws_dat
.wi_noise
);
2805 ap
->quality
= ap
->signal
- ap
->noise
;
2806 ap
->capinfo
= le16toh(ws_dat
.wi_capinfo
);
2807 ap
->interval
= le16toh(ws_dat
.wi_interval
);
2808 ap
->rate
= le16toh(ws_dat
.wi_rate
);
2809 ap
->namelen
= le16toh(ws_dat
.wi_namelen
);
2810 if (ap
->namelen
> sizeof(ap
->name
))
2811 ap
->namelen
= sizeof(ap
->name
);
2812 memcpy(ap
->name
, ws_dat
.wi_name
, ap
->namelen
);
2816 sc
->sc_scan_timer
= 0;
2817 DPRINTF((&sc
->sc_ic
.ic_if
, "wi_scan_result: scan complete: ap %d\n",
2823 wi_dump_pkt(struct wi_frame
*wh
, struct ieee80211_node
*ni
, int rssi
)
2825 ieee80211_dump_pkt((u_int8_t
*) &wh
->wi_whdr
, sizeof(wh
->wi_whdr
),
2826 ni
? ni
->ni_rates
.rs_rates
[ni
->ni_txrate
] & IEEE80211_RATE_VAL
: -1, rssi
);
2827 kprintf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
2828 le16toh(wh
->wi_status
), le16toh(wh
->wi_rx_tstamp1
),
2829 le16toh(wh
->wi_rx_tstamp0
), wh
->wi_rx_silence
);
2830 kprintf(" rx_signal %u rx_rate %u rx_flow %u\n",
2831 wh
->wi_rx_signal
, wh
->wi_rx_rate
, wh
->wi_rx_flow
);
2832 kprintf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
2833 wh
->wi_tx_rtry
, wh
->wi_tx_rate
,
2834 le16toh(wh
->wi_tx_ctl
), le16toh(wh
->wi_dat_len
));
2835 kprintf(" ehdr dst %6D src %6D type 0x%x\n",
2836 wh
->wi_ehdr
.ether_dhost
, ":", wh
->wi_ehdr
.ether_shost
, ":",
2837 wh
->wi_ehdr
.ether_type
);
2841 wi_alloc(device_t dev
, int rid
)
2843 struct wi_softc
*sc
= device_get_softc(dev
);
2845 if (sc
->wi_bus_type
!= WI_BUS_PCI_NATIVE
) {
2846 sc
->iobase_rid
= rid
;
2847 sc
->iobase
= bus_alloc_resource(dev
, SYS_RES_IOPORT
,
2848 &sc
->iobase_rid
, 0, ~0, (1 << 6),
2849 rman_make_alignment_flags(1 << 6) | RF_ACTIVE
);
2851 device_printf(dev
, "No I/O space?!\n");
2855 sc
->wi_io_addr
= rman_get_start(sc
->iobase
);
2856 sc
->wi_btag
= rman_get_bustag(sc
->iobase
);
2857 sc
->wi_bhandle
= rman_get_bushandle(sc
->iobase
);
2860 sc
->mem
= bus_alloc_resource_any(dev
, SYS_RES_MEMORY
,
2861 &sc
->mem_rid
, RF_ACTIVE
);
2864 device_printf(dev
, "No Mem space on prism2.5?\n");
2868 sc
->wi_btag
= rman_get_bustag(sc
->mem
);
2869 sc
->wi_bhandle
= rman_get_bushandle(sc
->mem
);
2874 sc
->irq
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &sc
->irq_rid
,
2876 ((sc
->wi_bus_type
== WI_BUS_PCCARD
) ? 0 : RF_SHAREABLE
));
2880 device_printf(dev
, "No irq?!\n");
2888 wi_free(device_t dev
)
2890 struct wi_softc
*sc
= device_get_softc(dev
);
2892 if (sc
->iobase
!= NULL
) {
2893 bus_release_resource(dev
, SYS_RES_IOPORT
, sc
->iobase_rid
, sc
->iobase
);
2896 if (sc
->irq
!= NULL
) {
2897 bus_release_resource(dev
, SYS_RES_IRQ
, sc
->irq_rid
, sc
->irq
);
2900 if (sc
->mem
!= NULL
) {
2901 bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->mem_rid
, sc
->mem
);
2907 wi_get_debug(struct wi_softc
*sc
, struct wi_req
*wreq
)
2913 switch (wreq
->wi_type
) {
2914 case WI_DEBUG_SLEEP
:
2916 wreq
->wi_val
[0] = sc
->wi_debug
.wi_sleep
;
2918 case WI_DEBUG_DELAYSUPP
:
2920 wreq
->wi_val
[0] = sc
->wi_debug
.wi_delaysupp
;
2922 case WI_DEBUG_TXSUPP
:
2924 wreq
->wi_val
[0] = sc
->wi_debug
.wi_txsupp
;
2926 case WI_DEBUG_MONITOR
:
2928 wreq
->wi_val
[0] = sc
->wi_debug
.wi_monitor
;
2930 case WI_DEBUG_LEDTEST
:
2932 wreq
->wi_val
[0] = sc
->wi_debug
.wi_ledtest
;
2933 wreq
->wi_val
[1] = sc
->wi_debug
.wi_ledtest_param0
;
2934 wreq
->wi_val
[2] = sc
->wi_debug
.wi_ledtest_param1
;
2936 case WI_DEBUG_CONTTX
:
2938 wreq
->wi_val
[0] = sc
->wi_debug
.wi_conttx
;
2939 wreq
->wi_val
[1] = sc
->wi_debug
.wi_conttx_param0
;
2941 case WI_DEBUG_CONTRX
:
2943 wreq
->wi_val
[0] = sc
->wi_debug
.wi_contrx
;
2945 case WI_DEBUG_SIGSTATE
:
2947 wreq
->wi_val
[0] = sc
->wi_debug
.wi_sigstate
;
2948 wreq
->wi_val
[1] = sc
->wi_debug
.wi_sigstate_param0
;
2950 case WI_DEBUG_CONFBITS
:
2952 wreq
->wi_val
[0] = sc
->wi_debug
.wi_confbits
;
2953 wreq
->wi_val
[1] = sc
->wi_debug
.wi_confbits_param0
;
2964 wi_set_debug(struct wi_softc
*sc
, struct wi_req
*wreq
)
2967 u_int16_t cmd
, param0
= 0, param1
= 0;
2969 switch (wreq
->wi_type
) {
2970 case WI_DEBUG_RESET
:
2972 case WI_DEBUG_CALENABLE
:
2974 case WI_DEBUG_SLEEP
:
2975 sc
->wi_debug
.wi_sleep
= 1;
2978 sc
->wi_debug
.wi_sleep
= 0;
2981 param0
= wreq
->wi_val
[0];
2983 case WI_DEBUG_DELAYSUPP
:
2984 sc
->wi_debug
.wi_delaysupp
= 1;
2986 case WI_DEBUG_TXSUPP
:
2987 sc
->wi_debug
.wi_txsupp
= 1;
2989 case WI_DEBUG_MONITOR
:
2990 sc
->wi_debug
.wi_monitor
= 1;
2992 case WI_DEBUG_LEDTEST
:
2993 param0
= wreq
->wi_val
[0];
2994 param1
= wreq
->wi_val
[1];
2995 sc
->wi_debug
.wi_ledtest
= 1;
2996 sc
->wi_debug
.wi_ledtest_param0
= param0
;
2997 sc
->wi_debug
.wi_ledtest_param1
= param1
;
2999 case WI_DEBUG_CONTTX
:
3000 param0
= wreq
->wi_val
[0];
3001 sc
->wi_debug
.wi_conttx
= 1;
3002 sc
->wi_debug
.wi_conttx_param0
= param0
;
3004 case WI_DEBUG_STOPTEST
:
3005 sc
->wi_debug
.wi_delaysupp
= 0;
3006 sc
->wi_debug
.wi_txsupp
= 0;
3007 sc
->wi_debug
.wi_monitor
= 0;
3008 sc
->wi_debug
.wi_ledtest
= 0;
3009 sc
->wi_debug
.wi_ledtest_param0
= 0;
3010 sc
->wi_debug
.wi_ledtest_param1
= 0;
3011 sc
->wi_debug
.wi_conttx
= 0;
3012 sc
->wi_debug
.wi_conttx_param0
= 0;
3013 sc
->wi_debug
.wi_contrx
= 0;
3014 sc
->wi_debug
.wi_sigstate
= 0;
3015 sc
->wi_debug
.wi_sigstate_param0
= 0;
3017 case WI_DEBUG_CONTRX
:
3018 sc
->wi_debug
.wi_contrx
= 1;
3020 case WI_DEBUG_SIGSTATE
:
3021 param0
= wreq
->wi_val
[0];
3022 sc
->wi_debug
.wi_sigstate
= 1;
3023 sc
->wi_debug
.wi_sigstate_param0
= param0
;
3025 case WI_DEBUG_CONFBITS
:
3026 param0
= wreq
->wi_val
[0];
3027 param1
= wreq
->wi_val
[1];
3028 sc
->wi_debug
.wi_confbits
= param0
;
3029 sc
->wi_debug
.wi_confbits_param0
= param1
;
3039 cmd
= WI_CMD_DEBUG
| (wreq
->wi_type
<< 8);
3040 error
= wi_cmd(sc
, cmd
, param0
, param1
, 0);
3046 * Special routines to download firmware for Symbol CF card.
3047 * XXX: This should be modified generic into any PRISM-2 based card.
3050 #define WI_SBCF_PDIADDR 0x3100
3052 /* unaligned load little endian */
3053 #define GETLE32(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
3054 #define GETLE16(p) ((p)[0] | ((p)[1]<<8))
3057 wi_symbol_load_firm(struct wi_softc
*sc
, const void *primsym
, int primlen
,
3058 const void *secsym
, int seclen
)
3063 /* load primary code and run it */
3064 wi_symbol_set_hcr(sc
, WI_HCR_EEHOLD
);
3065 if (wi_symbol_write_firm(sc
, primsym
, primlen
, NULL
, 0))
3067 wi_symbol_set_hcr(sc
, WI_HCR_RUN
);
3068 for (i
= 0; ; i
++) {
3071 tsleep(sc
, 0, "wiinit", 1);
3072 if (CSR_READ_2(sc
, WI_CNTL
) == WI_CNTL_AUX_ENA_STAT
)
3074 /* write the magic key value to unlock aux port */
3075 CSR_WRITE_2(sc
, WI_PARAM0
, WI_AUX_KEY0
);
3076 CSR_WRITE_2(sc
, WI_PARAM1
, WI_AUX_KEY1
);
3077 CSR_WRITE_2(sc
, WI_PARAM2
, WI_AUX_KEY2
);
3078 CSR_WRITE_2(sc
, WI_CNTL
, WI_CNTL_AUX_ENA_CNTL
);
3081 /* issue read EEPROM command: XXX copied from wi_cmd() */
3082 CSR_WRITE_2(sc
, WI_PARAM0
, 0);
3083 CSR_WRITE_2(sc
, WI_PARAM1
, 0);
3084 CSR_WRITE_2(sc
, WI_PARAM2
, 0);
3085 CSR_WRITE_2(sc
, WI_COMMAND
, WI_CMD_READEE
);
3086 for (i
= 0; i
< WI_TIMEOUT
; i
++) {
3087 if (CSR_READ_2(sc
, WI_EVENT_STAT
) & WI_EV_CMD
)
3091 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_CMD
);
3093 CSR_WRITE_2(sc
, WI_AUX_PAGE
, WI_SBCF_PDIADDR
/ WI_AUX_PGSZ
);
3094 CSR_WRITE_2(sc
, WI_AUX_OFFSET
, WI_SBCF_PDIADDR
% WI_AUX_PGSZ
);
3095 CSR_READ_MULTI_STREAM_2(sc
, WI_AUX_DATA
,
3096 (uint16_t *)ebuf
, sizeof(ebuf
) / 2);
3097 if (GETLE16(ebuf
) > sizeof(ebuf
))
3099 if (wi_symbol_write_firm(sc
, secsym
, seclen
, ebuf
+ 4, GETLE16(ebuf
)))
3105 wi_symbol_write_firm(struct wi_softc
*sc
, const void *buf
, int buflen
,
3106 const void *ebuf
, int ebuflen
)
3108 const uint8_t *p
, *ep
, *q
, *eq
;
3110 uint32_t addr
, id
, eid
;
3111 int i
, len
, elen
, nblk
, pdrlen
;
3114 * Parse the header of the firmware image.
3118 while (p
< ep
&& *p
++ != ' '); /* FILE: */
3119 while (p
< ep
&& *p
++ != ' '); /* filename */
3120 while (p
< ep
&& *p
++ != ' '); /* type of the firmware */
3121 nblk
= strtoul(p
, &tp
, 10);
3123 pdrlen
= strtoul(p
+ 1, &tp
, 10);
3125 while (p
< ep
&& *p
++ != 0x1a); /* skip rest of header */
3128 * Block records: address[4], length[2], data[length];
3130 for (i
= 0; i
< nblk
; i
++) {
3131 addr
= GETLE32(p
); p
+= 4;
3132 len
= GETLE16(p
); p
+= 2;
3133 CSR_WRITE_2(sc
, WI_AUX_PAGE
, addr
/ WI_AUX_PGSZ
);
3134 CSR_WRITE_2(sc
, WI_AUX_OFFSET
, addr
% WI_AUX_PGSZ
);
3135 CSR_WRITE_MULTI_STREAM_2(sc
, WI_AUX_DATA
,
3136 (const uint16_t *)p
, len
/ 2);
3141 * PDR: id[4], address[4], length[4];
3143 for (i
= 0; i
< pdrlen
; ) {
3144 id
= GETLE32(p
); p
+= 4; i
+= 4;
3145 addr
= GETLE32(p
); p
+= 4; i
+= 4;
3146 len
= GETLE32(p
); p
+= 4; i
+= 4;
3147 /* replace PDR entry with the values from EEPROM, if any */
3148 for (q
= ebuf
, eq
= q
+ ebuflen
; q
< eq
; q
+= elen
* 2) {
3149 elen
= GETLE16(q
); q
+= 2;
3150 eid
= GETLE16(q
); q
+= 2;
3151 elen
--; /* elen includes eid */
3156 CSR_WRITE_2(sc
, WI_AUX_PAGE
, addr
/ WI_AUX_PGSZ
);
3157 CSR_WRITE_2(sc
, WI_AUX_OFFSET
, addr
% WI_AUX_PGSZ
);
3158 CSR_WRITE_MULTI_STREAM_2(sc
, WI_AUX_DATA
,
3159 (const uint16_t *)q
, len
/ 2);
3167 wi_symbol_set_hcr(struct wi_softc
*sc
, int mode
)
3171 CSR_WRITE_2(sc
, WI_COR
, WI_COR_RESET
);
3172 tsleep(sc
, 0, "wiinit", 1);
3173 hcr
= CSR_READ_2(sc
, WI_HCR
);
3174 hcr
= (hcr
& WI_HCR_4WIRE
) | (mode
& ~WI_HCR_4WIRE
);
3175 CSR_WRITE_2(sc
, WI_HCR
, hcr
);
3176 tsleep(sc
, 0, "wiinit", 1);
3177 CSR_WRITE_2(sc
, WI_COR
, WI_COR_IOMODE
);
3178 tsleep(sc
, 0, "wiinit", 1);