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