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