wi.c revision 1.70 1 /* $NetBSD: wi.c,v 1.70 2002/04/14 19:55:23 onoe Exp $ */
2
3 /*
4 * Copyright (c) 1997, 1998, 1999
5 * Bill Paul <wpaul (at) 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 for NetBSD.
37 *
38 * Original FreeBSD driver written by Bill Paul <wpaul (at) 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 both the PCMCIA and ISA versions of the
60 * WaveLAN/IEEE cards. Note however that the ISA card isn't really
61 * anything of the sort: it's actually a PCMCIA bridge adapter
62 * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
63 * inserted. Consequently, you need to use the pccard support for
64 * both the ISA and PCMCIA adapters.
65 */
66
67 /*
68 * FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
69 * Oslo IETF plenary meeting.
70 */
71
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.70 2002/04/14 19:55:23 onoe Exp $");
74
75 #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
76 #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
77
78 #include "bpfilter.h"
79
80 #include <sys/param.h>
81 #include <sys/systm.h>
82 #include <sys/callout.h>
83 #include <sys/device.h>
84 #include <sys/socket.h>
85 #include <sys/mbuf.h>
86 #include <sys/ioctl.h>
87 #include <sys/kernel.h> /* for hz */
88 #include <sys/proc.h>
89
90 #include <net/if.h>
91 #include <net/if_dl.h>
92 #include <net/if_media.h>
93 #include <net/if_ether.h>
94 #include <net/if_ieee80211.h>
95
96 #if NBPFILTER > 0
97 #include <net/bpf.h>
98 #include <net/bpfdesc.h>
99 #endif
100
101 #include <machine/bus.h>
102
103 #include <dev/ic/wi_ieee.h>
104 #include <dev/ic/wireg.h>
105 #include <dev/ic/wivar.h>
106
107 static void wi_reset __P((struct wi_softc *));
108 static int wi_ioctl __P((struct ifnet *, u_long, caddr_t));
109 static void wi_start __P((struct ifnet *));
110 static void wi_watchdog __P((struct ifnet *));
111 static int wi_init __P((struct ifnet *));
112 static void wi_stop __P((struct ifnet *, int));
113 static void wi_rxeof __P((struct wi_softc *));
114 static void wi_txeof __P((struct wi_softc *, int));
115 static void wi_update_stats __P((struct wi_softc *));
116 static void wi_setmulti __P((struct wi_softc *));
117
118 static int wi_cmd __P((struct wi_softc *, int, int));
119 static int wi_read_record __P((struct wi_softc *, struct wi_ltv_gen *));
120 static int wi_write_record __P((struct wi_softc *, struct wi_ltv_gen *));
121 static int wi_read_data __P((struct wi_softc *, int,
122 int, caddr_t, int));
123 static int wi_write_data __P((struct wi_softc *, int,
124 int, caddr_t, int));
125 static int wi_seek __P((struct wi_softc *, int, int, int));
126 static int wi_alloc_nicmem __P((struct wi_softc *, int, int *));
127 static void wi_inquire __P((void *));
128 static void wi_wait_scan __P((void *));
129 static int wi_setdef __P((struct wi_softc *, struct wi_req *));
130 static int wi_getdef __P((struct wi_softc *, struct wi_req *));
131 static int wi_mgmt_xmit __P((struct wi_softc *, caddr_t, int));
132
133 static int wi_media_change __P((struct ifnet *));
134 static void wi_media_status __P((struct ifnet *, struct ifmediareq *));
135
136 static void wi_get_id __P((struct wi_softc *));
137
138 static int wi_set_ssid __P((struct ieee80211_nwid *, u_int8_t *, int));
139 static void wi_request_fill_ssid __P((struct wi_req *,
140 struct ieee80211_nwid *));
141 static int wi_write_ssid __P((struct wi_softc *, int, struct wi_req *,
142 struct ieee80211_nwid *));
143 static int wi_set_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
144 static int wi_get_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
145 static int wi_sync_media __P((struct wi_softc *, int, int));
146 static int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
147 static int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
148
149 struct wi_card_ident wi_card_ident[] = {
150 /* CARD_ID CARD_NAME FIRM_TYPE */
151 { WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT },
152 { WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT },
153 { WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT },
154 { WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL },
155 { WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL },
156 { WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL },
157 { WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL },
158 { WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL },
159 { WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL },
160 { WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL },
161 { WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL },
162 { WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL },
163 { WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
164 { WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
165 { WI_NIC_3842_PCMCIA_ATM_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
166 { WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
167 { WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
168 { WI_NIC_3842_MINI_ATM_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
169 { WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
170 { WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
171 { WI_NIC_3842_PCI_ATM_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
172 { WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL },
173 { WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL },
174 { WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL },
175 { WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL },
176 { 0, NULL, 0 },
177 };
178
179 int
180 wi_attach(sc)
181 struct wi_softc *sc;
182 {
183 struct ifnet *ifp = sc->sc_ifp;
184 struct wi_ltv_macaddr mac;
185 struct wi_ltv_gen gen;
186 static const u_int8_t empty_macaddr[ETHER_ADDR_LEN] = {
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
188 };
189 int s;
190
191 s = splnet();
192
193 callout_init(&sc->wi_inquire_ch);
194 callout_init(&sc->wi_scan_sh);
195
196 /* Make sure interrupts are disabled. */
197 CSR_WRITE_2(sc, WI_INT_EN, 0);
198 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
199
200 /* Reset the NIC. */
201 wi_reset(sc);
202
203 memset(&mac, 0, sizeof(mac));
204 /* Read the station address. */
205 mac.wi_type = WI_RID_MAC_NODE;
206 mac.wi_len = 4;
207 wi_read_record(sc, (struct wi_ltv_gen *)&mac);
208 memcpy(sc->sc_macaddr, mac.wi_mac_addr, ETHER_ADDR_LEN);
209
210 /*
211 * Check if we got anything meaningful.
212 *
213 * Is it really enough just checking against null ethernet address?
214 * Or, check against possible vendor? XXX.
215 */
216 if (memcmp(sc->sc_macaddr, empty_macaddr, ETHER_ADDR_LEN) == 0) {
217 printf("could not get mac address, attach failed\n");
218 splx(s);
219 return 1;
220 }
221
222 printf(" 802.11 address %s\n", ether_sprintf(sc->sc_macaddr));
223
224 /* Read NIC identification */
225 wi_get_id(sc);
226
227 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
228 ifp->if_softc = sc;
229 ifp->if_start = wi_start;
230 ifp->if_ioctl = wi_ioctl;
231 ifp->if_watchdog = wi_watchdog;
232 ifp->if_init = wi_init;
233 ifp->if_stop = wi_stop;
234 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
235 #ifdef IFF_NOTRAILERS
236 ifp->if_flags |= IFF_NOTRAILERS;
237 #endif
238 IFQ_SET_READY(&ifp->if_snd);
239
240 (void)wi_set_ssid(&sc->wi_nodeid, WI_DEFAULT_NODENAME,
241 sizeof(WI_DEFAULT_NODENAME) - 1);
242 (void)wi_set_ssid(&sc->wi_netid, WI_DEFAULT_NETNAME,
243 sizeof(WI_DEFAULT_NETNAME) - 1);
244 (void)wi_set_ssid(&sc->wi_ibssid, WI_DEFAULT_IBSS,
245 sizeof(WI_DEFAULT_IBSS) - 1);
246
247 sc->wi_portnum = WI_DEFAULT_PORT;
248 sc->wi_ptype = WI_PORTTYPE_BSS;
249 sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
250 sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
251 sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
252 sc->wi_max_data_len = WI_DEFAULT_DATALEN;
253 sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
254 sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
255 sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
256 sc->wi_roaming = WI_DEFAULT_ROAMING;
257 sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
258
259 /*
260 * Read the default channel from the NIC. This may vary
261 * depending on the country where the NIC was purchased, so
262 * we can't hard-code a default and expect it to work for
263 * everyone.
264 */
265 gen.wi_type = WI_RID_OWN_CHNL;
266 gen.wi_len = 2;
267 wi_read_record(sc, &gen);
268 sc->wi_channel = le16toh(gen.wi_val);
269
270 memset((char *)&sc->wi_stats, 0, sizeof(sc->wi_stats));
271
272 /* AP info was filled with 0 */
273 memset((char *)&sc->wi_aps, 0, sizeof(sc->wi_aps));
274 sc->wi_scanning=0;
275 sc->wi_naps=0;
276
277 /*
278 * Find out if we support WEP on this card.
279 */
280 gen.wi_type = WI_RID_WEP_AVAIL;
281 gen.wi_len = 2;
282 wi_read_record(sc, &gen);
283 sc->wi_has_wep = le16toh(gen.wi_val);
284
285 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
286 #define ADD(m, c) ifmedia_add(&sc->sc_media, (m), (c), NULL)
287 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
288 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
289 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
290 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
291 IFM_IEEE80211_ADHOC, 0), 0);
292 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
293 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
294 IFM_IEEE80211_ADHOC, 0), 0);
295 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
296 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
297 IFM_IEEE80211_ADHOC, 0), 0);
298 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
299 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
300 IFM_IEEE80211_ADHOC, 0), 0);
301 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
302 #undef ADD
303 ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
304
305 /*
306 * Call MI attach routines.
307 */
308 if_attach(ifp);
309 ether_ifattach(ifp, mac.wi_mac_addr);
310
311 ifp->if_baudrate = IF_Mbps(2);
312
313 /* Attach is successful. */
314 sc->sc_attached = 1;
315
316 splx(s);
317 return 0;
318 }
319
320 static void wi_rxeof(sc)
321 struct wi_softc *sc;
322 {
323 struct ifnet *ifp;
324 struct ether_header *eh;
325 struct wi_frame rx_frame;
326 struct mbuf *m;
327 int id;
328
329 ifp = sc->sc_ifp;
330
331 id = CSR_READ_2(sc, WI_RX_FID);
332
333 /* First read in the frame header */
334 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
335 ifp->if_ierrors++;
336 return;
337 }
338
339 /*
340 * Drop undecryptable or packets with receive errors here
341 */
342 if (le16toh(rx_frame.wi_status) & WI_STAT_ERRSTAT) {
343 ifp->if_ierrors++;
344 return;
345 }
346
347 MGETHDR(m, M_DONTWAIT, MT_DATA);
348 if (m == NULL) {
349 ifp->if_ierrors++;
350 return;
351 }
352 MCLGET(m, M_DONTWAIT);
353 if (!(m->m_flags & M_EXT)) {
354 m_freem(m);
355 ifp->if_ierrors++;
356 return;
357 }
358
359 /* Align the data after the ethernet header */
360 m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header))
361 - sizeof(struct ether_header);
362
363 eh = mtod(m, struct ether_header *);
364 m->m_pkthdr.rcvif = ifp;
365
366 if (le16toh(rx_frame.wi_status) == WI_STAT_1042 ||
367 le16toh(rx_frame.wi_status) == WI_STAT_TUNNEL ||
368 le16toh(rx_frame.wi_status) == WI_STAT_WMP_MSG) {
369 if ((le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > MCLBYTES) {
370 printf("%s: oversized packet received "
371 "(wi_dat_len=%d, wi_status=0x%x)\n",
372 sc->sc_dev.dv_xname,
373 le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
374 m_freem(m);
375 ifp->if_ierrors++;
376 return;
377 }
378 m->m_pkthdr.len = m->m_len =
379 le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
380
381 memcpy((char *)&eh->ether_dhost, (char *)&rx_frame.wi_dst_addr,
382 ETHER_ADDR_LEN);
383 memcpy((char *)&eh->ether_shost, (char *)&rx_frame.wi_src_addr,
384 ETHER_ADDR_LEN);
385 memcpy((char *)&eh->ether_type, (char *)&rx_frame.wi_type,
386 sizeof(u_int16_t));
387
388 if (wi_read_data(sc, id, WI_802_11_OFFSET,
389 mtod(m, caddr_t) + sizeof(struct ether_header),
390 m->m_len + 2)) {
391 m_freem(m);
392 ifp->if_ierrors++;
393 return;
394 }
395 } else {
396 if ((le16toh(rx_frame.wi_dat_len) +
397 sizeof(struct ether_header)) > MCLBYTES) {
398 printf("%s: oversized packet received "
399 "(wi_dat_len=%d, wi_status=0x%x)\n",
400 sc->sc_dev.dv_xname,
401 le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
402 m_freem(m);
403 ifp->if_ierrors++;
404 return;
405 }
406 m->m_pkthdr.len = m->m_len =
407 le16toh(rx_frame.wi_dat_len) + sizeof(struct ether_header);
408
409 if (wi_read_data(sc, id, WI_802_3_OFFSET,
410 mtod(m, caddr_t), m->m_len + 2)) {
411 m_freem(m);
412 ifp->if_ierrors++;
413 return;
414 }
415 }
416
417 ifp->if_ipackets++;
418
419 #if NBPFILTER > 0
420 /* Handle BPF listeners. */
421 if (ifp->if_bpf)
422 bpf_mtap(ifp->if_bpf, m);
423 #endif
424
425 /* Receive packet. */
426 (*ifp->if_input)(ifp, m);
427 }
428
429 static void wi_txeof(sc, status)
430 struct wi_softc *sc;
431 int status;
432 {
433 struct ifnet *ifp = sc->sc_ifp;
434
435 ifp->if_timer = 0;
436 ifp->if_flags &= ~IFF_OACTIVE;
437
438 if (status & WI_EV_TX_EXC)
439 ifp->if_oerrors++;
440 else
441 ifp->if_opackets++;
442
443 return;
444 }
445
446 void wi_inquire(xsc)
447 void *xsc;
448 {
449 struct wi_softc *sc;
450 struct ifnet *ifp;
451 int s;
452
453 sc = xsc;
454 ifp = &sc->sc_ethercom.ec_if;
455
456 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
457 return;
458
459 KASSERT(sc->sc_enabled);
460
461 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
462
463 /* Don't do this while we're transmitting */
464 if (ifp->if_flags & IFF_OACTIVE)
465 return;
466
467 s = splnet();
468 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
469 splx(s);
470 }
471
472 void wi_wait_scan(xsc)
473 void *xsc;
474 {
475 struct wi_softc *sc;
476 struct ifnet *ifp;
477 int s, result;
478
479 sc = xsc;
480 ifp = &sc->sc_ethercom.ec_if;
481
482 /* If not scanning, ignore */
483 if (!sc->wi_scanning)
484 return;
485
486 s = splnet();
487
488 /* Wait for sending complete to make INQUIRE */
489 if (ifp->if_flags & IFF_OACTIVE) {
490 callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
491 splx(s);
492 return;
493 }
494
495 /* try INQUIRE */
496 result = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS);
497 if (result == ETIMEDOUT)
498 callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
499
500 splx(s);
501 }
502
503 void wi_update_stats(sc)
504 struct wi_softc *sc;
505 {
506 struct wi_ltv_gen gen;
507 struct wi_scan_header ap2_header; /* Prism2 header */
508 struct wi_scan_data_p2 ap2; /* Prism2 scantable*/
509 struct wi_scan_data ap; /* Lucent scantable */
510 struct wi_assoc assoc; /* Association Status */
511 u_int16_t id;
512 struct ifnet *ifp;
513 u_int32_t *ptr;
514 int len, naps, i, j;
515 u_int16_t t;
516
517 ifp = &sc->sc_ethercom.ec_if;
518
519 id = CSR_READ_2(sc, WI_INFO_FID);
520
521 if (wi_seek(sc, id, 0, WI_BAP1)) {
522 return;
523 }
524
525 gen.wi_len = CSR_READ_2(sc, WI_DATA1);
526 gen.wi_type = CSR_READ_2(sc, WI_DATA1);
527
528 switch (gen.wi_type) {
529 case WI_INFO_SCAN_RESULTS:
530 if (gen.wi_len <= 3) {
531 sc->wi_naps = 0;
532 sc->wi_scanning = 0;
533 break;
534 }
535 switch (sc->sc_firmware_type) {
536 case WI_INTERSIL:
537 naps = 2 * (gen.wi_len - 3) / sizeof(ap2);
538 naps = naps > MAXAPINFO ? MAXAPINFO : naps;
539 sc->wi_naps = naps;
540 /* Read Header */
541 for(j=0; j < sizeof(ap2_header) / 2; j++)
542 ((u_int16_t *)&ap2_header)[j] =
543 CSR_READ_2(sc, WI_DATA1);
544 /* Read Data */
545 for (i=0; i < naps; i++) {
546 for(j=0; j < sizeof(ap2) / 2; j++)
547 ((u_int16_t *)&ap2)[j] =
548 CSR_READ_2(sc, WI_DATA1);
549 /* unswap 8 bit data fields: */
550 for(j=0;j<sizeof(ap.wi_bssid)/2;j++)
551 LE16TOH(((u_int16_t *)&ap.wi_bssid[0])[j]);
552 for(j=0;j<sizeof(ap.wi_name)/2;j++)
553 LE16TOH(((u_int16_t *)&ap.wi_name[0])[j]);
554 sc->wi_aps[i].scanreason = ap2_header.wi_reason;
555 memcpy(sc->wi_aps[i].bssid, ap2.wi_bssid, 6);
556 sc->wi_aps[i].channel = ap2.wi_chid;
557 sc->wi_aps[i].signal = ap2.wi_signal;
558 sc->wi_aps[i].noise = ap2.wi_noise;
559 sc->wi_aps[i].quality = ap2.wi_signal - ap2.wi_noise;
560 sc->wi_aps[i].capinfo = ap2.wi_capinfo;
561 sc->wi_aps[i].interval = ap2.wi_interval;
562 sc->wi_aps[i].rate = ap2.wi_rate;
563 if (ap2.wi_namelen > 32)
564 ap2.wi_namelen = 32;
565 sc->wi_aps[i].namelen = ap2.wi_namelen;
566 memcpy(sc->wi_aps[i].name, ap2.wi_name,
567 ap2.wi_namelen);
568 }
569 break;
570
571 case WI_LUCENT:
572 naps = 2 * gen.wi_len / sizeof(ap);
573 naps = naps > MAXAPINFO ? MAXAPINFO : naps;
574 sc->wi_naps = naps;
575 /* Read Data*/
576 for (i=0; i < naps; i++) {
577 for(j=0; j < sizeof(ap) / 2; j++)
578 ((u_int16_t *)&ap)[j] =
579 CSR_READ_2(sc, WI_DATA1);
580 /* unswap 8 bit data fields: */
581 for(j=0;j<sizeof(ap.wi_bssid)/2;j++)
582 HTOLE16(((u_int16_t *)&ap.wi_bssid[0])[j]);
583 for(j=0;j<sizeof(ap.wi_name)/2;j++)
584 HTOLE16(((u_int16_t *)&ap.wi_name[0])[j]);
585 memcpy(sc->wi_aps[i].bssid, ap.wi_bssid, 6);
586 sc->wi_aps[i].channel = ap.wi_chid;
587 sc->wi_aps[i].signal = ap.wi_signal;
588 sc->wi_aps[i].noise = ap.wi_noise;
589 sc->wi_aps[i].quality = ap.wi_signal - ap.wi_noise;
590 sc->wi_aps[i].capinfo = ap.wi_capinfo;
591 sc->wi_aps[i].interval = ap.wi_interval;
592 if (ap.wi_namelen > 32)
593 ap.wi_namelen = 32;
594 sc->wi_aps[i].namelen = ap.wi_namelen;
595 memcpy(sc->wi_aps[i].name, ap.wi_name,
596 ap.wi_namelen);
597 }
598 break;
599 case WI_SYMBOL:
600 /* unknown */
601 break;
602 }
603 /* Done scanning */
604 sc->wi_scanning = 0;
605 break;
606
607 case WI_INFO_COUNTERS:
608 /* some card versions have a larger stats structure */
609 len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
610 gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
611 ptr = (u_int32_t *)&sc->wi_stats;
612
613 for (i = 0; i < len; i++) {
614 t = CSR_READ_2(sc, WI_DATA1);
615 #ifdef WI_HERMES_STATS_WAR
616 if (t > 0xF000)
617 t = ~t & 0xFFFF;
618 #endif
619 ptr[i] += t;
620 }
621
622 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
623 sc->wi_stats.wi_tx_multi_retries +
624 sc->wi_stats.wi_tx_retry_limit;
625 break;
626
627 case WI_INFO_LINK_STAT: {
628 static char *msg[] = {
629 "connected",
630 "disconnected",
631 "AP change",
632 "AP out of range",
633 "AP in range",
634 "Association Failed"
635 };
636
637 if (gen.wi_len != 2) {
638 #ifdef WI_DEBUG
639 printf("WI_INFO_LINK_STAT: len=%d\n", gen.wi_len);
640 #endif
641 break;
642 }
643 t = CSR_READ_2(sc, WI_DATA1);
644 if ((t < 1) || (t > 6)) {
645 #ifdef WI_DEBUG
646 printf("WI_INFO_LINK_STAT: status %d\n", t);
647 #endif
648 break;
649 }
650 /*
651 * Some cards issue streams of "connected" messages while
652 * trying to find a peer. Don't bother the user with this
653 * unless he is debugging.
654 */
655 if (ifp->if_flags & IFF_DEBUG)
656 printf("%s: %s\n", sc->sc_dev.dv_xname, msg[t - 1]);
657 break;
658 }
659
660 case WI_INFO_ASSOC_STAT: {
661 static char *msg[] = {
662 "STA Associated",
663 "STA Reassociated",
664 "STA Disassociated",
665 "Association Failure",
666 "Authentication Failed"
667 };
668 if (gen.wi_len != 10)
669 break;
670 for (i=0; i < gen.wi_len - 1; i++)
671 ((u_int16_t *)&assoc)[i] = CSR_READ_2(sc, WI_DATA1);
672 /* unswap 8 bit data fields: */
673 for(j=0;j<sizeof(assoc.wi_assoc_sta)/2;j++)
674 HTOLE16(((u_int16_t *)&assoc.wi_assoc_sta[0])[j]);
675 for(j=0;j<sizeof(assoc.wi_assoc_osta)/2;j++)
676 HTOLE16(((u_int16_t *)&assoc.wi_assoc_osta[0])[j]);
677 switch (assoc.wi_assoc_stat) {
678 case ASSOC:
679 case DISASSOC:
680 case ASSOCFAIL:
681 case AUTHFAIL:
682 printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x\n",
683 sc->sc_dev.dv_xname,
684 msg[assoc.wi_assoc_stat - 1],
685 assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
686 assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
687 assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff);
688 break;
689 case REASSOC:
690 printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x, "
691 "OldAP = %02x:%02x:%02x:%02x:%02x:%02x\n",
692 sc->sc_dev.dv_xname, msg[assoc.wi_assoc_stat - 1],
693 assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
694 assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
695 assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff,
696 assoc.wi_assoc_osta[0]&0xff, assoc.wi_assoc_osta[1]&0xff,
697 assoc.wi_assoc_osta[2]&0xff, assoc.wi_assoc_osta[3]&0xff,
698 assoc.wi_assoc_osta[4]&0xff, assoc.wi_assoc_osta[5]&0xff);
699 break;
700 }
701 }
702 default:
703 #ifdef WI_DEBUG
704 printf("%s: got info type: 0x%04x len=0x%04x\n",
705 sc->sc_dev.dv_xname, gen.wi_type,gen.wi_len);
706 #endif
707 #if 0
708 for (i = 0; i < gen.wi_len; i++) {
709 t = CSR_READ_2(sc, WI_DATA1);
710 printf("[0x%02x] = 0x%04x\n", i, t);
711 }
712 #endif
713 break;
714 }
715 }
716
717 int wi_intr(arg)
718 void *arg;
719 {
720 struct wi_softc *sc = arg;
721 struct ifnet *ifp;
722 u_int16_t status;
723
724 if (sc->sc_enabled == 0 ||
725 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
726 (sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0)
727 return (0);
728
729 ifp = &sc->sc_ethercom.ec_if;
730
731 if (!(ifp->if_flags & IFF_UP)) {
732 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
733 CSR_WRITE_2(sc, WI_INT_EN, 0);
734 return 1;
735 }
736
737 /* Disable interrupts. */
738 CSR_WRITE_2(sc, WI_INT_EN, 0);
739
740 status = CSR_READ_2(sc, WI_EVENT_STAT);
741 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
742
743 if (status & WI_EV_RX) {
744 wi_rxeof(sc);
745 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
746 }
747
748 if (status & WI_EV_TX) {
749 wi_txeof(sc, status);
750 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
751 }
752
753 if (status & WI_EV_ALLOC) {
754 int id;
755 id = CSR_READ_2(sc, WI_ALLOC_FID);
756 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
757 if (id == sc->wi_tx_data_id)
758 wi_txeof(sc, status);
759 }
760
761 if (status & WI_EV_INFO) {
762 wi_update_stats(sc);
763 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
764 }
765
766 if (status & WI_EV_TX_EXC) {
767 wi_txeof(sc, status);
768 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
769 }
770
771 if (status & WI_EV_INFO_DROP) {
772 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
773 }
774
775 /* Re-enable interrupts. */
776 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
777
778 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
779 wi_start(ifp);
780
781 return 1;
782 }
783
784 /* Must be called at proper protection level! */
785 static int
786 wi_cmd(sc, cmd, val)
787 struct wi_softc *sc;
788 int cmd;
789 int val;
790 {
791 int i, s = 0;
792
793 /* wait for the busy bit to clear */
794 for (i = 0; i < WI_TIMEOUT; i++) {
795 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
796 break;
797 }
798
799 if (i == WI_TIMEOUT) {
800 printf("%s: wi_cmd: BUSY did not clear, cmd=0x%x\n",
801 sc->sc_dev.dv_xname, cmd);
802 return EIO;
803 }
804
805 CSR_WRITE_2(sc, WI_PARAM0, val);
806 CSR_WRITE_2(sc, WI_PARAM1, 0);
807 CSR_WRITE_2(sc, WI_PARAM2, 0);
808 CSR_WRITE_2(sc, WI_COMMAND, cmd);
809
810 /* wait for the cmd completed bit */
811 for (i = 0; i < WI_TIMEOUT; i++) {
812 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
813 break;
814 DELAY(1);
815 }
816
817 /* Ack the command */
818 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
819
820 s = CSR_READ_2(sc, WI_STATUS);
821 if (s & WI_STAT_CMD_RESULT)
822 return(EIO);
823
824 if (i == WI_TIMEOUT) {
825 if (!sc->wi_scanning)
826 printf("%s: command timed out, cmd=0x%x\n",
827 sc->sc_dev.dv_xname, cmd);
828 return(ETIMEDOUT);
829 }
830
831 return(0);
832 }
833
834 static void
835 wi_reset(sc)
836 struct wi_softc *sc;
837 {
838
839 DELAY(100*1000); /* 100 m sec */
840 if (wi_cmd(sc, WI_CMD_INI, 0))
841 printf("%s: init failed\n", sc->sc_dev.dv_xname);
842 CSR_WRITE_2(sc, WI_INT_EN, 0);
843 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
844
845 /* Calibrate timer. */
846 WI_SETVAL(WI_RID_TICK_TIME, 8);
847
848 return;
849 }
850
851 /*
852 * Read an LTV record from the NIC.
853 */
854 static int wi_read_record(sc, ltv)
855 struct wi_softc *sc;
856 struct wi_ltv_gen *ltv;
857 {
858 u_int16_t *ptr;
859 int len, code;
860 struct wi_ltv_gen *oltv, p2ltv;
861
862 if (sc->sc_firmware_type != WI_LUCENT) {
863 oltv = ltv;
864 switch (ltv->wi_type) {
865 case WI_RID_ENCRYPTION:
866 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
867 p2ltv.wi_len = 2;
868 ltv = &p2ltv;
869 break;
870 case WI_RID_TX_CRYPT_KEY:
871 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
872 p2ltv.wi_len = 2;
873 ltv = &p2ltv;
874 break;
875 case WI_RID_ROAMING_MODE:
876 if (sc->sc_firmware_type == WI_INTERSIL)
877 break;
878 /* not supported */
879 ltv->wi_len = 1;
880 return 0;
881 case WI_RID_MICROWAVE_OVEN:
882 /* not supported */
883 ltv->wi_len = 1;
884 return 0;
885 }
886 }
887
888 /* Tell the NIC to enter record read mode. */
889 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
890 return(EIO);
891
892 /* Seek to the record. */
893 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
894 return(EIO);
895
896 /*
897 * Read the length and record type and make sure they
898 * match what we expect (this verifies that we have enough
899 * room to hold all of the returned data).
900 */
901 len = CSR_READ_2(sc, WI_DATA1);
902 if (len > ltv->wi_len)
903 return(ENOSPC);
904 code = CSR_READ_2(sc, WI_DATA1);
905 if (code != ltv->wi_type)
906 return(EIO);
907
908 ltv->wi_len = len;
909 ltv->wi_type = code;
910
911 /* Now read the data. */
912 ptr = <v->wi_val;
913 if (ltv->wi_len > 1)
914 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
915
916 if (sc->sc_firmware_type != WI_LUCENT) {
917 int v;
918
919 switch (oltv->wi_type) {
920 case WI_RID_TX_RATE:
921 case WI_RID_CUR_TX_RATE:
922 switch (le16toh(ltv->wi_val)) {
923 case 1: v = 1; break;
924 case 2: v = 2; break;
925 case 3: v = 6; break;
926 case 4: v = 5; break;
927 case 7: v = 7; break;
928 case 8: v = 11; break;
929 case 15: v = 3; break;
930 default: v = 0x100 + le16toh(ltv->wi_val); break;
931 }
932 oltv->wi_val = htole16(v);
933 break;
934 case WI_RID_ENCRYPTION:
935 oltv->wi_len = 2;
936 if (le16toh(ltv->wi_val) & 0x01)
937 oltv->wi_val = htole16(1);
938 else
939 oltv->wi_val = htole16(0);
940 break;
941 case WI_RID_TX_CRYPT_KEY:
942 oltv->wi_len = 2;
943 oltv->wi_val = ltv->wi_val;
944 break;
945 case WI_RID_AUTH_CNTL:
946 oltv->wi_len = 2;
947 if (le16toh(ltv->wi_val) & 0x01)
948 oltv->wi_val = htole16(1);
949 else if (le16toh(ltv->wi_val) & 0x02)
950 oltv->wi_val = htole16(2);
951 break;
952 }
953 }
954
955 return(0);
956 }
957
958 /*
959 * Same as read, except we inject data instead of reading it.
960 */
961 static int wi_write_record(sc, ltv)
962 struct wi_softc *sc;
963 struct wi_ltv_gen *ltv;
964 {
965 u_int16_t *ptr;
966 int i;
967 struct wi_ltv_gen p2ltv;
968
969 if (sc->sc_firmware_type != WI_LUCENT) {
970 int v;
971
972 switch (ltv->wi_type) {
973 case WI_RID_TX_RATE:
974 p2ltv.wi_type = WI_RID_TX_RATE;
975 p2ltv.wi_len = 2;
976 switch (le16toh(ltv->wi_val)) {
977 case 1: v = 1; break;
978 case 2: v = 2; break;
979 case 3: v = 15; break;
980 case 5: v = 4; break;
981 case 6: v = 3; break;
982 case 7: v = 7; break;
983 case 11: v = 8; break;
984 default: return EINVAL;
985 }
986 p2ltv.wi_val = htole16(v);
987 ltv = &p2ltv;
988 break;
989 case WI_RID_ENCRYPTION:
990 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
991 p2ltv.wi_len = 2;
992 if (le16toh(ltv->wi_val))
993 p2ltv.wi_val = htole16(PRIVACY_INVOKED |
994 EXCLUDE_UNENCRYPTED);
995 else
996 p2ltv.wi_val =
997 htole16(HOST_ENCRYPT | HOST_DECRYPT);
998 ltv = &p2ltv;
999 break;
1000 case WI_RID_TX_CRYPT_KEY:
1001 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1002 p2ltv.wi_len = 2;
1003 p2ltv.wi_val = ltv->wi_val;
1004 ltv = &p2ltv;
1005 break;
1006 case WI_RID_DEFLT_CRYPT_KEYS:
1007 {
1008 int error;
1009 int keylen;
1010 struct wi_ltv_str ws;
1011 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
1012
1013 keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1014
1015 for (i = 0; i < 4; i++) {
1016 memset(&ws, 0, sizeof(ws));
1017 ws.wi_len = (keylen > 5) ? 8 : 4;
1018 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1019 memcpy(ws.wi_str,
1020 &wk->wi_keys[i].wi_keydat, keylen);
1021 error = wi_write_record(sc,
1022 (struct wi_ltv_gen *)&ws);
1023 if (error)
1024 return error;
1025 }
1026 return 0;
1027 }
1028 case WI_RID_AUTH_CNTL:
1029 p2ltv.wi_type = WI_RID_AUTH_CNTL;
1030 p2ltv.wi_len = 2;
1031 if (le16toh(ltv->wi_val) == 1)
1032 p2ltv.wi_val = htole16(0x01);
1033 else if (le16toh(ltv->wi_val) == 2)
1034 p2ltv.wi_val = htole16(0x02);
1035 ltv = &p2ltv;
1036 break;
1037
1038 case WI_RID_ROAMING_MODE:
1039 if (sc->sc_firmware_type == WI_INTERSIL)
1040 break;
1041 /* not supported */
1042 return 0;
1043
1044 case WI_RID_MICROWAVE_OVEN:
1045 /* not supported */
1046 return 0;
1047 }
1048 }
1049
1050 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1051 return(EIO);
1052
1053 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1054 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1055
1056 /* Write data */
1057 ptr = <v->wi_val;
1058 if (ltv->wi_len > 1)
1059 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
1060
1061 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
1062 return(EIO);
1063
1064 return(0);
1065 }
1066
1067 static int wi_seek(sc, id, off, chan)
1068 struct wi_softc *sc;
1069 int id, off, chan;
1070 {
1071 int i;
1072 int selreg, offreg;
1073 int status;
1074
1075 switch (chan) {
1076 case WI_BAP0:
1077 selreg = WI_SEL0;
1078 offreg = WI_OFF0;
1079 break;
1080 case WI_BAP1:
1081 selreg = WI_SEL1;
1082 offreg = WI_OFF1;
1083 break;
1084 default:
1085 printf("%s: invalid data path: %x\n",
1086 sc->sc_dev.dv_xname, chan);
1087 return(EIO);
1088 }
1089
1090 CSR_WRITE_2(sc, selreg, id);
1091 CSR_WRITE_2(sc, offreg, off);
1092
1093 for (i = 0; i < WI_TIMEOUT; i++) {
1094 status = CSR_READ_2(sc, offreg);
1095 if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
1096 break;
1097 }
1098
1099 if (i == WI_TIMEOUT) {
1100 printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
1101 sc->sc_dev.dv_xname, id, off, status);
1102 return(ETIMEDOUT);
1103 }
1104 return(0);
1105 }
1106
1107 static int wi_read_data(sc, id, off, buf, len)
1108 struct wi_softc *sc;
1109 int id, off;
1110 caddr_t buf;
1111 int len;
1112 {
1113 u_int16_t *ptr;
1114
1115 if (wi_seek(sc, id, off, WI_BAP1))
1116 return(EIO);
1117
1118 ptr = (u_int16_t *)buf;
1119 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
1120
1121 return(0);
1122 }
1123
1124 /*
1125 * According to the comments in the HCF Light code, there is a bug in
1126 * the Hermes (or possibly in certain Hermes firmware revisions) where
1127 * the chip's internal autoincrement counter gets thrown off during
1128 * data writes: the autoincrement is missed, causing one data word to
1129 * be overwritten and subsequent words to be written to the wrong memory
1130 * locations. The end result is that we could end up transmitting bogus
1131 * frames without realizing it. The workaround for this is to write a
1132 * couple of extra guard words after the end of the transfer, then
1133 * attempt to read then back. If we fail to locate the guard words where
1134 * we expect them, we preform the transfer over again.
1135 */
1136 static int wi_write_data(sc, id, off, buf, len)
1137 struct wi_softc *sc;
1138 int id, off;
1139 caddr_t buf;
1140 int len;
1141 {
1142 u_int16_t *ptr;
1143
1144 #ifdef WI_HERMES_AUTOINC_WAR
1145 again:
1146 #endif
1147
1148 if (wi_seek(sc, id, off, WI_BAP0))
1149 return(EIO);
1150
1151 ptr = (u_int16_t *)buf;
1152 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
1153
1154 #ifdef WI_HERMES_AUTOINC_WAR
1155 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1156 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1157
1158 if (wi_seek(sc, id, off + len, WI_BAP0))
1159 return(EIO);
1160
1161 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1162 CSR_READ_2(sc, WI_DATA0) != 0x5678)
1163 goto again;
1164 #endif
1165
1166 return(0);
1167 }
1168
1169 /*
1170 * Allocate a region of memory inside the NIC and zero
1171 * it out.
1172 */
1173 static int wi_alloc_nicmem(sc, len, id)
1174 struct wi_softc *sc;
1175 int len;
1176 int *id;
1177 {
1178 int i;
1179
1180 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
1181 printf("%s: failed to allocate %d bytes on NIC\n",
1182 sc->sc_dev.dv_xname, len);
1183 return(ENOMEM);
1184 }
1185
1186 for (i = 0; i < WI_TIMEOUT; i++) {
1187 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1188 break;
1189 }
1190
1191 if (i == WI_TIMEOUT) {
1192 printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
1193 return(ETIMEDOUT);
1194 }
1195
1196 *id = CSR_READ_2(sc, WI_ALLOC_FID);
1197 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1198
1199 if (wi_seek(sc, *id, 0, WI_BAP0)) {
1200 printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
1201 return(EIO);
1202 }
1203
1204 for (i = 0; i < len / 2; i++)
1205 CSR_WRITE_2(sc, WI_DATA0, 0);
1206
1207 return(0);
1208 }
1209
1210 static void wi_setmulti(sc)
1211 struct wi_softc *sc;
1212 {
1213 struct ifnet *ifp;
1214 int i = 0;
1215 struct wi_ltv_mcast mcast;
1216 struct ether_multi *enm;
1217 struct ether_multistep estep;
1218 struct ethercom *ec = &sc->sc_ethercom;
1219
1220 ifp = &sc->sc_ethercom.ec_if;
1221
1222 if ((ifp->if_flags & IFF_PROMISC) != 0) {
1223 allmulti:
1224 ifp->if_flags |= IFF_ALLMULTI;
1225 memset((char *)&mcast, 0, sizeof(mcast));
1226 mcast.wi_type = WI_RID_MCAST_LIST;
1227 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
1228
1229 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1230 return;
1231 }
1232
1233 i = 0;
1234 ETHER_FIRST_MULTI(estep, ec, enm);
1235 while (enm != NULL) {
1236 /* Punt on ranges or too many multicast addresses. */
1237 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
1238 ETHER_ADDR_LEN) != 0 ||
1239 i >= 16)
1240 goto allmulti;
1241
1242 memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo,
1243 ETHER_ADDR_LEN);
1244 i++;
1245 ETHER_NEXT_MULTI(estep, enm);
1246 }
1247
1248 ifp->if_flags &= ~IFF_ALLMULTI;
1249 mcast.wi_type = WI_RID_MCAST_LIST;
1250 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
1251 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1252 }
1253
1254 static int
1255 wi_setdef(sc, wreq)
1256 struct wi_softc *sc;
1257 struct wi_req *wreq;
1258 {
1259 struct sockaddr_dl *sdl;
1260 struct ifnet *ifp;
1261 int error = 0;
1262
1263 ifp = &sc->sc_ethercom.ec_if;
1264
1265 switch(wreq->wi_type) {
1266 case WI_RID_MAC_NODE:
1267 sdl = (struct sockaddr_dl *)ifp->if_sadl;
1268 memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val,
1269 ETHER_ADDR_LEN);
1270 memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN);
1271 break;
1272 case WI_RID_PORTTYPE:
1273 error = wi_sync_media(sc, le16toh(wreq->wi_val[0]), sc->wi_tx_rate);
1274 break;
1275 case WI_RID_TX_RATE:
1276 error = wi_sync_media(sc, sc->wi_ptype, le16toh(wreq->wi_val[0]));
1277 break;
1278 case WI_RID_MAX_DATALEN:
1279 sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
1280 break;
1281 case WI_RID_RTS_THRESH:
1282 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
1283 break;
1284 case WI_RID_SYSTEM_SCALE:
1285 sc->wi_ap_density = le16toh(wreq->wi_val[0]);
1286 break;
1287 case WI_RID_CREATE_IBSS:
1288 if (sc->sc_firmware_type != WI_INTERSIL)
1289 sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
1290 break;
1291 case WI_RID_OWN_CHNL:
1292 sc->wi_channel = le16toh(wreq->wi_val[0]);
1293 break;
1294 case WI_RID_NODENAME:
1295 error = wi_set_ssid(&sc->wi_nodeid,
1296 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1297 break;
1298 case WI_RID_DESIRED_SSID:
1299 error = wi_set_ssid(&sc->wi_netid,
1300 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1301 break;
1302 case WI_RID_OWN_SSID:
1303 error = wi_set_ssid(&sc->wi_ibssid,
1304 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1305 break;
1306 case WI_RID_PM_ENABLED:
1307 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
1308 break;
1309 case WI_RID_MICROWAVE_OVEN:
1310 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
1311 break;
1312 case WI_RID_MAX_SLEEP:
1313 sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
1314 break;
1315 case WI_RID_AUTH_CNTL:
1316 sc->wi_authtype = le16toh(wreq->wi_val[0]);
1317 break;
1318 case WI_RID_ROAMING_MODE:
1319 sc->wi_roaming = le16toh(wreq->wi_val[0]);
1320 break;
1321 case WI_RID_ENCRYPTION:
1322 sc->wi_use_wep = le16toh(wreq->wi_val[0]);
1323 break;
1324 case WI_RID_TX_CRYPT_KEY:
1325 sc->wi_tx_key = le16toh(wreq->wi_val[0]);
1326 break;
1327 case WI_RID_DEFLT_CRYPT_KEYS:
1328 memcpy((char *)&sc->wi_keys, (char *)wreq,
1329 sizeof(struct wi_ltv_keys));
1330 break;
1331 default:
1332 error = EINVAL;
1333 break;
1334 }
1335
1336 return (error);
1337 }
1338
1339 static int
1340 wi_getdef(sc, wreq)
1341 struct wi_softc *sc;
1342 struct wi_req *wreq;
1343 {
1344 struct sockaddr_dl *sdl;
1345 struct ifnet *ifp;
1346 int error = 0;
1347
1348 ifp = &sc->sc_ethercom.ec_if;
1349
1350 wreq->wi_len = 2; /* XXX */
1351 switch (wreq->wi_type) {
1352 case WI_RID_MAC_NODE:
1353 wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
1354 sdl = (struct sockaddr_dl *)ifp->if_sadl;
1355 memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN);
1356 memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
1357 break;
1358 case WI_RID_PORTTYPE:
1359 wreq->wi_val[0] = htole16(sc->wi_ptype);
1360 break;
1361 case WI_RID_TX_RATE:
1362 wreq->wi_val[0] = htole16(sc->wi_tx_rate);
1363 break;
1364 case WI_RID_MAX_DATALEN:
1365 wreq->wi_val[0] = htole16(sc->wi_max_data_len);
1366 break;
1367 case WI_RID_RTS_THRESH:
1368 wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
1369 break;
1370 case WI_RID_SYSTEM_SCALE:
1371 wreq->wi_val[0] = htole16(sc->wi_ap_density);
1372 break;
1373 case WI_RID_CREATE_IBSS:
1374 if (sc->sc_firmware_type != WI_INTERSIL)
1375 wreq->wi_val[0] = htole16(sc->wi_create_ibss);
1376 break;
1377 case WI_RID_OWN_CHNL:
1378 wreq->wi_val[0] = htole16(sc->wi_channel);
1379 break;
1380 case WI_RID_NODENAME:
1381 wi_request_fill_ssid(wreq, &sc->wi_nodeid);
1382 break;
1383 case WI_RID_DESIRED_SSID:
1384 wi_request_fill_ssid(wreq, &sc->wi_netid);
1385 break;
1386 case WI_RID_OWN_SSID:
1387 wi_request_fill_ssid(wreq, &sc->wi_ibssid);
1388 break;
1389 case WI_RID_PM_ENABLED:
1390 wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
1391 break;
1392 case WI_RID_MICROWAVE_OVEN:
1393 wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
1394 break;
1395 case WI_RID_MAX_SLEEP:
1396 wreq->wi_val[0] = htole16(sc->wi_max_sleep);
1397 break;
1398 case WI_RID_AUTH_CNTL:
1399 wreq->wi_val[0] = htole16(sc->wi_authtype);
1400 break;
1401 case WI_RID_ROAMING_MODE:
1402 wreq->wi_val[0] = htole16(sc->wi_roaming);
1403 break;
1404 case WI_RID_WEP_AVAIL:
1405 wreq->wi_val[0] = htole16(sc->wi_has_wep);
1406 break;
1407 case WI_RID_ENCRYPTION:
1408 wreq->wi_val[0] = htole16(sc->wi_use_wep);
1409 break;
1410 case WI_RID_TX_CRYPT_KEY:
1411 wreq->wi_val[0] = htole16(sc->wi_tx_key);
1412 break;
1413 case WI_RID_DEFLT_CRYPT_KEYS:
1414 wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
1415 memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
1416 break;
1417 default:
1418 #if 0
1419 error = EIO;
1420 #else
1421 #ifdef WI_DEBUG
1422 printf("%s: wi_getdef: unknown request %d\n",
1423 sc->sc_dev.dv_xname, wreq->wi_type);
1424 #endif
1425 #endif
1426 break;
1427 }
1428
1429 return (error);
1430 }
1431
1432 static int
1433 wi_ioctl(ifp, command, data)
1434 struct ifnet *ifp;
1435 u_long command;
1436 caddr_t data;
1437 {
1438 int s, error = 0;
1439 int len;
1440 struct wi_softc *sc = ifp->if_softc;
1441 struct wi_req wreq;
1442 struct ifreq *ifr;
1443 struct proc *p = curproc;
1444 struct ieee80211_nwid nwid;
1445
1446 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
1447 return (ENXIO);
1448
1449 s = splnet();
1450
1451 ifr = (struct ifreq *)data;
1452 switch (command) {
1453 case SIOCSIFADDR:
1454 case SIOCGIFADDR:
1455 case SIOCSIFMTU:
1456 error = ether_ioctl(ifp, command, data);
1457 break;
1458 case SIOCSIFFLAGS:
1459 if (ifp->if_flags & IFF_UP) {
1460 if (ifp->if_flags & IFF_RUNNING &&
1461 ifp->if_flags & IFF_PROMISC &&
1462 !(sc->wi_if_flags & IFF_PROMISC)) {
1463 WI_SETVAL(WI_RID_PROMISC, 1);
1464 } else if (ifp->if_flags & IFF_RUNNING &&
1465 !(ifp->if_flags & IFF_PROMISC) &&
1466 sc->wi_if_flags & IFF_PROMISC) {
1467 WI_SETVAL(WI_RID_PROMISC, 0);
1468 }
1469 wi_init(ifp);
1470 } else {
1471 if (ifp->if_flags & IFF_RUNNING) {
1472 wi_stop(ifp, 0);
1473 }
1474 }
1475 sc->wi_if_flags = ifp->if_flags;
1476
1477 if (!(ifp->if_flags & IFF_UP)) {
1478 if (sc->sc_enabled) {
1479 if (sc->sc_disable)
1480 (*sc->sc_disable)(sc);
1481 sc->sc_enabled = 0;
1482 ifp->if_flags &= ~IFF_RUNNING;
1483 }
1484 }
1485 error = 0;
1486 break;
1487 case SIOCADDMULTI:
1488 case SIOCDELMULTI:
1489 error = (command == SIOCADDMULTI) ?
1490 ether_addmulti(ifr, &sc->sc_ethercom) :
1491 ether_delmulti(ifr, &sc->sc_ethercom);
1492 if (error == ENETRESET) {
1493 if (sc->sc_enabled != 0) {
1494 /*
1495 * Multicast list has changed. Set the
1496 * hardware filter accordingly.
1497 */
1498 wi_setmulti(sc);
1499 }
1500 error = 0;
1501 }
1502 break;
1503 case SIOCSIFMEDIA:
1504 case SIOCGIFMEDIA:
1505 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1506 break;
1507 case SIOCGWAVELAN:
1508 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1509 if (error)
1510 break;
1511 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1512 memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
1513 sizeof(sc->wi_stats));
1514 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1515 } else if (wreq.wi_type == WI_RID_READ_APS) {
1516 if (sc->wi_scanning) {
1517 error = EINPROGRESS;
1518 break;
1519 } else {
1520 len = sc->wi_naps * sizeof(struct wi_apinfo);
1521 len = len > WI_MAX_DATALEN ? WI_MAX_DATALEN : len;
1522 len = len / sizeof(struct wi_apinfo);
1523 memcpy((char *)&wreq.wi_val, (char *)&len, sizeof(len));
1524 memcpy((char *)&wreq.wi_val + sizeof(len),
1525 (char *)&sc->wi_aps,
1526 len * sizeof(struct wi_apinfo));
1527 }
1528 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
1529 /* For non-root user, return all-zeroes keys */
1530 if (suser(p->p_ucred, &p->p_acflag))
1531 memset((char *)&wreq, 0,
1532 sizeof(struct wi_ltv_keys));
1533 else
1534 memcpy((char *)&wreq, (char *)&sc->wi_keys,
1535 sizeof(struct wi_ltv_keys));
1536 } else {
1537 if (sc->sc_enabled == 0)
1538 error = wi_getdef(sc, &wreq);
1539 else if (wreq.wi_len > WI_MAX_DATALEN)
1540 error = EINVAL;
1541 else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
1542 error = EINVAL;
1543 }
1544 if (error == 0)
1545 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1546 break;
1547 case SIOCSWAVELAN:
1548 error = suser(p->p_ucred, &p->p_acflag);
1549 if (error)
1550 break;
1551 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1552 if (error)
1553 break;
1554 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1555 if (sc->sc_enabled)
1556 wi_inquire(sc);
1557 break;
1558 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1559 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1560 wreq.wi_len);
1561 } else if (wreq.wi_type == WI_RID_SCAN_APS) {
1562 if (wreq.wi_len != 4) {
1563 error = EINVAL;
1564 break;
1565 }
1566 if (!sc->wi_scanning) {
1567 if (sc->sc_firmware_type != WI_LUCENT) {
1568 wreq.wi_type = WI_RID_SCAN_REQ;
1569 error = wi_write_record(sc,
1570 (struct wi_ltv_gen *)&wreq);
1571 }
1572 if (!error) {
1573 sc->wi_scanning = 1;
1574 callout_reset(&sc->wi_scan_sh, hz * 1,
1575 wi_wait_scan, sc);
1576 }
1577 }
1578 } else {
1579 if (wreq.wi_len > WI_MAX_DATALEN)
1580 error = EINVAL;
1581 else if (sc->sc_enabled != 0)
1582 error = wi_write_record(sc,
1583 (struct wi_ltv_gen *)&wreq);
1584 if (error == 0)
1585 error = wi_setdef(sc, &wreq);
1586 if (error == 0 && sc->sc_enabled != 0)
1587 /* Reinitialize WaveLAN. */
1588 wi_init(ifp);
1589 }
1590 break;
1591 case SIOCG80211NWID:
1592 if (sc->sc_enabled == 0) {
1593 /* Return the desired ID */
1594 error = copyout(&sc->wi_netid, ifr->ifr_data,
1595 sizeof(sc->wi_netid));
1596 } else {
1597 wreq.wi_type = WI_RID_CURRENT_SSID;
1598 wreq.wi_len = WI_MAX_DATALEN;
1599 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
1600 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
1601 error = EINVAL;
1602 else {
1603 wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
1604 le16toh(wreq.wi_val[0]));
1605 error = copyout(&nwid, ifr->ifr_data,
1606 sizeof(nwid));
1607 }
1608 }
1609 break;
1610 case SIOCS80211NWID:
1611 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
1612 if (error != 0)
1613 break;
1614 if (nwid.i_len > IEEE80211_NWID_LEN) {
1615 error = EINVAL;
1616 break;
1617 }
1618 if (sc->wi_netid.i_len == nwid.i_len &&
1619 memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
1620 break;
1621 wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
1622 if (sc->sc_enabled != 0)
1623 /* Reinitialize WaveLAN. */
1624 wi_init(ifp);
1625 break;
1626 case SIOCS80211NWKEY:
1627 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1628 break;
1629 case SIOCG80211NWKEY:
1630 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1631 break;
1632 case SIOCS80211POWER:
1633 error = wi_set_pm(sc, (struct ieee80211_power *)data);
1634 break;
1635 case SIOCG80211POWER:
1636 error = wi_get_pm(sc, (struct ieee80211_power *)data);
1637 break;
1638
1639 default:
1640 error = EINVAL;
1641 break;
1642 }
1643
1644 splx(s);
1645 return (error);
1646 }
1647
1648 static int
1649 wi_init(ifp)
1650 struct ifnet *ifp;
1651 {
1652 struct wi_softc *sc = ifp->if_softc;
1653 struct wi_req wreq;
1654 struct wi_ltv_macaddr mac;
1655 int error, id = 0, wasenabled;
1656
1657 wasenabled = sc->sc_enabled;
1658 if (!sc->sc_enabled) {
1659 if ((error = (*sc->sc_enable)(sc)) != 0)
1660 goto out;
1661 sc->sc_enabled = 1;
1662 }
1663
1664 wi_stop(ifp, 0);
1665 /* Symbol firmware cannot be initialized more than once */
1666 if (!(sc->sc_firmware_type == WI_SYMBOL && wasenabled))
1667 wi_reset(sc);
1668
1669 /* Program max data length. */
1670 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1671
1672 /* Enable/disable IBSS creation. */
1673 if (sc->sc_firmware_type != WI_INTERSIL)
1674 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1675
1676 /* Set the port type. */
1677 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1678
1679 /* Program the RTS/CTS threshold. */
1680 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1681
1682 /* Program the TX rate */
1683 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1684
1685 /* Access point density */
1686 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1687
1688 /* Power Management Enabled */
1689 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1690
1691 /* Power Managment Max Sleep */
1692 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1693
1694 /* Roaming type */
1695 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
1696
1697 /* Specify the IBSS name */
1698 wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
1699
1700 /* Specify the network name */
1701 wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
1702
1703 /* Specify the frequency to use */
1704 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1705
1706 /* Program the nodename. */
1707 wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
1708
1709 /* Set our MAC address. */
1710 mac.wi_len = 4;
1711 mac.wi_type = WI_RID_MAC_NODE;
1712 memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
1713 wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1714
1715 /* Initialize promisc mode. */
1716 if (ifp->if_flags & IFF_PROMISC) {
1717 WI_SETVAL(WI_RID_PROMISC, 1);
1718 } else {
1719 WI_SETVAL(WI_RID_PROMISC, 0);
1720 }
1721
1722 /* Configure WEP. */
1723 if (sc->wi_has_wep) {
1724 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1725 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1726 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1727 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1728 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1729 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
1730 /*
1731 * ONLY HWB3163 EVAL-CARD Firmware version
1732 * less than 0.8 variant2
1733 *
1734 * If promiscuous mode disable, Prism2 chip
1735 * does not work with WEP .
1736 * It is under investigation for details.
1737 * (ichiro (at) netbsd.org)
1738 */
1739 if (sc->sc_firmware_type == WI_INTERSIL &&
1740 sc->sc_sta_firmware_ver < 802 ) {
1741 /* firm ver < 0.8 variant 2 */
1742 WI_SETVAL(WI_RID_PROMISC, 1);
1743 }
1744 WI_SETVAL(WI_RID_AUTH_CNTL, sc->wi_authtype);
1745 }
1746 }
1747
1748 /* Set multicast filter. */
1749 wi_setmulti(sc);
1750
1751 /* Enable desired port */
1752 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
1753
1754 /* scanning variable is modal, therefore reinit to OFF, in case it was on. */
1755 sc->wi_scanning=0;
1756 sc->wi_naps=0;
1757
1758 if ((error = wi_alloc_nicmem(sc,
1759 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
1760 printf("%s: tx buffer allocation failed\n",
1761 sc->sc_dev.dv_xname);
1762 goto out;
1763 }
1764 sc->wi_tx_data_id = id;
1765
1766 if ((error = wi_alloc_nicmem(sc,
1767 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
1768 printf("%s: mgmt. buffer allocation failed\n",
1769 sc->sc_dev.dv_xname);
1770 goto out;
1771 }
1772 sc->wi_tx_mgmt_id = id;
1773
1774 /* Enable interrupts */
1775 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1776
1777 ifp->if_flags |= IFF_RUNNING;
1778 ifp->if_flags &= ~IFF_OACTIVE;
1779
1780 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
1781
1782 out:
1783 if (error) {
1784 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1785 ifp->if_timer = 0;
1786 printf("%s: interface not running\n", sc->sc_dev.dv_xname);
1787 }
1788 return (error);
1789 }
1790
1791 static void
1792 wi_start(ifp)
1793 struct ifnet *ifp;
1794 {
1795 struct wi_softc *sc;
1796 struct mbuf *m0;
1797 struct wi_frame tx_frame;
1798 struct ether_header *eh;
1799 int id;
1800
1801 sc = ifp->if_softc;
1802
1803 if (ifp->if_flags & IFF_OACTIVE)
1804 return;
1805
1806 IFQ_DEQUEUE(&ifp->if_snd, m0);
1807 if (m0 == NULL)
1808 return;
1809
1810 memset((char *)&tx_frame, 0, sizeof(tx_frame));
1811 id = sc->wi_tx_data_id;
1812 eh = mtod(m0, struct ether_header *);
1813
1814 /*
1815 * Use RFC1042 encoding for IP and ARP datagrams,
1816 * 802.3 for anything else.
1817 */
1818 if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
1819 ntohs(eh->ether_type) == ETHERTYPE_ARP ||
1820 ntohs(eh->ether_type) == ETHERTYPE_REVARP ||
1821 ntohs(eh->ether_type) == ETHERTYPE_IPV6) {
1822 memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost,
1823 ETHER_ADDR_LEN);
1824 memcpy((char *)&tx_frame.wi_addr2, (char *)&eh->ether_shost,
1825 ETHER_ADDR_LEN);
1826 memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost,
1827 ETHER_ADDR_LEN);
1828 memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost,
1829 ETHER_ADDR_LEN);
1830
1831 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1832 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
1833 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
1834 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
1835 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1836 tx_frame.wi_type = eh->ether_type;
1837
1838 m_copydata(m0, sizeof(struct ether_header),
1839 m0->m_pkthdr.len - sizeof(struct ether_header),
1840 (caddr_t)&sc->wi_txbuf);
1841
1842 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1843 sizeof(struct wi_frame));
1844 wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
1845 (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
1846 } else {
1847 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
1848
1849 m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
1850
1851 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1852 sizeof(struct wi_frame));
1853 wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
1854 m0->m_pkthdr.len + 2);
1855 }
1856
1857 #if NBPFILTER > 0
1858 /*
1859 * If there's a BPF listener, bounce a copy of
1860 * this frame to him.
1861 */
1862 if (ifp->if_bpf)
1863 bpf_mtap(ifp->if_bpf, m0);
1864 #endif
1865
1866 m_freem(m0);
1867
1868 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1869 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
1870
1871 ifp->if_flags |= IFF_OACTIVE;
1872
1873 /*
1874 * Set a timeout in case the chip goes out to lunch.
1875 */
1876 ifp->if_timer = 5;
1877
1878 return;
1879 }
1880
1881 static int
1882 wi_mgmt_xmit(sc, data, len)
1883 struct wi_softc *sc;
1884 caddr_t data;
1885 int len;
1886 {
1887 struct wi_frame tx_frame;
1888 int id;
1889 struct wi_80211_hdr *hdr;
1890 caddr_t dptr;
1891
1892 hdr = (struct wi_80211_hdr *)data;
1893 dptr = data + sizeof(struct wi_80211_hdr);
1894
1895 memset((char *)&tx_frame, 0, sizeof(tx_frame));
1896 id = sc->wi_tx_mgmt_id;
1897
1898 memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr,
1899 sizeof(struct wi_80211_hdr));
1900
1901 tx_frame.wi_dat_len = htole16(len - WI_SNAPHDR_LEN);
1902 tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1903
1904 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1905 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1906 (len - sizeof(struct wi_80211_hdr)) + 2);
1907
1908 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1909 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
1910 return(EIO);
1911 }
1912
1913 return(0);
1914 }
1915
1916 static void
1917 wi_stop(ifp, disable)
1918 struct ifnet *ifp;
1919 {
1920 struct wi_softc *sc = ifp->if_softc;
1921
1922 CSR_WRITE_2(sc, WI_INT_EN, 0);
1923 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
1924
1925 callout_stop(&sc->wi_inquire_ch);
1926 callout_stop(&sc->wi_scan_sh);
1927
1928 if (disable) {
1929 if (sc->sc_enabled) {
1930 if (sc->sc_disable)
1931 (*sc->sc_disable)(sc);
1932 sc->sc_enabled = 0;
1933 }
1934 }
1935
1936 ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
1937 ifp->if_timer = 0;
1938 }
1939
1940 static void
1941 wi_watchdog(ifp)
1942 struct ifnet *ifp;
1943 {
1944 struct wi_softc *sc;
1945
1946 sc = ifp->if_softc;
1947
1948 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1949
1950 wi_init(ifp);
1951
1952 ifp->if_oerrors++;
1953
1954 return;
1955 }
1956
1957 void
1958 wi_shutdown(sc)
1959 struct wi_softc *sc;
1960 {
1961 int s;
1962
1963 s = splnet();
1964 if (sc->sc_enabled) {
1965 if (sc->sc_disable)
1966 (*sc->sc_disable)(sc);
1967 sc->sc_enabled = 0;
1968 }
1969 splx(s);
1970 }
1971
1972 int
1973 wi_activate(self, act)
1974 struct device *self;
1975 enum devact act;
1976 {
1977 struct wi_softc *sc = (struct wi_softc *)self;
1978 int rv = 0, s;
1979
1980 s = splnet();
1981 switch (act) {
1982 case DVACT_ACTIVATE:
1983 rv = EOPNOTSUPP;
1984 break;
1985
1986 case DVACT_DEACTIVATE:
1987 if_deactivate(&sc->sc_ethercom.ec_if);
1988 break;
1989 }
1990 splx(s);
1991 return (rv);
1992 }
1993
1994 static void
1995 wi_get_id(sc)
1996 struct wi_softc *sc;
1997 {
1998 struct wi_ltv_ver ver;
1999 struct wi_card_ident *id;
2000
2001 /* getting chip identity */
2002 memset(&ver, 0, sizeof(ver));
2003 ver.wi_type = WI_RID_CARD_ID;
2004 ver.wi_len = 5;
2005 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2006 printf("%s: using ", sc->sc_dev.dv_xname);
2007
2008 sc->sc_firmware_type = WI_NOTYPE;
2009 for (id = wi_card_ident; id->card_name != NULL; id++) {
2010 if (le16toh(ver.wi_ver[0]) == id->card_id) {
2011 printf("%s", id->card_name);
2012 sc->sc_firmware_type = id->firm_type;
2013 break;
2014 }
2015 }
2016 if (sc->sc_firmware_type == WI_NOTYPE) {
2017 if (le16toh(ver.wi_ver[0]) & 0x8000) {
2018 printf("Unknown PRISM2 chip");
2019 sc->sc_firmware_type = WI_INTERSIL;
2020 } else {
2021 printf("Unknown Lucent chip");
2022 sc->sc_firmware_type = WI_LUCENT;
2023 }
2024 }
2025
2026 /* get primary firmware version (Only Prism chips) */
2027 if (sc->sc_firmware_type != WI_LUCENT) {
2028 memset(&ver, 0, sizeof(ver));
2029 ver.wi_type = WI_RID_PRI_IDENTITY;
2030 ver.wi_len = 5;
2031 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2032 LE16TOH(ver.wi_ver[1]);
2033 LE16TOH(ver.wi_ver[2]);
2034 LE16TOH(ver.wi_ver[3]);
2035 sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
2036 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2037 }
2038
2039 /* get station firmware version */
2040 memset(&ver, 0, sizeof(ver));
2041 ver.wi_type = WI_RID_STA_IDENTITY;
2042 ver.wi_len = 5;
2043 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2044 LE16TOH(ver.wi_ver[1]);
2045 LE16TOH(ver.wi_ver[2]);
2046 LE16TOH(ver.wi_ver[3]);
2047 sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2048 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2049 if (sc->sc_firmware_type == WI_INTERSIL &&
2050 (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2051 struct wi_ltv_str sver;
2052 char *p;
2053
2054 memset(&sver, 0, sizeof(sver));
2055 sver.wi_type = WI_RID_SYMBOL_IDENTITY;
2056 sver.wi_len = 7;
2057 /* value should be the format like "V2.00-11" */
2058 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2059 *(p = (char *)sver.wi_str) >= 'A' &&
2060 p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2061 sc->sc_firmware_type = WI_SYMBOL;
2062 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2063 (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2064 (p[6] - '0') * 10 + (p[7] - '0');
2065 }
2066 }
2067
2068 printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
2069 sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
2070 (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
2071 if (sc->sc_firmware_type != WI_LUCENT) /* XXX */
2072 printf("Primary (%u.%u.%u), ", sc->sc_pri_firmware_ver / 10000,
2073 (sc->sc_pri_firmware_ver % 10000) / 100,
2074 sc->sc_pri_firmware_ver % 100);
2075 printf("Station (%u.%u.%u)\n",
2076 sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
2077 sc->sc_sta_firmware_ver % 100);
2078
2079 return;
2080 }
2081
2082 int
2083 wi_detach(sc)
2084 struct wi_softc *sc;
2085 {
2086 struct ifnet *ifp = sc->sc_ifp;
2087 int s;
2088
2089 if (!sc->sc_attached)
2090 return (0);
2091
2092 s = splnet();
2093 callout_stop(&sc->wi_inquire_ch);
2094
2095 /* Delete all remaining media. */
2096 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
2097
2098 ether_ifdetach(ifp);
2099 if_detach(ifp);
2100 if (sc->sc_enabled) {
2101 if (sc->sc_disable)
2102 (*sc->sc_disable)(sc);
2103 sc->sc_enabled = 0;
2104 }
2105 splx(s);
2106 return (0);
2107 }
2108
2109 void
2110 wi_power(sc, why)
2111 struct wi_softc *sc;
2112 int why;
2113 {
2114 int s;
2115
2116 if (!sc->sc_enabled)
2117 return;
2118
2119 s = splnet();
2120 switch (why) {
2121 case PWR_SUSPEND:
2122 case PWR_STANDBY:
2123 wi_stop(sc->sc_ifp, 0);
2124 if (sc->sc_enabled) {
2125 if (sc->sc_disable)
2126 (*sc->sc_disable)(sc);
2127 }
2128 break;
2129 case PWR_RESUME:
2130 sc->sc_enabled = 0;
2131 wi_init(sc->sc_ifp);
2132 (void)wi_intr(sc);
2133 break;
2134 case PWR_SOFTSUSPEND:
2135 case PWR_SOFTSTANDBY:
2136 case PWR_SOFTRESUME:
2137 break;
2138 }
2139 splx(s);
2140 }
2141
2142 static int
2143 wi_set_ssid(ws, id, len)
2144 struct ieee80211_nwid *ws;
2145 u_int8_t *id;
2146 int len;
2147 {
2148
2149 if (len > IEEE80211_NWID_LEN)
2150 return (EINVAL);
2151 ws->i_len = len;
2152 memcpy(ws->i_nwid, id, len);
2153 return (0);
2154 }
2155
2156 static void
2157 wi_request_fill_ssid(wreq, ws)
2158 struct wi_req *wreq;
2159 struct ieee80211_nwid *ws;
2160 {
2161 int len = ws->i_len;
2162
2163 memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
2164 wreq->wi_val[0] = htole16(len);
2165 wreq->wi_len = roundup(len, 2) / 2 + 2;
2166 memcpy(&wreq->wi_val[1], ws->i_nwid, len);
2167 }
2168
2169 static int
2170 wi_write_ssid(sc, type, wreq, ws)
2171 struct wi_softc *sc;
2172 int type;
2173 struct wi_req *wreq;
2174 struct ieee80211_nwid *ws;
2175 {
2176
2177 wreq->wi_type = type;
2178 wi_request_fill_ssid(wreq, ws);
2179 return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
2180 }
2181
2182 static int
2183 wi_sync_media(sc, ptype, txrate)
2184 struct wi_softc *sc;
2185 int ptype;
2186 int txrate;
2187 {
2188 int media = sc->sc_media.ifm_cur->ifm_media;
2189 int options = IFM_OPTIONS(media);
2190 int subtype;
2191
2192 switch (txrate) {
2193 case 1:
2194 subtype = IFM_IEEE80211_DS1;
2195 break;
2196 case 2:
2197 subtype = IFM_IEEE80211_DS2;
2198 break;
2199 case 3:
2200 subtype = IFM_AUTO;
2201 break;
2202 case 5:
2203 subtype = IFM_IEEE80211_DS5;
2204 break;
2205 case 11:
2206 subtype = IFM_IEEE80211_DS11;
2207 break;
2208 default:
2209 subtype = IFM_MANUAL; /* Unable to represent */
2210 break;
2211 }
2212 switch (ptype) {
2213 case WI_PORTTYPE_ADHOC:
2214 options |= IFM_IEEE80211_ADHOC;
2215 break;
2216 case WI_PORTTYPE_BSS:
2217 options &= ~IFM_IEEE80211_ADHOC;
2218 break;
2219 default:
2220 subtype = IFM_MANUAL; /* Unable to represent */
2221 break;
2222 }
2223 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
2224 IFM_INST(media));
2225 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
2226 return (EINVAL);
2227 ifmedia_set(&sc->sc_media, media);
2228 sc->wi_ptype = ptype;
2229 sc->wi_tx_rate = txrate;
2230 return (0);
2231 }
2232
2233 static int
2234 wi_media_change(ifp)
2235 struct ifnet *ifp;
2236 {
2237 struct wi_softc *sc = ifp->if_softc;
2238 int otype = sc->wi_ptype;
2239 int orate = sc->wi_tx_rate;
2240
2241 if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
2242 sc->wi_ptype = WI_PORTTYPE_ADHOC;
2243 else
2244 sc->wi_ptype = WI_PORTTYPE_BSS;
2245
2246 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
2247 case IFM_IEEE80211_DS1:
2248 sc->wi_tx_rate = 1;
2249 break;
2250 case IFM_IEEE80211_DS2:
2251 sc->wi_tx_rate = 2;
2252 break;
2253 case IFM_AUTO:
2254 sc->wi_tx_rate = 3;
2255 break;
2256 case IFM_IEEE80211_DS5:
2257 sc->wi_tx_rate = 5;
2258 break;
2259 case IFM_IEEE80211_DS11:
2260 sc->wi_tx_rate = 11;
2261 break;
2262 }
2263
2264 if (sc->sc_enabled != 0) {
2265 if (otype != sc->wi_ptype ||
2266 orate != sc->wi_tx_rate)
2267 wi_init(ifp);
2268 }
2269
2270 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2271
2272 return (0);
2273 }
2274
2275 static void
2276 wi_media_status(ifp, imr)
2277 struct ifnet *ifp;
2278 struct ifmediareq *imr;
2279 {
2280 struct wi_softc *sc = ifp->if_softc;
2281
2282 if (sc->sc_enabled == 0) {
2283 imr->ifm_active = IFM_IEEE80211|IFM_NONE;
2284 imr->ifm_status = 0;
2285 return;
2286 }
2287
2288 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2289 imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
2290 }
2291
2292 static int
2293 wi_set_nwkey(sc, nwkey)
2294 struct wi_softc *sc;
2295 struct ieee80211_nwkey *nwkey;
2296 {
2297 int i, error;
2298 size_t len;
2299 struct wi_req wreq;
2300 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
2301
2302 if (!sc->wi_has_wep)
2303 return ENODEV;
2304 if (nwkey->i_defkid <= 0 ||
2305 nwkey->i_defkid > IEEE80211_WEP_NKID)
2306 return EINVAL;
2307 memcpy(wk, &sc->wi_keys, sizeof(*wk));
2308 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2309 if (nwkey->i_key[i].i_keydat == NULL)
2310 continue;
2311 len = nwkey->i_key[i].i_keylen;
2312 if (len > sizeof(wk->wi_keys[i].wi_keydat))
2313 return EINVAL;
2314 error = copyin(nwkey->i_key[i].i_keydat,
2315 wk->wi_keys[i].wi_keydat, len);
2316 if (error)
2317 return error;
2318 wk->wi_keys[i].wi_keylen = htole16(len);
2319 }
2320
2321 wk->wi_len = (sizeof(*wk) / 2) + 1;
2322 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2323 if (sc->sc_enabled != 0) {
2324 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2325 if (error)
2326 return error;
2327 }
2328 error = wi_setdef(sc, &wreq);
2329 if (error)
2330 return error;
2331
2332 wreq.wi_len = 2;
2333 wreq.wi_type = WI_RID_TX_CRYPT_KEY;
2334 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
2335 if (sc->sc_enabled != 0) {
2336 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2337 if (error)
2338 return error;
2339 }
2340 error = wi_setdef(sc, &wreq);
2341 if (error)
2342 return error;
2343
2344 wreq.wi_type = WI_RID_ENCRYPTION;
2345 wreq.wi_val[0] = htole16(nwkey->i_wepon);
2346 if (sc->sc_enabled != 0) {
2347 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2348 if (error)
2349 return error;
2350 }
2351 error = wi_setdef(sc, &wreq);
2352 if (error)
2353 return error;
2354
2355 if (sc->sc_enabled != 0)
2356 wi_init(&sc->sc_ethercom.ec_if);
2357 return 0;
2358 }
2359
2360 static int
2361 wi_get_nwkey(sc, nwkey)
2362 struct wi_softc *sc;
2363 struct ieee80211_nwkey *nwkey;
2364 {
2365 int i, len, error;
2366 struct wi_ltv_keys *wk = &sc->wi_keys;
2367
2368 if (!sc->wi_has_wep)
2369 return ENODEV;
2370 nwkey->i_wepon = sc->wi_use_wep;
2371 nwkey->i_defkid = sc->wi_tx_key + 1;
2372
2373 /* do not show any keys to non-root user */
2374 error = suser(curproc->p_ucred, &curproc->p_acflag);
2375 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2376 if (nwkey->i_key[i].i_keydat == NULL)
2377 continue;
2378 /* error holds results of suser() for the first time */
2379 if (error)
2380 return error;
2381 len = le16toh(wk->wi_keys[i].wi_keylen);
2382 if (nwkey->i_key[i].i_keylen < len)
2383 return ENOSPC;
2384 nwkey->i_key[i].i_keylen = len;
2385 error = copyout(wk->wi_keys[i].wi_keydat,
2386 nwkey->i_key[i].i_keydat, len);
2387 if (error)
2388 return error;
2389 }
2390 return 0;
2391 }
2392
2393 static int
2394 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2395 {
2396
2397 sc->wi_pm_enabled = power->i_enabled;
2398 sc->wi_max_sleep = power->i_maxsleep;
2399
2400 if (sc->sc_enabled)
2401 return (wi_init(&sc->sc_ethercom.ec_if));
2402
2403 return (0);
2404 }
2405
2406 static int
2407 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2408 {
2409
2410 power->i_enabled = sc->wi_pm_enabled;
2411 power->i_maxsleep = sc->wi_max_sleep;
2412
2413 return (0);
2414 }
2415