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