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$");
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_ADDR_LOCK(ifp);
1725 #if __FreeBSD_version < 500000
1726 LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1727 #else
1728 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1729 #endif
1730 if (ifma->ifma_addr->sa_family != AF_LINK)
1731 continue;
1732 if (n >= 16)
1733 goto allmulti;
1734 IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
1735 (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
1736 n++;
1737 }
1738 IF_ADDR_UNLOCK(ifp);
1739 return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1740 IEEE80211_ADDR_LEN * n);
1741 }
1742
1743 static void
1744 wi_read_nicid(struct wi_softc *sc)
1745 {
1746 struct wi_card_ident *id;
1747 char *p;
1748 int len;
1749 u_int16_t ver[4];
1750
1751 /* getting chip identity */
1752 memset(ver, 0, sizeof(ver));
1753 len = sizeof(ver);
1754 wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
1755 device_printf(sc->sc_dev, "using ");
1756
1757 sc->sc_firmware_type = WI_NOTYPE;
1758 for (id = wi_card_ident; id->card_name != NULL; id++) {
1759 if (le16toh(ver[0]) == id->card_id) {
1760 printf("%s", id->card_name);
1761 sc->sc_firmware_type = id->firm_type;
1762 break;
1763 }
1764 }
1765 if (sc->sc_firmware_type == WI_NOTYPE) {
1766 if (le16toh(ver[0]) & 0x8000) {
1767 printf("Unknown PRISM2 chip");
1768 sc->sc_firmware_type = WI_INTERSIL;
1769 } else {
1770 printf("Unknown Lucent chip");
1771 sc->sc_firmware_type = WI_LUCENT;
1772 }
1773 }
1774
1775 /* get primary firmware version (Only Prism chips) */
1776 if (sc->sc_firmware_type != WI_LUCENT) {
1777 memset(ver, 0, sizeof(ver));
1778 len = sizeof(ver);
1779 wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
1780 sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
1781 le16toh(ver[3]) * 100 + le16toh(ver[1]);
1782 }
1783
1784 /* get station firmware version */
1785 memset(ver, 0, sizeof(ver));
1786 len = sizeof(ver);
1787 wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
1788 sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
1789 le16toh(ver[3]) * 100 + le16toh(ver[1]);
1790 if (sc->sc_firmware_type == WI_INTERSIL &&
1791 (sc->sc_sta_firmware_ver == 10102 ||
1792 sc->sc_sta_firmware_ver == 20102)) {
1793 char ident[12];
1794 memset(ident, 0, sizeof(ident));
1795 len = sizeof(ident);
1796 /* value should be the format like "V2.00-11" */
1797 if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
1798 *(p = (char *)ident) >= 'A' &&
1799 p[2] == '.' && p[5] == '-' && p[8] == '\0') {
1800 sc->sc_firmware_type = WI_SYMBOL;
1801 sc->sc_sta_firmware_ver = (p[1] - '') * 10000 +
1802 (p[3] - '') * 1000 + (p[4] - '') * 100 +
1803 (p[6] - '') * 10 + (p[7] - '');
1804 }
1805 }
1806 printf("\n");
1807 device_printf(sc->sc_dev, "%s Firmware: ",
1808 sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
1809 (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
1810 if (sc->sc_firmware_type != WI_LUCENT) /* XXX */
1811 printf("Primary (%u.%u.%u), ",
1812 sc->sc_pri_firmware_ver / 10000,
1813 (sc->sc_pri_firmware_ver % 10000) / 100,
1814 sc->sc_pri_firmware_ver % 100);
1815 printf("Station (%u.%u.%u)\n",
1816 sc->sc_sta_firmware_ver / 10000,
1817 (sc->sc_sta_firmware_ver % 10000) / 100,
1818 sc->sc_sta_firmware_ver % 100);
1819 }
1820
1821 static int
1822 wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
1823 {
1824 struct wi_ssid ssid;
1825
1826 if (buflen > IEEE80211_NWID_LEN)
1827 return ENOBUFS;
1828 memset(&ssid, 0, sizeof(ssid));
1829 ssid.wi_len = htole16(buflen);
1830 memcpy(ssid.wi_ssid, buf, buflen);
1831 return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
1832 }
1833
1834 static int
1835 wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
1836 {
1837 struct wi_softc *sc = ifp->if_softc;
1838 struct ieee80211com *ic = &sc->sc_ic;
1839 struct ifreq *ifr = (struct ifreq *)data;
1840 struct wi_req wreq;
1841 struct wi_scan_res *res;
1842 size_t reslen;
1843 int len, n, error, mif, val, off, i;
1844
1845 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1846 if (error)
1847 return error;
1848 len = (wreq.wi_len - 1) * 2;
1849 if (len < sizeof(u_int16_t))
1850 return ENOSPC;
1851 if (len > sizeof(wreq.wi_val))
1852 len = sizeof(wreq.wi_val);
1853
1854 switch (wreq.wi_type) {
1855
1856 case WI_RID_IFACE_STATS:
1857 memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
1858 if (len < sizeof(sc->sc_stats))
1859 error = ENOSPC;
1860 else
1861 len = sizeof(sc->sc_stats);
1862 break;
1863
1864 case WI_RID_ENCRYPTION:
1865 case WI_RID_TX_CRYPT_KEY:
1866 case WI_RID_DEFLT_CRYPT_KEYS:
1867 case WI_RID_TX_RATE:
1868 return ieee80211_cfgget(ifp, cmd, data);
1869
1870 case WI_RID_MICROWAVE_OVEN:
1871 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
1872 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1873 &len);
1874 break;
1875 }
1876 wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
1877 len = sizeof(u_int16_t);
1878 break;
1879
1880 case WI_RID_DBM_ADJUST:
1881 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
1882 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1883 &len);
1884 break;
1885 }
1886 wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
1887 len = sizeof(u_int16_t);
1888 break;
1889
1890 case WI_RID_ROAMING_MODE:
1891 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
1892 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1893 &len);
1894 break;
1895 }
1896 wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
1897 len = sizeof(u_int16_t);
1898 break;
1899
1900 case WI_RID_SYSTEM_SCALE:
1901 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
1902 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1903 &len);
1904 break;
1905 }
1906 wreq.wi_val[0] = htole16(sc->sc_system_scale);
1907 len = sizeof(u_int16_t);
1908 break;
1909
1910 case WI_RID_FRAG_THRESH:
1911 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
1912 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1913 &len);
1914 break;
1915 }
1916 wreq.wi_val[0] = htole16(ic->ic_fragthreshold);
1917 len = sizeof(u_int16_t);
1918 break;
1919
1920 case WI_RID_READ_APS:
1921 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1922 return ieee80211_cfgget(ifp, cmd, data);
1923 if (sc->sc_scan_timer > 0) {
1924 error = EINPROGRESS;
1925 break;
1926 }
1927 n = sc->sc_naps;
1928 if (len < sizeof(n)) {
1929 error = ENOSPC;
1930 break;
1931 }
1932 if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
1933 n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
1934 len = sizeof(n) + sizeof(struct wi_apinfo) * n;
1935 memcpy(wreq.wi_val, &n, sizeof(n));
1936 memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps,
1937 sizeof(struct wi_apinfo) * n);
1938 break;
1939
1940 case WI_RID_PRISM2:
1941 wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT;
1942 len = sizeof(u_int16_t);
1943 break;
1944
1945 case WI_RID_MIF:
1946 mif = wreq.wi_val[0];
1947 error = wi_cmd(sc, WI_CMD_READMIF, mif, 0, 0);
1948 val = CSR_READ_2(sc, WI_RESP0);
1949 wreq.wi_val[0] = val;
1950 len = sizeof(u_int16_t);
1951 break;
1952
1953 case WI_RID_ZERO_CACHE:
1954 case WI_RID_PROCFRAME: /* ignore for compatibility */
1955 /* XXX ??? */
1956 break;
1957
1958 case WI_RID_READ_CACHE:
1959 return ieee80211_cfgget(ifp, cmd, data);
1960
1961 case WI_RID_SCAN_RES: /* compatibility interface */
1962 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1963 return ieee80211_cfgget(ifp, cmd, data);
1964 if (sc->sc_scan_timer > 0) {
1965 error = EINPROGRESS;
1966 break;
1967 }
1968 n = sc->sc_naps;
1969 if (sc->sc_firmware_type == WI_LUCENT) {
1970 off = 0;
1971 reslen = WI_WAVELAN_RES_SIZE;
1972 } else {
1973 off = sizeof(struct wi_scan_p2_hdr);
1974 reslen = WI_PRISM2_RES_SIZE;
1975 }
1976 if (len < off + reslen * n)
1977 n = (len - off) / reslen;
1978 len = off + reslen * n;
1979 if (off != 0) {
1980 struct wi_scan_p2_hdr *p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
1981 /*
1982 * Prepend Prism-specific header.
1983 */
1984 if (len < sizeof(struct wi_scan_p2_hdr)) {
1985 error = ENOSPC;
1986 break;
1987 }
1988 p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
1989 p2->wi_rsvd = 0;
1990 p2->wi_reason = n; /* XXX */
1991 }
1992 for (i = 0; i < n; i++, off += reslen) {
1993 const struct wi_apinfo *ap = &sc->sc_aps[i];
1994
1995 res = (struct wi_scan_res *)((char *)wreq.wi_val + off);
1996 res->wi_chan = ap->channel;
1997 res->wi_noise = ap->noise;
1998 res->wi_signal = ap->signal;
1999 IEEE80211_ADDR_COPY(res->wi_bssid, ap->bssid);
2000 res->wi_interval = ap->interval;
2001 res->wi_capinfo = ap->capinfo;
2002 res->wi_ssid_len = ap->namelen;
2003 memcpy(res->wi_ssid, ap->name,
2004 IEEE80211_NWID_LEN);
2005 if (sc->sc_firmware_type != WI_LUCENT) {
2006 /* XXX not saved from Prism cards */
2007 memset(res->wi_srates, 0,
2008 sizeof(res->wi_srates));
2009 res->wi_rate = ap->rate;
2010 res->wi_rsvd = 0;
2011 }
2012 }
2013 break;
2014
2015 default:
2016 if (sc->sc_enabled) {
2017 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
2018 &len);
2019 break;
2020 }
2021 switch (wreq.wi_type) {
2022 case WI_RID_MAX_DATALEN:
2023 wreq.wi_val[0] = htole16(sc->sc_max_datalen);
2024 len = sizeof(u_int16_t);
2025 break;
2026 case WI_RID_RTS_THRESH:
2027 wreq.wi_val[0] = htole16(ic->ic_rtsthreshold);
2028 len = sizeof(u_int16_t);
2029 break;
2030 case WI_RID_CNFAUTHMODE:
2031 wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
2032 len = sizeof(u_int16_t);
2033 break;
2034 case WI_RID_NODENAME:
2035 if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
2036 error = ENOSPC;
2037 break;
2038 }
2039 len = sc->sc_nodelen + sizeof(u_int16_t);
2040 wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
2041 memcpy(&wreq.wi_val[1], sc->sc_nodename,
2042 sc->sc_nodelen);
2043 break;
2044 default:
2045 return ieee80211_cfgget(ifp, cmd, data);
2046 }
2047 break;
2048 }
2049 if (error)
2050 return error;
2051 wreq.wi_len = (len + 1) / 2 + 1;
2052 return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
2053 }
2054
2055 static int
2056 wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
2057 {
2058 struct wi_softc *sc = ifp->if_softc;
2059 struct ieee80211com *ic = &sc->sc_ic;
2060 struct ifreq *ifr = (struct ifreq *)data;
2061 struct wi_req wreq;
2062 struct mbuf *m;
2063 int i, len, error, mif, val;
2064 struct ieee80211_rateset *rs;
2065
2066 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
2067 if (error)
2068 return error;
2069 len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0;
2070 switch (wreq.wi_type) {
2071 case WI_RID_DBM_ADJUST:
2072 return ENODEV;
2073
2074 case WI_RID_NODENAME:
2075 if (le16toh(wreq.wi_val[0]) * 2 > len ||
2076 le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
2077 error = ENOSPC;
2078 break;
2079 }
2080 if (sc->sc_enabled) {
2081 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2082 len);
2083 if (error)
2084 break;
2085 }
2086 sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
2087 memcpy(sc->sc_nodename, &wreq.wi_val[1], sc->sc_nodelen);
2088 break;
2089
2090 case WI_RID_MICROWAVE_OVEN:
2091 case WI_RID_ROAMING_MODE:
2092 case WI_RID_SYSTEM_SCALE:
2093 case WI_RID_FRAG_THRESH:
2094 if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
2095 (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
2096 break;
2097 if (wreq.wi_type == WI_RID_ROAMING_MODE &&
2098 (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
2099 break;
2100 if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
2101 (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
2102 break;
2103 if (wreq.wi_type == WI_RID_FRAG_THRESH &&
2104 (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
2105 break;
2106 /* FALLTHROUGH */
2107 case WI_RID_RTS_THRESH:
2108 case WI_RID_CNFAUTHMODE:
2109 case WI_RID_MAX_DATALEN:
2110 if (sc->sc_enabled) {
2111 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2112 sizeof(u_int16_t));
2113 if (error)
2114 break;
2115 }
2116 switch (wreq.wi_type) {
2117 case WI_RID_FRAG_THRESH:
2118 ic->ic_fragthreshold = le16toh(wreq.wi_val[0]);
2119 break;
2120 case WI_RID_RTS_THRESH:
2121 ic->ic_rtsthreshold = le16toh(wreq.wi_val[0]);
2122 break;
2123 case WI_RID_MICROWAVE_OVEN:
2124 sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
2125 break;
2126 case WI_RID_ROAMING_MODE:
2127 sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
2128 break;
2129 case WI_RID_SYSTEM_SCALE:
2130 sc->sc_system_scale = le16toh(wreq.wi_val[0]);
2131 break;
2132 case WI_RID_CNFAUTHMODE:
2133 sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
2134 break;
2135 case WI_RID_MAX_DATALEN:
2136 sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
2137 break;
2138 }
2139 break;
2140
2141 case WI_RID_TX_RATE:
2142 switch (le16toh(wreq.wi_val[0])) {
2143 case 3:
2144 ic->ic_fixed_rate = -1;
2145 break;
2146 default:
2147 rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
2148 for (i = 0; i < rs->rs_nrates; i++) {
2149 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL)
2150 / 2 == le16toh(wreq.wi_val[0]))
2151 break;
2152 }
2153 if (i == rs->rs_nrates)
2154 return EINVAL;
2155 ic->ic_fixed_rate = i;
2156 }
2157 if (sc->sc_enabled)
2158 error = wi_write_txrate(sc);
2159 break;
2160
2161 case WI_RID_SCAN_APS:
2162 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
2163 error = wi_scan_ap(sc, 0x3fff, 0x000f);
2164 break;
2165
2166 case WI_RID_SCAN_REQ: /* compatibility interface */
2167 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
2168 error = wi_scan_ap(sc, wreq.wi_val[0], wreq.wi_val[1]);
2169 break;
2170
2171 case WI_RID_MGMT_XMIT:
2172 if (!sc->sc_enabled) {
2173 error = ENETDOWN;
2174 break;
2175 }
2176 if (ic->ic_mgtq.ifq_len > 5) {
2177 error = EAGAIN;
2178 break;
2179 }
2180 /* XXX wi_len looks in u_int8_t, not in u_int16_t */
2181 m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0, ifp, NULL);
2182 if (m == NULL) {
2183 error = ENOMEM;
2184 break;
2185 }
2186 IF_ENQUEUE(&ic->ic_mgtq, m);
2187 break;
2188
2189 case WI_RID_MIF:
2190 mif = wreq.wi_val[0];
2191 val = wreq.wi_val[1];
2192 error = wi_cmd(sc, WI_CMD_WRITEMIF, mif, val, 0);
2193 break;
2194
2195 case WI_RID_PROCFRAME: /* ignore for compatibility */
2196 break;
2197
2198 case WI_RID_OWN_SSID:
2199 if (le16toh(wreq.wi_val[0]) * 2 > len ||
2200 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) {
2201 error = ENOSPC;
2202 break;
2203 }
2204 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
2205 ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2;
2206 memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen);
2207 error = ENETRESET;
2208 break;
2209
2210 default:
2211 if (sc->sc_enabled) {
2212 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2213 len);
2214 if (error)
2215 break;
2216 }
2217 error = ieee80211_cfgset(ifp, cmd, data);
2218 break;
2219 }
2220 return error;
2221 }
2222
2223 static int
2224 wi_write_txrate(struct wi_softc *sc)
2225 {
2226 struct ieee80211com *ic = &sc->sc_ic;
2227 int i;
2228 u_int16_t rate;
2229
2230 if (ic->ic_fixed_rate < 0)
2231 rate = 0; /* auto */
2232 else
2233 rate = (ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ic->ic_fixed_rate] &
2234 IEEE80211_RATE_VAL) / 2;
2235
2236 /* rate: 0, 1, 2, 5, 11 */
2237
2238 switch (sc->sc_firmware_type) {
2239 case WI_LUCENT:
2240 switch (rate) {
2241 case 0: /* auto == 11mbps auto */
2242 rate = 3;
2243 break;
2244 /* case 1, 2 map to 1, 2*/
2245 case 5: /* 5.5Mbps -> 4 */
2246 rate = 4;
2247 break;
2248 case 11: /* 11mbps -> 5 */
2249 rate = 5;
2250 break;
2251 default:
2252 break;
2253 }
2254 break;
2255 default:
2256 /* Choose a bit according to this table.
2257 *
2258 * bit | data rate
2259 * ----+-------------------
2260 * 0 | 1Mbps
2261 * 1 | 2Mbps
2262 * 2 | 5.5Mbps
2263 * 3 | 11Mbps
2264 */
2265 for (i = 8; i > 0; i >>= 1) {
2266 if (rate >= i)
2267 break;
2268 }
2269 if (i == 0)
2270 rate = 0xf; /* auto */
2271 else
2272 rate = i;
2273 break;
2274 }
2275 return wi_write_val(sc, WI_RID_TX_RATE, rate);
2276 }
2277
2278 static int
2279 wi_write_wep(struct wi_softc *sc)
2280 {
2281 struct ieee80211com *ic = &sc->sc_ic;
2282 int error = 0;
2283 int i, keylen;
2284 u_int16_t val;
2285 struct wi_key wkey[IEEE80211_WEP_NKID];
2286
2287 switch (sc->sc_firmware_type) {
2288 case WI_LUCENT:
2289 val = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0;
2290 error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
2291 if (error)
2292 break;
2293 error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_wep_txkey);
2294 if (error)
2295 break;
2296 memset(wkey, 0, sizeof(wkey));
2297 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2298 keylen = ic->ic_nw_keys[i].wk_len;
2299 wkey[i].wi_keylen = htole16(keylen);
2300 memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
2301 keylen);
2302 }
2303 error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
2304 wkey, sizeof(wkey));
2305 break;
2306
2307 case WI_INTERSIL:
2308 case WI_SYMBOL:
2309 if (ic->ic_flags & IEEE80211_F_WEPON) {
2310 /*
2311 * ONLY HWB3163 EVAL-CARD Firmware version
2312 * less than 0.8 variant2
2313 *
2314 * If promiscuous mode disable, Prism2 chip
2315 * does not work with WEP .
2316 * It is under investigation for details.
2317 * (ichiro@netbsd.org)
2318 */
2319 if (sc->sc_firmware_type == WI_INTERSIL &&
2320 sc->sc_sta_firmware_ver < 802 ) {
2321 /* firm ver < 0.8 variant 2 */
2322 wi_write_val(sc, WI_RID_PROMISC, 1);
2323 }
2324 wi_write_val(sc, WI_RID_CNFAUTHMODE,
2325 sc->sc_cnfauthmode);
2326 val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
2327 /*
2328 * Encryption firmware has a bug for HostAP mode.
2329 */
2330 if (sc->sc_firmware_type == WI_INTERSIL &&
2331 ic->ic_opmode == IEEE80211_M_HOSTAP)
2332 val |= HOST_ENCRYPT;
2333 } else {
2334 wi_write_val(sc, WI_RID_CNFAUTHMODE,
2335 IEEE80211_AUTH_OPEN);
2336 val = HOST_ENCRYPT | HOST_DECRYPT;
2337 }
2338 error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
2339 if (error)
2340 break;
2341 error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
2342 ic->ic_wep_txkey);
2343 if (error)
2344 break;
2345 /*
2346 * It seems that the firmware accept 104bit key only if
2347 * all the keys have 104bit length. We get the length of
2348 * the transmit key and use it for all other keys.
2349 * Perhaps we should use software WEP for such situation.
2350 */
2351 keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len;
2352 if (keylen > IEEE80211_WEP_KEYLEN)
2353 keylen = 13; /* 104bit keys */
2354 else
2355 keylen = IEEE80211_WEP_KEYLEN;
2356 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2357 error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
2358 ic->ic_nw_keys[i].wk_key, keylen);
2359 if (error)
2360 break;
2361 }
2362 break;
2363 }
2364 return error;
2365 }
2366
2367 static int
2368 wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
2369 {
2370 int i, s = 0;
2371 static volatile int count = 0;
2372
2373 if (sc->wi_gone)
2374 return (ENODEV);
2375
2376 if (count > 0)
2377 panic("Hey partner, hold on there!");
2378 count++;
2379
2380 /* wait for the busy bit to clear */
2381 for (i = sc->wi_cmd_count; i > 0; i--) { /* 500ms */
2382 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
2383 break;
2384 DELAY(1*1000); /* 1ms */
2385 }
2386 if (i == 0) {
2387 device_printf(sc->sc_dev, "wi_cmd: busy bit won't clear.\n" );
2388 sc->wi_gone = 1;
2389 count--;
2390 return(ETIMEDOUT);
2391 }
2392
2393 CSR_WRITE_2(sc, WI_PARAM0, val0);
2394 CSR_WRITE_2(sc, WI_PARAM1, val1);
2395 CSR_WRITE_2(sc, WI_PARAM2, val2);
2396 CSR_WRITE_2(sc, WI_COMMAND, cmd);
2397
2398 if (cmd == WI_CMD_INI) {
2399 /* XXX: should sleep here. */
2400 DELAY(100*1000); /* 100ms delay for init */
2401 }
2402 for (i = 0; i < WI_TIMEOUT; i++) {
2403 /*
2404 * Wait for 'command complete' bit to be
2405 * set in the event status register.
2406 */
2407 s = CSR_READ_2(sc, WI_EVENT_STAT);
2408 if (s & WI_EV_CMD) {
2409 /* Ack the event and read result code. */
2410 s = CSR_READ_2(sc, WI_STATUS);
2411 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
2412 if (s & WI_STAT_CMD_RESULT) {
2413 count--;
2414 return(EIO);
2415 }
2416 break;
2417 }
2418 DELAY(WI_DELAY);
2419 }
2420
2421 count--;
2422 if (i == WI_TIMEOUT) {
2423 device_printf(sc->sc_dev,
2424 "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
2425 if (s == 0xffff)
2426 sc->wi_gone = 1;
2427 return(ETIMEDOUT);
2428 }
2429 return (0);
2430 }
2431
2432 static int
2433 wi_seek_bap(struct wi_softc *sc, int id, int off)
2434 {
2435 int i, status;
2436
2437 CSR_WRITE_2(sc, WI_SEL0, id);
2438 CSR_WRITE_2(sc, WI_OFF0, off);
2439
2440 for (i = 0; ; i++) {
2441 status = CSR_READ_2(sc, WI_OFF0);
2442 if ((status & WI_OFF_BUSY) == 0)
2443 break;
2444 if (i == WI_TIMEOUT) {
2445 device_printf(sc->sc_dev, "timeout in wi_seek to %x/%x\n",
2446 id, off);
2447 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
2448 if (status == 0xffff)
2449 sc->wi_gone = 1;
2450 return ETIMEDOUT;
2451 }
2452 DELAY(1);
2453 }
2454 if (status & WI_OFF_ERR) {
2455 device_printf(sc->sc_dev, "failed in wi_seek to %x/%x\n", id, off);
2456 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
2457 return EIO;
2458 }
2459 sc->sc_bap_id = id;
2460 sc->sc_bap_off = off;
2461 return 0;
2462 }
2463
2464 static int
2465 wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
2466 {
2467 u_int16_t *ptr;
2468 int i, error, cnt;
2469
2470 if (buflen == 0)
2471 return 0;
2472 if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
2473 if ((error = wi_seek_bap(sc, id, off)) != 0)
2474 return error;
2475 }
2476 cnt = (buflen + 1) / 2;
2477 ptr = (u_int16_t *)buf;
2478 for (i = 0; i < cnt; i++)
2479 *ptr++ = CSR_READ_2(sc, WI_DATA0);
2480 sc->sc_bap_off += cnt * 2;
2481 return 0;
2482 }
2483
2484 static int
2485 wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
2486 {
2487 u_int16_t *ptr;
2488 int i, error, cnt;
2489
2490 if (buflen == 0)
2491 return 0;
2492
2493 #ifdef WI_HERMES_AUTOINC_WAR
2494 again:
2495 #endif
2496 if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
2497 if ((error = wi_seek_bap(sc, id, off)) != 0)
2498 return error;
2499 }
2500 cnt = (buflen + 1) / 2;
2501 ptr = (u_int16_t *)buf;
2502 for (i = 0; i < cnt; i++)
2503 CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
2504 sc->sc_bap_off += cnt * 2;
2505
2506 #ifdef WI_HERMES_AUTOINC_WAR
2507 /*
2508 * According to the comments in the HCF Light code, there is a bug
2509 * in the Hermes (or possibly in certain Hermes firmware revisions)
2510 * where the chip's internal autoincrement counter gets thrown off
2511 * during data writes: the autoincrement is missed, causing one
2512 * data word to be overwritten and subsequent words to be written to
2513 * the wrong memory locations. The end result is that we could end
2514 * up transmitting bogus frames without realizing it. The workaround
2515 * for this is to write a couple of extra guard words after the end
2516 * of the transfer, then attempt to read then back. If we fail to
2517 * locate the guard words where we expect them, we preform the
2518 * transfer over again.
2519 */
2520 if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
2521 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
2522 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
2523 wi_seek_bap(sc, id, sc->sc_bap_off);
2524 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
2525 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
2526 CSR_READ_2(sc, WI_DATA0) != 0x5678) {
2527 device_printf(sc->sc_dev,
2528 "detect auto increment bug, try again\n");
2529 goto again;
2530 }
2531 }
2532 #endif
2533 return 0;
2534 }
2535
2536 static int
2537 wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen)
2538 {
2539 int error, len;
2540 struct mbuf *m;
2541
2542 for (m = m0; m != NULL && totlen > 0; m = m->m_next) {
2543 if (m->m_len == 0)
2544 continue;
2545
2546 len = min(m->m_len, totlen);
2547
2548 if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) {
2549 m_copydata(m, 0, totlen, (caddr_t)&sc->sc_txbuf);
2550 return wi_write_bap(sc, id, off, (caddr_t)&sc->sc_txbuf,
2551 totlen);
2552 }
2553
2554 if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0)
2555 return error;
2556
2557 off += m->m_len;
2558 totlen -= len;
2559 }
2560 return 0;
2561 }
2562
2563 static int
2564 wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
2565 {
2566 int i;
2567
2568 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
2569 device_printf(sc->sc_dev, "failed to allocate %d bytes on NIC\n",
2570 len);
2571 return ENOMEM;
2572 }
2573
2574 for (i = 0; i < WI_TIMEOUT; i++) {
2575 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
2576 break;
2577 if (i == WI_TIMEOUT) {
2578 device_printf(sc->sc_dev, "timeout in alloc\n");
2579 return ETIMEDOUT;
2580 }
2581 DELAY(1);
2582 }
2583 *idp = CSR_READ_2(sc, WI_ALLOC_FID);
2584 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
2585 return 0;
2586 }
2587
2588 static int
2589 wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
2590 {
2591 int error, len;
2592 u_int16_t ltbuf[2];
2593
2594 /* Tell the NIC to enter record read mode. */
2595 error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
2596 if (error)
2597 return error;
2598
2599 error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2600 if (error)
2601 return error;
2602
2603 if (le16toh(ltbuf[1]) != rid) {
2604 device_printf(sc->sc_dev, "record read mismatch, rid=%x, got=%x\n",
2605 rid, le16toh(ltbuf[1]));
2606 return EIO;
2607 }
2608 len = (le16toh(ltbuf[0]) - 1) * 2; /* already got rid */
2609 if (*buflenp < len) {
2610 device_printf(sc->sc_dev, "record buffer is too small, "
2611 "rid=%x, size=%d, len=%d\n",
2612 rid, *buflenp, len);
2613 return ENOSPC;
2614 }
2615 *buflenp = len;
2616 return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
2617 }
2618
2619 static int
2620 wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
2621 {
2622 int error;
2623 u_int16_t ltbuf[2];
2624
2625 ltbuf[0] = htole16((buflen + 1) / 2 + 1); /* includes rid */
2626 ltbuf[1] = htole16(rid);
2627
2628 error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2629 if (error)
2630 return error;
2631 error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
2632 if (error)
2633 return error;
2634
2635 return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
2636 }
2637
2638 static int
2639 wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
2640 {
2641 struct ifnet *ifp = &ic->ic_if;
2642 struct wi_softc *sc = ifp->if_softc;
2643 struct ieee80211_node *ni = ic->ic_bss;
2644 int buflen;
2645 u_int16_t val;
2646 struct wi_ssid ssid;
2647 u_int8_t old_bssid[IEEE80211_ADDR_LEN];
2648
2649 DPRINTF(("%s: %s -> %s\n", __func__,
2650 ieee80211_state_name[ic->ic_state],
2651 ieee80211_state_name[nstate]));
2652
2653 switch (nstate) {
2654 case IEEE80211_S_INIT:
2655 ic->ic_flags &= ~IEEE80211_F_SIBSS;
2656 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2657 return (*sc->sc_newstate)(ic, nstate, arg);
2658
2659 case IEEE80211_S_RUN:
2660 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2661 buflen = IEEE80211_ADDR_LEN;
2662 wi_read_rid(sc, WI_RID_CURRENT_BSSID, ni->ni_bssid, &buflen);
2663 IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid);
2664 buflen = sizeof(val);
2665 wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
2666 /* XXX validate channel */
2667 ni->ni_chan = &ic->ic_channels[le16toh(val)];
2668 #if NBPFILTER > 0
2669 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2670 htole16(ni->ni_chan->ic_freq);
2671 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2672 htole16(ni->ni_chan->ic_flags);
2673 #endif
2674
2675 if (IEEE80211_ADDR_EQ(old_bssid, ni->ni_bssid))
2676 sc->sc_false_syns++;
2677 else
2678 sc->sc_false_syns = 0;
2679
2680 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
2681 ni->ni_esslen = ic->ic_des_esslen;
2682 memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
2683 ni->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B];
2684 ni->ni_intval = ic->ic_lintval;
2685 ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
2686 if (ic->ic_flags & IEEE80211_F_WEPON)
2687 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
2688 } else {
2689 /* XXX check return value */
2690 buflen = sizeof(ssid);
2691 wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen);
2692 ni->ni_esslen = le16toh(ssid.wi_len);
2693 if (ni->ni_esslen > IEEE80211_NWID_LEN)
2694 ni->ni_esslen = IEEE80211_NWID_LEN; /*XXX*/
2695 memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
2696 }
2697 break;
2698
2699 case IEEE80211_S_SCAN:
2700 case IEEE80211_S_AUTH:
2701 case IEEE80211_S_ASSOC:
2702 break;
2703 }
2704
2705 ic->ic_state = nstate; /* NB: skip normal ieee80211 handling */
2706 return 0;
2707 }
2708
2709 static int
2710 wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate)
2711 {
2712 int error = 0;
2713 u_int16_t val[2];
2714
2715 if (!sc->sc_enabled)
2716 return ENXIO;
2717 switch (sc->sc_firmware_type) {
2718 case WI_LUCENT:
2719 (void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
2720 break;
2721 case WI_INTERSIL:
2722 val[0] = chanmask; /* channel */
2723 val[1] = txrate; /* tx rate */
2724 error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
2725 break;
2726 case WI_SYMBOL:
2727 /*
2728 * XXX only supported on 3.x ?
2729 */
2730 val[0] = BSCAN_BCAST | BSCAN_ONETIME;
2731 error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
2732 val, sizeof(val[0]));
2733 break;
2734 }
2735 if (error == 0) {
2736 sc->sc_scan_timer = WI_SCAN_WAIT;
2737 sc->sc_ic.ic_if.if_timer = 1;
2738 DPRINTF(("wi_scan_ap: start scanning, "
2739 "chamask 0x%x txrate 0x%x\n", chanmask, txrate));
2740 }
2741 return error;
2742 }
2743
2744 static void
2745 wi_scan_result(struct wi_softc *sc, int fid, int cnt)
2746 {
2747 #define N(a) (sizeof (a) / sizeof (a[0]))
2748 int i, naps, off, szbuf;
2749 struct wi_scan_header ws_hdr; /* Prism2 header */
2750 struct wi_scan_data_p2 ws_dat; /* Prism2 scantable*/
2751 struct wi_apinfo *ap;
2752
2753 off = sizeof(u_int16_t) * 2;
2754 memset(&ws_hdr, 0, sizeof(ws_hdr));
2755 switch (sc->sc_firmware_type) {
2756 case WI_INTERSIL:
2757 wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
2758 off += sizeof(ws_hdr);
2759 szbuf = sizeof(struct wi_scan_data_p2);
2760 break;
2761 case WI_SYMBOL:
2762 szbuf = sizeof(struct wi_scan_data_p2) + 6;
2763 break;
2764 case WI_LUCENT:
2765 szbuf = sizeof(struct wi_scan_data);
2766 break;
2767 default:
2768 device_printf(sc->sc_dev,
2769 "wi_scan_result: unknown firmware type %u\n",
2770 sc->sc_firmware_type);
2771 naps = 0;
2772 goto done;
2773 }
2774 naps = (cnt * 2 + 2 - off) / szbuf;
2775 if (naps > N(sc->sc_aps))
2776 naps = N(sc->sc_aps);
2777 sc->sc_naps = naps;
2778 /* Read Data */
2779 ap = sc->sc_aps;
2780 memset(&ws_dat, 0, sizeof(ws_dat));
2781 for (i = 0; i < naps; i++, ap++) {
2782 wi_read_bap(sc, fid, off, &ws_dat,
2783 (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
2784 DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
2785 ether_sprintf(ws_dat.wi_bssid)));
2786 off += szbuf;
2787 ap->scanreason = le16toh(ws_hdr.wi_reason);
2788 memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
2789 ap->channel = le16toh(ws_dat.wi_chid);
2790 ap->signal = le16toh(ws_dat.wi_signal);
2791 ap->noise = le16toh(ws_dat.wi_noise);
2792 ap->quality = ap->signal - ap->noise;
2793 ap->capinfo = le16toh(ws_dat.wi_capinfo);
2794 ap->interval = le16toh(ws_dat.wi_interval);
2795 ap->rate = le16toh(ws_dat.wi_rate);
2796 ap->namelen = le16toh(ws_dat.wi_namelen);
2797 if (ap->namelen > sizeof(ap->name))
2798 ap->namelen = sizeof(ap->name);
2799 memcpy(ap->name, ws_dat.wi_name, ap->namelen);
2800 }
2801 done:
2802 /* Done scanning */
2803 sc->sc_scan_timer = 0;
2804 DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps));
2805 #undef N
2806 }
2807
2808 static void
2809 wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
2810 {
2811 ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
2812 ni ? ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL : -1, rssi);
2813 printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
2814 le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
2815 le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
2816 printf(" rx_signal %u rx_rate %u rx_flow %u\n",
2817 wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow);
2818 printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
2819 wh->wi_tx_rtry, wh->wi_tx_rate,
2820 le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len));
2821 printf(" ehdr dst %6D src %6D type 0x%x\n",
2822 wh->wi_ehdr.ether_dhost, ":", wh->wi_ehdr.ether_shost, ":",
2823 wh->wi_ehdr.ether_type);
2824 }
2825
2826 int
2827 wi_alloc(device_t dev, int rid)
2828 {
2829 struct wi_softc *sc = device_get_softc(dev);
2830
2831 if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
2832 sc->iobase_rid = rid;
2833 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
2834 &sc->iobase_rid, 0, ~0, (1 << 6),
2835 rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
2836 if (!sc->iobase) {
2837 device_printf(dev, "No I/O space?!\n");
2838 return (ENXIO);
2839 }
2840
2841 sc->wi_io_addr = rman_get_start(sc->iobase);
2842 sc->wi_btag = rman_get_bustag(sc->iobase);
2843 sc->wi_bhandle = rman_get_bushandle(sc->iobase);
2844 } else {
2845 sc->mem_rid = rid;
2846 sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
2847 &sc->mem_rid, RF_ACTIVE);
2848
2849 if (!sc->mem) {
2850 device_printf(dev, "No Mem space on prism2.5?\n");
2851 return (ENXIO);
2852 }
2853
2854 sc->wi_btag = rman_get_bustag(sc->mem);
2855 sc->wi_bhandle = rman_get_bushandle(sc->mem);
2856 }
2857
2858
2859 sc->irq_rid = 0;
2860 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
2861 RF_ACTIVE |
2862 ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
2863
2864 if (!sc->irq) {
2865 wi_free(dev);
2866 device_printf(dev, "No irq?!\n");
2867 return (ENXIO);
2868 }
2869
2870 sc->sc_dev = dev;
2871 sc->sc_unit = device_get_unit(dev);
2872
2873 return (0);
2874 }
2875
2876 void
2877 wi_free(device_t dev)
2878 {
2879 struct wi_softc *sc = device_get_softc(dev);
2880
2881 if (sc->iobase != NULL) {
2882 bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
2883 sc->iobase = NULL;
2884 }
2885 if (sc->irq != NULL) {
2886 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
2887 sc->irq = NULL;
2888 }
2889 if (sc->mem != NULL) {
2890 bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
2891 sc->mem = NULL;
2892 }
2893
2894 return;
2895 }
2896
2897 static int
2898 wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
2899 {
2900 int error = 0;
2901
2902 wreq->wi_len = 1;
2903
2904 switch (wreq->wi_type) {
2905 case WI_DEBUG_SLEEP:
2906 wreq->wi_len++;
2907 wreq->wi_val[0] = sc->wi_debug.wi_sleep;
2908 break;
2909 case WI_DEBUG_DELAYSUPP:
2910 wreq->wi_len++;
2911 wreq->wi_val[0] = sc->wi_debug.wi_delaysupp;
2912 break;
2913 case WI_DEBUG_TXSUPP:
2914 wreq->wi_len++;
2915 wreq->wi_val[0] = sc->wi_debug.wi_txsupp;
2916 break;
2917 case WI_DEBUG_MONITOR:
2918 wreq->wi_len++;
2919 wreq->wi_val[0] = sc->wi_debug.wi_monitor;
2920 break;
2921 case WI_DEBUG_LEDTEST:
2922 wreq->wi_len += 3;
2923 wreq->wi_val[0] = sc->wi_debug.wi_ledtest;
2924 wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0;
2925 wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1;
2926 break;
2927 case WI_DEBUG_CONTTX:
2928 wreq->wi_len += 2;
2929 wreq->wi_val[0] = sc->wi_debug.wi_conttx;
2930 wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0;
2931 break;
2932 case WI_DEBUG_CONTRX:
2933 wreq->wi_len++;
2934 wreq->wi_val[0] = sc->wi_debug.wi_contrx;
2935 break;
2936 case WI_DEBUG_SIGSTATE:
2937 wreq->wi_len += 2;
2938 wreq->wi_val[0] = sc->wi_debug.wi_sigstate;
2939 wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0;
2940 break;
2941 case WI_DEBUG_CONFBITS:
2942 wreq->wi_len += 2;
2943 wreq->wi_val[0] = sc->wi_debug.wi_confbits;
2944 wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0;
2945 break;
2946 default:
2947 error = EIO;
2948 break;
2949 }
2950
2951 return (error);
2952 }
2953
2954 static int
2955 wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
2956 {
2957 int error = 0;
2958 u_int16_t cmd, param0 = 0, param1 = 0;
2959
2960 switch (wreq->wi_type) {
2961 case WI_DEBUG_RESET:
2962 case WI_DEBUG_INIT:
2963 case WI_DEBUG_CALENABLE:
2964 break;
2965 case WI_DEBUG_SLEEP:
2966 sc->wi_debug.wi_sleep = 1;
2967 break;
2968 case WI_DEBUG_WAKE:
2969 sc->wi_debug.wi_sleep = 0;
2970 break;
2971 case WI_DEBUG_CHAN:
2972 param0 = wreq->wi_val[0];
2973 break;
2974 case WI_DEBUG_DELAYSUPP:
2975 sc->wi_debug.wi_delaysupp = 1;
2976 break;
2977 case WI_DEBUG_TXSUPP:
2978 sc->wi_debug.wi_txsupp = 1;
2979 break;
2980 case WI_DEBUG_MONITOR:
2981 sc->wi_debug.wi_monitor = 1;
2982 break;
2983 case WI_DEBUG_LEDTEST:
2984 param0 = wreq->wi_val[0];
2985 param1 = wreq->wi_val[1];
2986 sc->wi_debug.wi_ledtest = 1;
2987 sc->wi_debug.wi_ledtest_param0 = param0;
2988 sc->wi_debug.wi_ledtest_param1 = param1;
2989 break;
2990 case WI_DEBUG_CONTTX:
2991 param0 = wreq->wi_val[0];
2992 sc->wi_debug.wi_conttx = 1;
2993 sc->wi_debug.wi_conttx_param0 = param0;
2994 break;
2995 case WI_DEBUG_STOPTEST:
2996 sc->wi_debug.wi_delaysupp = 0;
2997 sc->wi_debug.wi_txsupp = 0;
2998 sc->wi_debug.wi_monitor = 0;
2999 sc->wi_debug.wi_ledtest = 0;
3000 sc->wi_debug.wi_ledtest_param0 = 0;
3001 sc->wi_debug.wi_ledtest_param1 = 0;
3002 sc->wi_debug.wi_conttx = 0;
3003 sc->wi_debug.wi_conttx_param0 = 0;
3004 sc->wi_debug.wi_contrx = 0;
3005 sc->wi_debug.wi_sigstate = 0;
3006 sc->wi_debug.wi_sigstate_param0 = 0;
3007 break;
3008 case WI_DEBUG_CONTRX:
3009 sc->wi_debug.wi_contrx = 1;
3010 break;
3011 case WI_DEBUG_SIGSTATE:
3012 param0 = wreq->wi_val[0];
3013 sc->wi_debug.wi_sigstate = 1;
3014 sc->wi_debug.wi_sigstate_param0 = param0;
3015 break;
3016 case WI_DEBUG_CONFBITS:
3017 param0 = wreq->wi_val[0];
3018 param1 = wreq->wi_val[1];
3019 sc->wi_debug.wi_confbits = param0;
3020 sc->wi_debug.wi_confbits_param0 = param1;
3021 break;
3022 default:
3023 error = EIO;
3024 break;
3025 }
3026
3027 if (error)
3028 return (error);
3029
3030 cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3031 error = wi_cmd(sc, cmd, param0, param1, 0);
3032
3033 return (error);
3034 }
3035
3036 #if __FreeBSD_version >= 500000
3037 /*
3038 * Special routines to download firmware for Symbol CF card.
3039 * XXX: This should be modified generic into any PRISM-2 based card.
3040 */
3041
3042 #define WI_SBCF_PDIADDR 0x3100
3043
3044 /* unaligned load little endian */
3045 #define GETLE32(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
3046 #define GETLE16(p) ((p)[0] | ((p)[1]<<8))
3047
3048 int
3049 wi_symbol_load_firm(struct wi_softc *sc, const void *primsym, int primlen,
3050 const void *secsym, int seclen)
3051 {
3052 uint8_t ebuf[256];
3053 int i;
3054
3055 /* load primary code and run it */
3056 wi_symbol_set_hcr(sc, WI_HCR_EEHOLD);
3057 if (wi_symbol_write_firm(sc, primsym, primlen, NULL, 0))
3058 return EIO;
3059 wi_symbol_set_hcr(sc, WI_HCR_RUN);
3060 for (i = 0; ; i++) {
3061 if (i == 10)
3062 return ETIMEDOUT;
3063 tsleep(sc, PWAIT, "wiinit", 1);
3064 if (CSR_READ_2(sc, WI_CNTL) == WI_CNTL_AUX_ENA_STAT)
3065 break;
3066 /* write the magic key value to unlock aux port */
3067 CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0);
3068 CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1);
3069 CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2);
3070 CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL);
3071 }
3072
3073 /* issue read EEPROM command: XXX copied from wi_cmd() */
3074 CSR_WRITE_2(sc, WI_PARAM0, 0);
3075 CSR_WRITE_2(sc, WI_PARAM1, 0);
3076 CSR_WRITE_2(sc, WI_PARAM2, 0);
3077 CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE);
3078 for (i = 0; i < WI_TIMEOUT; i++) {
3079 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
3080 break;
3081 DELAY(1);
3082 }
3083 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
3084
3085 CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ);
3086 CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ);
3087 CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA,
3088 (uint16_t *)ebuf, sizeof(ebuf) / 2);
3089 if (GETLE16(ebuf) > sizeof(ebuf))
3090 return EIO;
3091 if (wi_symbol_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf)))
3092 return EIO;
3093 return 0;
3094 }
3095
3096 static int
3097 wi_symbol_write_firm(struct wi_softc *sc, const void *buf, int buflen,
3098 const void *ebuf, int ebuflen)
3099 {
3100 const uint8_t *p, *ep, *q, *eq;
3101 char *tp;
3102 uint32_t addr, id, eid;
3103 int i, len, elen, nblk, pdrlen;
3104
3105 /*
3106 * Parse the header of the firmware image.
3107 */
3108 p = buf;
3109 ep = p + buflen;
3110 while (p < ep && *p++ != ' '); /* FILE: */
3111 while (p < ep && *p++ != ' '); /* filename */
3112 while (p < ep && *p++ != ' '); /* type of the firmware */
3113 nblk = strtoul(p, &tp, 10);
3114 p = tp;
3115 pdrlen = strtoul(p + 1, &tp, 10);
3116 p = tp;
3117 while (p < ep && *p++ != 0x1a); /* skip rest of header */
3118
3119 /*
3120 * Block records: address[4], length[2], data[length];
3121 */
3122 for (i = 0; i < nblk; i++) {
3123 addr = GETLE32(p); p += 4;
3124 len = GETLE16(p); p += 2;
3125 CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
3126 CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
3127 CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
3128 (const uint16_t *)p, len / 2);
3129 p += len;
3130 }
3131
3132 /*
3133 * PDR: id[4], address[4], length[4];
3134 */
3135 for (i = 0; i < pdrlen; ) {
3136 id = GETLE32(p); p += 4; i += 4;
3137 addr = GETLE32(p); p += 4; i += 4;
3138 len = GETLE32(p); p += 4; i += 4;
3139 /* replace PDR entry with the values from EEPROM, if any */
3140 for (q = ebuf, eq = q + ebuflen; q < eq; q += elen * 2) {
3141 elen = GETLE16(q); q += 2;
3142 eid = GETLE16(q); q += 2;
3143 elen--; /* elen includes eid */
3144 if (eid == 0)
3145 break;
3146 if (eid != id)
3147 continue;
3148 CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
3149 CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
3150 CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
3151 (const uint16_t *)q, len / 2);
3152 break;
3153 }
3154 }
3155 return 0;
3156 }
3157
3158 static int
3159 wi_symbol_set_hcr(struct wi_softc *sc, int mode)
3160 {
3161 uint16_t hcr;
3162
3163 CSR_WRITE_2(sc, WI_COR, WI_COR_RESET);
3164 tsleep(sc, PWAIT, "wiinit", 1);
3165 hcr = CSR_READ_2(sc, WI_HCR);
3166 hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE);
3167 CSR_WRITE_2(sc, WI_HCR, hcr);
3168 tsleep(sc, PWAIT, "wiinit", 1);
3169 CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE);
3170 tsleep(sc, PWAIT, "wiinit", 1);
3171 return 0;
3172 }
3173 #endif
Cache object: 0cb6a60661d43e4ffd957b8b849d82de
|