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