wi.c revision 1.15 1 /* $NetBSD: wi.c,v 1.15 2001/06/02 15:49:16 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 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
651
652 if (sc->sc_prism2) {
653 int v;
654
655 switch (oltv->wi_type) {
656 case WI_RID_TX_RATE:
657 case WI_RID_CUR_TX_RATE:
658 switch (le16toh(ltv->wi_val)) {
659 case 1: v = 1; break;
660 case 2: v = 2; break;
661 case 3: v = 6; break;
662 case 4: v = 5; break;
663 case 7: v = 7; break;
664 case 8: v = 11; break;
665 case 15: v = 3; break;
666 default: v = 0x100 + le16toh(ltv->wi_val); break;
667 }
668 oltv->wi_val = htole16(v);
669 break;
670 case WI_RID_ENCRYPTION:
671 oltv->wi_len = 2;
672 if (le16toh(ltv->wi_val) & 0x01)
673 oltv->wi_val = htole16(1);
674 else
675 oltv->wi_val = htole16(0);
676 break;
677 case WI_RID_TX_CRYPT_KEY:
678 oltv->wi_len = 2;
679 oltv->wi_val = ltv->wi_val;
680 break;
681 case WI_RID_AUTH_CNTL:
682 oltv->wi_len = 2;
683 if (le16toh(ltv->wi_val) & 0x01)
684 oltv->wi_val = htole16(1);
685 else if (le16toh(ltv->wi_val) & 0x02)
686 oltv->wi_val = htole16(2);
687 break;
688 }
689 }
690
691 return(0);
692 }
693
694 /*
695 * Same as read, except we inject data instead of reading it.
696 */
697 static int wi_write_record(sc, ltv)
698 struct wi_softc *sc;
699 struct wi_ltv_gen *ltv;
700 {
701 u_int16_t *ptr;
702 int i;
703 struct wi_ltv_gen p2ltv;
704
705 if (sc->sc_prism2) {
706 int v;
707
708 switch (ltv->wi_type) {
709 case WI_RID_TX_RATE:
710 p2ltv.wi_type = WI_RID_TX_RATE;
711 p2ltv.wi_len = 2;
712 switch (le16toh(ltv->wi_val)) {
713 case 1: v = 1; break;
714 case 2: v = 2; break;
715 case 3: v = 15; break;
716 case 5: v = 4; break;
717 case 6: v = 3; break;
718 case 7: v = 7; break;
719 case 11: v = 8; break;
720 default: return EINVAL;
721 }
722 p2ltv.wi_val = htole16(v);
723 ltv = &p2ltv;
724 break;
725 case WI_RID_ENCRYPTION:
726 p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
727 p2ltv.wi_len = 2;
728 if (le16toh(ltv->wi_val))
729 p2ltv.wi_val = htole16(0x03);
730 else
731 p2ltv.wi_val = htole16(0x90);
732 ltv = &p2ltv;
733 break;
734 case WI_RID_TX_CRYPT_KEY:
735 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
736 p2ltv.wi_len = 2;
737 p2ltv.wi_val = ltv->wi_val;
738 ltv = &p2ltv;
739 break;
740 case WI_RID_DEFLT_CRYPT_KEYS:
741 {
742 int error;
743 struct wi_ltv_str ws;
744 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
745 for (i = 0; i < 4; i++) {
746 ws.wi_len = 4;
747 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
748 memcpy(ws.wi_str, &wk->wi_keys[i].wi_keydat, 5);
749 ws.wi_str[5] = '\0';
750 error = wi_write_record(sc,
751 (struct wi_ltv_gen *)&ws);
752 if (error)
753 return error;
754 }
755 return 0;
756 }
757 case WI_RID_AUTH_CNTL:
758 p2ltv.wi_type = WI_RID_AUTH_CNTL;
759 p2ltv.wi_len = 2;
760 if (le16toh(ltv->wi_val) == 1)
761 p2ltv.wi_val = htole16(0x01);
762 else if (le16toh(ltv->wi_val) == 2)
763 p2ltv.wi_val = htole16(0x02);
764 ltv = &p2ltv;
765 break;
766 }
767 }
768
769 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
770 return(EIO);
771
772 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
773 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
774
775 /* Write data */
776 ptr = <v->wi_val;
777 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
778
779 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
780 return(EIO);
781
782 return(0);
783 }
784
785 static int wi_seek(sc, id, off, chan)
786 struct wi_softc *sc;
787 int id, off, chan;
788 {
789 int i;
790 int selreg, offreg;
791 int status;
792
793 switch (chan) {
794 case WI_BAP0:
795 selreg = WI_SEL0;
796 offreg = WI_OFF0;
797 break;
798 case WI_BAP1:
799 selreg = WI_SEL1;
800 offreg = WI_OFF1;
801 break;
802 default:
803 printf("%s: invalid data path: %x\n",
804 sc->sc_dev.dv_xname, chan);
805 return(EIO);
806 }
807
808 CSR_WRITE_2(sc, selreg, id);
809 CSR_WRITE_2(sc, offreg, off);
810
811 for (i = 0; i < WI_TIMEOUT; i++) {
812 status = CSR_READ_2(sc, offreg);
813 if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
814 break;
815 }
816
817 if (i == WI_TIMEOUT) {
818 printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
819 sc->sc_dev.dv_xname, id, off, status);
820 return(ETIMEDOUT);
821 }
822 return(0);
823 }
824
825 static int wi_read_data(sc, id, off, buf, len)
826 struct wi_softc *sc;
827 int id, off;
828 caddr_t buf;
829 int len;
830 {
831 u_int16_t *ptr;
832
833 if (wi_seek(sc, id, off, WI_BAP1))
834 return(EIO);
835
836 ptr = (u_int16_t *)buf;
837 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
838
839 return(0);
840 }
841
842 /*
843 * According to the comments in the HCF Light code, there is a bug in
844 * the Hermes (or possibly in certain Hermes firmware revisions) where
845 * the chip's internal autoincrement counter gets thrown off during
846 * data writes: the autoincrement is missed, causing one data word to
847 * be overwritten and subsequent words to be written to the wrong memory
848 * locations. The end result is that we could end up transmitting bogus
849 * frames without realizing it. The workaround for this is to write a
850 * couple of extra guard words after the end of the transfer, then
851 * attempt to read then back. If we fail to locate the guard words where
852 * we expect them, we preform the transfer over again.
853 */
854 static int wi_write_data(sc, id, off, buf, len)
855 struct wi_softc *sc;
856 int id, off;
857 caddr_t buf;
858 int len;
859 {
860 u_int16_t *ptr;
861
862 #ifdef WI_HERMES_AUTOINC_WAR
863 again:
864 #endif
865
866 if (wi_seek(sc, id, off, WI_BAP0))
867 return(EIO);
868
869 ptr = (u_int16_t *)buf;
870 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
871
872 #ifdef WI_HERMES_AUTOINC_WAR
873 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
874 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
875
876 if (wi_seek(sc, id, off + len, WI_BAP0))
877 return(EIO);
878
879 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
880 CSR_READ_2(sc, WI_DATA0) != 0x5678)
881 goto again;
882 #endif
883
884 return(0);
885 }
886
887 /*
888 * Allocate a region of memory inside the NIC and zero
889 * it out.
890 */
891 static int wi_alloc_nicmem(sc, len, id)
892 struct wi_softc *sc;
893 int len;
894 int *id;
895 {
896 int i;
897
898 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
899 printf("%s: failed to allocate %d bytes on NIC\n",
900 sc->sc_dev.dv_xname, len);
901 return(ENOMEM);
902 }
903
904 for (i = 0; i < WI_TIMEOUT; i++) {
905 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
906 break;
907 }
908
909 if (i == WI_TIMEOUT) {
910 printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
911 return(ETIMEDOUT);
912 }
913
914 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
915 *id = CSR_READ_2(sc, WI_ALLOC_FID);
916
917 if (wi_seek(sc, *id, 0, WI_BAP0)) {
918 printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
919 return(EIO);
920 }
921
922 for (i = 0; i < len / 2; i++)
923 CSR_WRITE_2(sc, WI_DATA0, 0);
924
925 return(0);
926 }
927
928 static void wi_setmulti(sc)
929 struct wi_softc *sc;
930 {
931 struct ifnet *ifp;
932 int i = 0;
933 struct wi_ltv_mcast mcast;
934 struct ether_multi *enm;
935 struct ether_multistep estep;
936 struct ethercom *ec = &sc->sc_ethercom;
937
938 ifp = &sc->sc_ethercom.ec_if;
939
940 if ((ifp->if_flags & IFF_PROMISC) != 0) {
941 allmulti:
942 ifp->if_flags |= IFF_ALLMULTI;
943 bzero((char *)&mcast, sizeof(mcast));
944 mcast.wi_type = WI_RID_MCAST;
945 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
946
947 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
948 return;
949 }
950
951 i = 0;
952 ETHER_FIRST_MULTI(estep, ec, enm);
953 while (enm != NULL) {
954 /* Punt on ranges or too many multicast addresses. */
955 if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
956 ETHER_ADDR_LEN) != 0 ||
957 i >= 16)
958 goto allmulti;
959
960 bcopy(enm->enm_addrlo,
961 (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
962 i++;
963 ETHER_NEXT_MULTI(estep, enm);
964 }
965
966 ifp->if_flags &= ~IFF_ALLMULTI;
967 mcast.wi_type = WI_RID_MCAST;
968 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
969 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
970 }
971
972 static int
973 wi_setdef(sc, wreq)
974 struct wi_softc *sc;
975 struct wi_req *wreq;
976 {
977 struct sockaddr_dl *sdl;
978 struct ifnet *ifp;
979 int error = 0;
980
981 ifp = &sc->sc_ethercom.ec_if;
982
983 switch(wreq->wi_type) {
984 case WI_RID_MAC_NODE:
985 sdl = (struct sockaddr_dl *)ifp->if_sadl;
986 bcopy((char *)&wreq->wi_val, (char *)&sc->sc_macaddr,
987 ETHER_ADDR_LEN);
988 bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
989 break;
990 case WI_RID_PORTTYPE:
991 error = wi_sync_media(sc, le16toh(wreq->wi_val[0]), sc->wi_tx_rate);
992 break;
993 case WI_RID_TX_RATE:
994 error = wi_sync_media(sc, sc->wi_ptype, le16toh(wreq->wi_val[0]));
995 break;
996 case WI_RID_MAX_DATALEN:
997 sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
998 break;
999 case WI_RID_RTS_THRESH:
1000 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
1001 break;
1002 case WI_RID_SYSTEM_SCALE:
1003 sc->wi_ap_density = le16toh(wreq->wi_val[0]);
1004 break;
1005 case WI_RID_CREATE_IBSS:
1006 sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
1007 break;
1008 case WI_RID_OWN_CHNL:
1009 sc->wi_channel = le16toh(wreq->wi_val[0]);
1010 break;
1011 case WI_RID_NODENAME:
1012 error = wi_set_ssid(&sc->wi_nodeid,
1013 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1014 break;
1015 case WI_RID_DESIRED_SSID:
1016 error = wi_set_ssid(&sc->wi_netid,
1017 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1018 break;
1019 case WI_RID_OWN_SSID:
1020 error = wi_set_ssid(&sc->wi_ibssid,
1021 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1022 break;
1023 case WI_RID_PM_ENABLED:
1024 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
1025 break;
1026 case WI_RID_MICROWAVE_OVEN:
1027 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
1028 break;
1029 case WI_RID_MAX_SLEEP:
1030 sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
1031 break;
1032 case WI_RID_AUTH_CNTL:
1033 sc->wi_authtype = le16toh(wreq->wi_val[0]);
1034 break;
1035 case WI_RID_ROAMING_MODE:
1036 sc->wi_roaming = le16toh(wreq->wi_val[0]);
1037 break;
1038 case WI_RID_ENCRYPTION:
1039 sc->wi_use_wep = le16toh(wreq->wi_val[0]);
1040 break;
1041 case WI_RID_TX_CRYPT_KEY:
1042 sc->wi_tx_key = le16toh(wreq->wi_val[0]);
1043 break;
1044 case WI_RID_DEFLT_CRYPT_KEYS:
1045 bcopy((char *)wreq, (char *)&sc->wi_keys,
1046 sizeof(struct wi_ltv_keys));
1047 break;
1048 default:
1049 error = EINVAL;
1050 break;
1051 }
1052
1053 return (error);
1054 }
1055
1056 static int
1057 wi_getdef(sc, wreq)
1058 struct wi_softc *sc;
1059 struct wi_req *wreq;
1060 {
1061 struct sockaddr_dl *sdl;
1062 struct ifnet *ifp;
1063 int error = 0;
1064
1065 ifp = &sc->sc_ethercom.ec_if;
1066
1067 wreq->wi_len = 2; /* XXX */
1068 switch (wreq->wi_type) {
1069 case WI_RID_MAC_NODE:
1070 wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
1071 sdl = (struct sockaddr_dl *)ifp->if_sadl;
1072 bcopy(&sc->sc_macaddr, &wreq->wi_val, ETHER_ADDR_LEN);
1073 bcopy(LLADDR(sdl), &wreq->wi_val, ETHER_ADDR_LEN);
1074 break;
1075 case WI_RID_PORTTYPE:
1076 wreq->wi_val[0] = htole16(sc->wi_ptype);
1077 break;
1078 case WI_RID_TX_RATE:
1079 wreq->wi_val[0] = htole16(sc->wi_tx_rate);
1080 break;
1081 case WI_RID_MAX_DATALEN:
1082 wreq->wi_val[0] = htole16(sc->wi_max_data_len);
1083 break;
1084 case WI_RID_RTS_THRESH:
1085 wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
1086 break;
1087 case WI_RID_SYSTEM_SCALE:
1088 wreq->wi_val[0] = htole16(sc->wi_ap_density);
1089 break;
1090 case WI_RID_CREATE_IBSS:
1091 wreq->wi_val[0] = htole16(sc->wi_create_ibss);
1092 break;
1093 case WI_RID_OWN_CHNL:
1094 wreq->wi_val[0] = htole16(sc->wi_channel);
1095 break;
1096 case WI_RID_NODENAME:
1097 wi_request_fill_ssid(wreq, &sc->wi_nodeid);
1098 break;
1099 case WI_RID_DESIRED_SSID:
1100 wi_request_fill_ssid(wreq, &sc->wi_netid);
1101 break;
1102 case WI_RID_OWN_SSID:
1103 wi_request_fill_ssid(wreq, &sc->wi_ibssid);
1104 break;
1105 case WI_RID_PM_ENABLED:
1106 wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
1107 break;
1108 case WI_RID_MICROWAVE_OVEN:
1109 wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
1110 break;
1111 case WI_RID_MAX_SLEEP:
1112 wreq->wi_val[0] = htole16(sc->wi_max_sleep);
1113 break;
1114 case WI_RID_AUTH_CNTL:
1115 wreq->wi_val[0] = htole16(sc->wi_authtype);
1116 break;
1117 case WI_RID_ROAMING_MODE:
1118 wreq->wi_val[0] = htole16(sc->wi_roaming);
1119 break;
1120 case WI_RID_WEP_AVAIL:
1121 wreq->wi_val[0] = htole16(sc->wi_has_wep);
1122 break;
1123 case WI_RID_ENCRYPTION:
1124 wreq->wi_val[0] = htole16(sc->wi_use_wep);
1125 break;
1126 case WI_RID_TX_CRYPT_KEY:
1127 wreq->wi_val[0] = htole16(sc->wi_tx_key);
1128 break;
1129 case WI_RID_DEFLT_CRYPT_KEYS:
1130 wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
1131 bcopy(&sc->wi_keys, wreq, sizeof(struct wi_ltv_keys));
1132 break;
1133 default:
1134 #if 0
1135 error = EIO;
1136 #else
1137 #ifdef WI_DEBUG
1138 printf("%s: wi_getdef: unknown request %d\n",
1139 sc->sc_dev.dv_xname, wreq->wi_type);
1140 #endif
1141 #endif
1142 break;
1143 }
1144
1145 return (error);
1146 }
1147
1148 static int
1149 wi_ioctl(ifp, command, data)
1150 struct ifnet *ifp;
1151 u_long command;
1152 caddr_t data;
1153 {
1154 int s, error = 0;
1155 struct wi_softc *sc = ifp->if_softc;
1156 struct wi_req wreq;
1157 struct ifreq *ifr;
1158 struct proc *p = curproc;
1159 struct ieee80211_nwid nwid;
1160
1161 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
1162 return (ENXIO);
1163
1164 s = splnet();
1165
1166 ifr = (struct ifreq *)data;
1167 switch (command) {
1168 case SIOCSIFADDR:
1169 case SIOCGIFADDR:
1170 case SIOCSIFMTU:
1171 error = ether_ioctl(ifp, command, data);
1172 break;
1173 case SIOCSIFFLAGS:
1174 if (ifp->if_flags & IFF_UP) {
1175 if (ifp->if_flags & IFF_RUNNING &&
1176 ifp->if_flags & IFF_PROMISC &&
1177 !(sc->wi_if_flags & IFF_PROMISC)) {
1178 WI_SETVAL(WI_RID_PROMISC, 1);
1179 } else if (ifp->if_flags & IFF_RUNNING &&
1180 !(ifp->if_flags & IFF_PROMISC) &&
1181 sc->wi_if_flags & IFF_PROMISC) {
1182 WI_SETVAL(WI_RID_PROMISC, 0);
1183 }
1184 wi_init(ifp);
1185 } else {
1186 if (ifp->if_flags & IFF_RUNNING) {
1187 wi_stop(ifp, 0);
1188 }
1189 }
1190 sc->wi_if_flags = ifp->if_flags;
1191
1192 if (!(ifp->if_flags & IFF_UP)) {
1193 if (sc->sc_enabled) {
1194 if (sc->sc_disable)
1195 (*sc->sc_disable)(sc);
1196 sc->sc_enabled = 0;
1197 ifp->if_flags &= ~IFF_RUNNING;
1198 }
1199 }
1200 error = 0;
1201 break;
1202 case SIOCADDMULTI:
1203 case SIOCDELMULTI:
1204 error = (command == SIOCADDMULTI) ?
1205 ether_addmulti(ifr, &sc->sc_ethercom) :
1206 ether_delmulti(ifr, &sc->sc_ethercom);
1207 if (error == ENETRESET) {
1208 if (sc->sc_enabled != 0) {
1209 /*
1210 * Multicast list has changed. Set the
1211 * hardware filter accordingly.
1212 */
1213 wi_setmulti(sc);
1214 }
1215 error = 0;
1216 }
1217 break;
1218 case SIOCSIFMEDIA:
1219 case SIOCGIFMEDIA:
1220 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1221 break;
1222 case SIOCGWAVELAN:
1223 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1224 if (error)
1225 break;
1226 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1227 /* XXX native byte order */
1228 bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1229 sizeof(sc->wi_stats));
1230 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1231 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
1232 /* For non-root user, return all-zeroes keys */
1233 if (suser(p->p_ucred, &p->p_acflag))
1234 bzero((char *)&wreq,
1235 sizeof(struct wi_ltv_keys));
1236 else
1237 bcopy((char *)&sc->wi_keys, (char *)&wreq,
1238 sizeof(struct wi_ltv_keys));
1239 } else {
1240 if (sc->sc_enabled == 0)
1241 error = wi_getdef(sc, &wreq);
1242 else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
1243 error = EINVAL;
1244 }
1245 if (error == 0)
1246 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1247 break;
1248 case SIOCSWAVELAN:
1249 error = suser(p->p_ucred, &p->p_acflag);
1250 if (error)
1251 break;
1252 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1253 if (error)
1254 break;
1255 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1256 error = EINVAL;
1257 break;
1258 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1259 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1260 wreq.wi_len);
1261 } else {
1262 if (sc->sc_enabled != 0)
1263 error = wi_write_record(sc,
1264 (struct wi_ltv_gen *)&wreq);
1265 if (error == 0)
1266 error = wi_setdef(sc, &wreq);
1267 if (error == 0 && sc->sc_enabled != 0)
1268 /* Reinitialize WaveLAN. */
1269 wi_init(ifp);
1270 }
1271 break;
1272 case SIOCG80211NWID:
1273 if (sc->sc_enabled == 0) {
1274 /* Return the desired ID */
1275 error = copyout(&sc->wi_netid, ifr->ifr_data,
1276 sizeof(sc->wi_netid));
1277 } else {
1278 wreq.wi_type = WI_RID_CURRENT_SSID;
1279 wreq.wi_len = WI_MAX_DATALEN;
1280 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
1281 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
1282 error = EINVAL;
1283 else {
1284 wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
1285 le16toh(wreq.wi_val[0]));
1286 error = copyout(&nwid, ifr->ifr_data,
1287 sizeof(nwid));
1288 }
1289 }
1290 break;
1291 case SIOCS80211NWID:
1292 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
1293 if (error != 0)
1294 break;
1295 if (nwid.i_len > IEEE80211_NWID_LEN) {
1296 error = EINVAL;
1297 break;
1298 }
1299 if (sc->wi_netid.i_len == nwid.i_len &&
1300 memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
1301 break;
1302 wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
1303 if (sc->sc_enabled != 0)
1304 /* Reinitialize WaveLAN. */
1305 wi_init(ifp);
1306 break;
1307 case SIOCS80211NWKEY:
1308 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1309 break;
1310 case SIOCG80211NWKEY:
1311 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1312 break;
1313 case SIOCS80211POWER:
1314 error = wi_set_pm(sc, (struct ieee80211_power *)data);
1315 break;
1316 case SIOCG80211POWER:
1317 error = wi_get_pm(sc, (struct ieee80211_power *)data);
1318 break;
1319
1320 default:
1321 error = EINVAL;
1322 break;
1323 }
1324
1325 splx(s);
1326 return (error);
1327 }
1328
1329 static int
1330 wi_init(ifp)
1331 struct ifnet *ifp;
1332 {
1333 struct wi_softc *sc = ifp->if_softc;
1334 struct wi_req wreq;
1335 struct wi_ltv_macaddr mac;
1336 int error, id = 0;
1337
1338 if (!sc->sc_enabled) {
1339 if ((error = (*sc->sc_enable)(sc)) != 0)
1340 goto out;
1341 sc->sc_enabled = 1;
1342 }
1343
1344 wi_stop(ifp, 0);
1345 wi_reset(sc);
1346
1347 /* Program max data length. */
1348 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1349
1350 /* Enable/disable IBSS creation. */
1351 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1352
1353 /* Set the port type. */
1354 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1355
1356 /* Program the RTS/CTS threshold. */
1357 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1358
1359 /* Program the TX rate */
1360 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1361
1362 /* Access point density */
1363 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1364
1365 /* Power Management Enabled */
1366 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1367
1368 /* Power Managment Max Sleep */
1369 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1370
1371 /* Roaming type */
1372 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
1373
1374 /* Specify the IBSS name */
1375 wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
1376
1377 /* Specify the network name */
1378 wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
1379
1380 /* Specify the frequency to use */
1381 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1382
1383 /* Program the nodename. */
1384 wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
1385
1386 /* Set our MAC address. */
1387 mac.wi_len = 4;
1388 mac.wi_type = WI_RID_MAC_NODE;
1389 memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
1390 wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1391
1392 /* Initialize promisc mode. */
1393 if (ifp->if_flags & IFF_PROMISC) {
1394 WI_SETVAL(WI_RID_PROMISC, 1);
1395 } else {
1396 WI_SETVAL(WI_RID_PROMISC, 0);
1397 }
1398
1399 /* Configure WEP. */
1400 if (sc->wi_has_wep) {
1401 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1402 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1403 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1404 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1405 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1406 if (sc->sc_prism2 && sc->wi_use_wep) {
1407 /*
1408 * ONLY HWB3163 EVAL-CARD Firmware version
1409 * less than 0.8 variant3
1410 *
1411 * If promiscuous mode disable, Prism2 chip
1412 * does not work with WEP .
1413 * It is under investigation for details.
1414 * (ichiro (at) netbsd.org)
1415 */
1416 if (sc->sc_prism2_ver < 83 ) {
1417 /* firm ver < 0.8 variant 3 */
1418 WI_SETVAL(WI_RID_PROMISC, 1);
1419 }
1420 WI_SETVAL(WI_RID_AUTH_CNTL, sc->wi_authtype);
1421 }
1422 }
1423
1424 /* Set multicast filter. */
1425 wi_setmulti(sc);
1426
1427 /* Enable desired port */
1428 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
1429
1430 if ((error = wi_alloc_nicmem(sc,
1431 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
1432 printf("%s: tx buffer allocation failed\n",
1433 sc->sc_dev.dv_xname);
1434 goto out;
1435 }
1436 sc->wi_tx_data_id = id;
1437
1438 if ((error = wi_alloc_nicmem(sc,
1439 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
1440 printf("%s: mgmt. buffer allocation failed\n",
1441 sc->sc_dev.dv_xname);
1442 goto out;
1443 }
1444 sc->wi_tx_mgmt_id = id;
1445
1446 /* Enable interrupts */
1447 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1448
1449 ifp->if_flags |= IFF_RUNNING;
1450 ifp->if_flags &= ~IFF_OACTIVE;
1451
1452 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
1453
1454 out:
1455 if (error) {
1456 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1457 ifp->if_timer = 0;
1458 printf("%s: interface not running\n", sc->sc_dev.dv_xname);
1459 }
1460 return (error);
1461 }
1462
1463 static void
1464 wi_start(ifp)
1465 struct ifnet *ifp;
1466 {
1467 struct wi_softc *sc;
1468 struct mbuf *m0;
1469 struct wi_frame tx_frame;
1470 struct ether_header *eh;
1471 int id;
1472
1473 sc = ifp->if_softc;
1474
1475 if (ifp->if_flags & IFF_OACTIVE)
1476 return;
1477
1478 IFQ_DEQUEUE(&ifp->if_snd, m0);
1479 if (m0 == NULL)
1480 return;
1481
1482 bzero((char *)&tx_frame, sizeof(tx_frame));
1483 id = sc->wi_tx_data_id;
1484 eh = mtod(m0, struct ether_header *);
1485
1486 /*
1487 * Use RFC1042 encoding for IP and ARP datagrams,
1488 * 802.3 for anything else.
1489 */
1490 if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
1491 ntohs(eh->ether_type) == ETHERTYPE_ARP ||
1492 ntohs(eh->ether_type) == ETHERTYPE_REVARP ||
1493 ntohs(eh->ether_type) == ETHERTYPE_IPV6) {
1494 bcopy((char *)&eh->ether_dhost,
1495 (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
1496 bcopy((char *)&eh->ether_shost,
1497 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
1498 bcopy((char *)&eh->ether_dhost,
1499 (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
1500 bcopy((char *)&eh->ether_shost,
1501 (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
1502
1503 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1504 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
1505 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
1506 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
1507 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1508 tx_frame.wi_type = eh->ether_type;
1509
1510 m_copydata(m0, sizeof(struct ether_header),
1511 m0->m_pkthdr.len - sizeof(struct ether_header),
1512 (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_11_OFFSET, (caddr_t)&sc->wi_txbuf,
1517 (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
1518 } else {
1519 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
1520
1521 m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
1522
1523 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1524 sizeof(struct wi_frame));
1525 wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
1526 m0->m_pkthdr.len + 2);
1527 }
1528
1529 #if NBPFILTER > 0
1530 /*
1531 * If there's a BPF listener, bounce a copy of
1532 * this frame to him.
1533 */
1534 if (ifp->if_bpf)
1535 bpf_mtap(ifp->if_bpf, m0);
1536 #endif
1537
1538 m_freem(m0);
1539
1540 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1541 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
1542
1543 ifp->if_flags |= IFF_OACTIVE;
1544
1545 /*
1546 * Set a timeout in case the chip goes out to lunch.
1547 */
1548 ifp->if_timer = 5;
1549
1550 return;
1551 }
1552
1553 static int
1554 wi_mgmt_xmit(sc, data, len)
1555 struct wi_softc *sc;
1556 caddr_t data;
1557 int len;
1558 {
1559 struct wi_frame tx_frame;
1560 int id;
1561 struct wi_80211_hdr *hdr;
1562 caddr_t dptr;
1563
1564 hdr = (struct wi_80211_hdr *)data;
1565 dptr = data + sizeof(struct wi_80211_hdr);
1566
1567 bzero((char *)&tx_frame, sizeof(tx_frame));
1568 id = sc->wi_tx_mgmt_id;
1569
1570 bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
1571 sizeof(struct wi_80211_hdr));
1572
1573 tx_frame.wi_dat_len = htole16(len - WI_SNAPHDR_LEN);
1574 tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1575
1576 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1577 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1578 (len - sizeof(struct wi_80211_hdr)) + 2);
1579
1580 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1581 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
1582 return(EIO);
1583 }
1584
1585 return(0);
1586 }
1587
1588 static void
1589 wi_stop(ifp, disable)
1590 struct ifnet *ifp;
1591 {
1592 struct wi_softc *sc = ifp->if_softc;
1593
1594 CSR_WRITE_2(sc, WI_INT_EN, 0);
1595 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
1596
1597 callout_stop(&sc->wi_inquire_ch);
1598
1599 if (disable) {
1600 if (sc->sc_enabled) {
1601 if (sc->sc_disable)
1602 (*sc->sc_disable)(sc);
1603 sc->sc_enabled = 0;
1604 }
1605 }
1606
1607 ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
1608 ifp->if_timer = 0;
1609 }
1610
1611 static void
1612 wi_watchdog(ifp)
1613 struct ifnet *ifp;
1614 {
1615 struct wi_softc *sc;
1616
1617 sc = ifp->if_softc;
1618
1619 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1620
1621 wi_init(ifp);
1622
1623 ifp->if_oerrors++;
1624
1625 return;
1626 }
1627
1628 void
1629 wi_shutdown(sc)
1630 struct wi_softc *sc;
1631 {
1632 int s;
1633
1634 s = splnet();
1635 if (sc->sc_enabled) {
1636 if (sc->sc_disable)
1637 (*sc->sc_disable)(sc);
1638 sc->sc_enabled = 0;
1639 }
1640 splx(s);
1641 }
1642
1643 int
1644 wi_activate(self, act)
1645 struct device *self;
1646 enum devact act;
1647 {
1648 struct wi_softc *sc = (struct wi_softc *)self;
1649 int rv = 0, s;
1650
1651 s = splnet();
1652 switch (act) {
1653 case DVACT_ACTIVATE:
1654 rv = EOPNOTSUPP;
1655 break;
1656
1657 case DVACT_DEACTIVATE:
1658 if_deactivate(&sc->sc_ethercom.ec_if);
1659 break;
1660 }
1661 splx(s);
1662 return (rv);
1663 }
1664
1665 static void
1666 wi_get_id(sc)
1667 struct wi_softc *sc;
1668 {
1669 struct wi_ltv_ver ver;
1670
1671 /* getting chip identity */
1672 memset(&ver, 0, sizeof(ver));
1673 ver.wi_type = WI_RID_CARDID;
1674 ver.wi_len = 5;
1675 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
1676 printf("%s: using ", sc->sc_dev.dv_xname);
1677 switch (le16toh(ver.wi_ver[0])) {
1678 case WI_NIC_EVB2:
1679 printf("RF:PRISM2 MAC:HFA3841");
1680 sc->sc_prism2 = 1;
1681 break;
1682 case WI_NIC_HWB3763:
1683 printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3763 rev.B");
1684 sc->sc_prism2 = 1;
1685 break;
1686 case WI_NIC_HWB3163:
1687 printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.A");
1688 sc->sc_prism2 = 1;
1689 break;
1690 case WI_NIC_HWB3163B:
1691 printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.B");
1692 sc->sc_prism2 = 1;
1693 break;
1694 case WI_NIC_EVB3:
1695 printf("RF:PRISM2 MAC:HFA3842");
1696 sc->sc_prism2 = 1;
1697 break;
1698 case WI_NIC_HWB1153:
1699 printf("RF:PRISM1 MAC:HFA3841 CARD:HWB1153");
1700 sc->sc_prism2 = 1;
1701 break;
1702 case WI_NIC_P2_SST:
1703 printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163-SST-flash");
1704 sc->sc_prism2 = 1;
1705 break;
1706 case WI_NIC_PRISM2_5:
1707 printf("RF:PRISM2.5 MAC:ISL3873");
1708 sc->sc_prism2 = 1;
1709 break;
1710 default:
1711 printf("Lucent chip or unknown chip\n");
1712 sc->sc_prism2 = 0;
1713 break;
1714 }
1715
1716 if (sc->sc_prism2) {
1717 /* try to get prism2 firm version */
1718 memset(&ver, 0, sizeof(ver));
1719 ver.wi_type = WI_RID_IDENT;
1720 ver.wi_len = 5;
1721 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
1722 LE16TOH(ver.wi_ver[1]);
1723 LE16TOH(ver.wi_ver[2]);
1724 LE16TOH(ver.wi_ver[3]);
1725 printf(" ,Firmware: %i.%i variant %i\n", ver.wi_ver[2],
1726 ver.wi_ver[3], ver.wi_ver[1]);
1727 sc->sc_prism2_ver = ver.wi_ver[2] * 100 +
1728 ver.wi_ver[3] * 10 + ver.wi_ver[1];
1729 }
1730
1731 return;
1732 }
1733
1734 int
1735 wi_detach(sc)
1736 struct wi_softc *sc;
1737 {
1738 struct ifnet *ifp = sc->sc_ifp;
1739 int s;
1740
1741 if (!sc->sc_attached)
1742 return (0);
1743
1744 s = splnet();
1745 callout_stop(&sc->wi_inquire_ch);
1746
1747 /* Delete all remaining media. */
1748 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
1749
1750 ether_ifdetach(ifp);
1751 if_detach(ifp);
1752 if (sc->sc_enabled) {
1753 if (sc->sc_disable)
1754 (*sc->sc_disable)(sc);
1755 sc->sc_enabled = 0;
1756 }
1757 splx(s);
1758 return (0);
1759 }
1760
1761 void
1762 wi_power(sc, why)
1763 struct wi_softc *sc;
1764 int why;
1765 {
1766 int s;
1767
1768 if (!sc->sc_enabled)
1769 return;
1770
1771 s = splnet();
1772 switch (why) {
1773 case PWR_SUSPEND:
1774 case PWR_STANDBY:
1775 wi_stop(sc->sc_ifp, 0);
1776 if (sc->sc_enabled) {
1777 if (sc->sc_disable)
1778 (*sc->sc_disable)(sc);
1779 }
1780 break;
1781 case PWR_RESUME:
1782 sc->sc_enabled = 0;
1783 wi_init(sc->sc_ifp);
1784 (void)wi_intr(sc);
1785 break;
1786 case PWR_SOFTSUSPEND:
1787 case PWR_SOFTSTANDBY:
1788 case PWR_SOFTRESUME:
1789 break;
1790 }
1791 splx(s);
1792 }
1793
1794 static int
1795 wi_set_ssid(ws, id, len)
1796 struct ieee80211_nwid *ws;
1797 u_int8_t *id;
1798 int len;
1799 {
1800
1801 if (len > IEEE80211_NWID_LEN)
1802 return (EINVAL);
1803 ws->i_len = len;
1804 memcpy(ws->i_nwid, id, len);
1805 return (0);
1806 }
1807
1808 static void
1809 wi_request_fill_ssid(wreq, ws)
1810 struct wi_req *wreq;
1811 struct ieee80211_nwid *ws;
1812 {
1813 int len = ws->i_len;
1814
1815 memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
1816 wreq->wi_val[0] = htole16(len);
1817 wreq->wi_len = roundup(len, 2) / 2 + 2;
1818 memcpy(&wreq->wi_val[1], ws->i_nwid, len);
1819 }
1820
1821 static int
1822 wi_write_ssid(sc, type, wreq, ws)
1823 struct wi_softc *sc;
1824 int type;
1825 struct wi_req *wreq;
1826 struct ieee80211_nwid *ws;
1827 {
1828
1829 wreq->wi_type = type;
1830 wi_request_fill_ssid(wreq, ws);
1831 return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
1832 }
1833
1834 static int
1835 wi_sync_media(sc, ptype, txrate)
1836 struct wi_softc *sc;
1837 int ptype;
1838 int txrate;
1839 {
1840 int media = sc->sc_media.ifm_cur->ifm_media;
1841 int options = IFM_OPTIONS(media);
1842 int subtype;
1843
1844 switch (txrate) {
1845 case 1:
1846 subtype = IFM_IEEE80211_DS1;
1847 break;
1848 case 2:
1849 subtype = IFM_IEEE80211_DS2;
1850 break;
1851 case 3:
1852 subtype = IFM_AUTO;
1853 break;
1854 case 11:
1855 subtype = IFM_IEEE80211_DS11;
1856 break;
1857 default:
1858 subtype = IFM_MANUAL; /* Unable to represent */
1859 break;
1860 }
1861 switch (ptype) {
1862 case WI_PORTTYPE_ADHOC:
1863 options |= IFM_IEEE80211_ADHOC;
1864 break;
1865 case WI_PORTTYPE_BSS:
1866 options &= ~IFM_IEEE80211_ADHOC;
1867 break;
1868 default:
1869 subtype = IFM_MANUAL; /* Unable to represent */
1870 break;
1871 }
1872 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
1873 IFM_INST(media));
1874 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
1875 return (EINVAL);
1876 ifmedia_set(&sc->sc_media, media);
1877 sc->wi_ptype = ptype;
1878 sc->wi_tx_rate = txrate;
1879 return (0);
1880 }
1881
1882 static int
1883 wi_media_change(ifp)
1884 struct ifnet *ifp;
1885 {
1886 struct wi_softc *sc = ifp->if_softc;
1887 int otype = sc->wi_ptype;
1888 int orate = sc->wi_tx_rate;
1889
1890 if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
1891 sc->wi_ptype = WI_PORTTYPE_ADHOC;
1892 else
1893 sc->wi_ptype = WI_PORTTYPE_BSS;
1894
1895 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
1896 case IFM_IEEE80211_DS1:
1897 sc->wi_tx_rate = 1;
1898 break;
1899 case IFM_IEEE80211_DS2:
1900 sc->wi_tx_rate = 2;
1901 break;
1902 case IFM_AUTO:
1903 sc->wi_tx_rate = 3;
1904 break;
1905 case IFM_IEEE80211_DS11:
1906 sc->wi_tx_rate = 11;
1907 break;
1908 }
1909
1910 if (sc->sc_enabled != 0) {
1911 if (otype != sc->wi_ptype ||
1912 orate != sc->wi_tx_rate)
1913 wi_init(ifp);
1914 }
1915
1916 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
1917
1918 return (0);
1919 }
1920
1921 static void
1922 wi_media_status(ifp, imr)
1923 struct ifnet *ifp;
1924 struct ifmediareq *imr;
1925 {
1926 struct wi_softc *sc = ifp->if_softc;
1927
1928 if (sc->sc_enabled == 0) {
1929 imr->ifm_active = IFM_IEEE80211|IFM_NONE;
1930 imr->ifm_status = 0;
1931 return;
1932 }
1933
1934 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
1935 imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
1936 }
1937
1938 static int
1939 wi_set_nwkey(sc, nwkey)
1940 struct wi_softc *sc;
1941 struct ieee80211_nwkey *nwkey;
1942 {
1943 int i, len, error;
1944 struct wi_req wreq;
1945 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
1946
1947 if (!sc->wi_has_wep)
1948 return ENODEV;
1949 if (nwkey->i_defkid <= 0 ||
1950 nwkey->i_defkid > IEEE80211_WEP_NKID)
1951 return EINVAL;
1952 memcpy(wk, &sc->wi_keys, sizeof(*wk));
1953 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1954 if (nwkey->i_key[i].i_keydat == NULL)
1955 continue;
1956 len = nwkey->i_key[i].i_keylen;
1957 if (len > sizeof(wk->wi_keys[i].wi_keydat))
1958 return EINVAL;
1959 error = copyin(nwkey->i_key[i].i_keydat,
1960 wk->wi_keys[i].wi_keydat, len);
1961 if (error)
1962 return error;
1963 wk->wi_keys[i].wi_keylen = htole16(len);
1964 }
1965
1966 wk->wi_len = (sizeof(*wk) / 2) + 1;
1967 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1968 if (sc->sc_enabled != 0) {
1969 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1970 if (error)
1971 return error;
1972 }
1973 error = wi_setdef(sc, &wreq);
1974 if (error)
1975 return error;
1976
1977 wreq.wi_len = 2;
1978 wreq.wi_type = WI_RID_TX_CRYPT_KEY;
1979 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
1980 if (sc->sc_enabled != 0) {
1981 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1982 if (error)
1983 return error;
1984 }
1985 error = wi_setdef(sc, &wreq);
1986 if (error)
1987 return error;
1988
1989 wreq.wi_type = WI_RID_ENCRYPTION;
1990 wreq.wi_val[0] = htole16(nwkey->i_wepon);
1991 if (sc->sc_enabled != 0) {
1992 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1993 if (error)
1994 return error;
1995 }
1996 error = wi_setdef(sc, &wreq);
1997 if (error)
1998 return error;
1999
2000 if (sc->sc_enabled != 0)
2001 wi_init(&sc->sc_ethercom.ec_if);
2002 return 0;
2003 }
2004
2005 static int
2006 wi_get_nwkey(sc, nwkey)
2007 struct wi_softc *sc;
2008 struct ieee80211_nwkey *nwkey;
2009 {
2010 int i, len, error;
2011 struct wi_ltv_keys *wk = &sc->wi_keys;
2012
2013 if (!sc->wi_has_wep)
2014 return ENODEV;
2015 nwkey->i_wepon = sc->wi_use_wep;
2016 nwkey->i_defkid = sc->wi_tx_key + 1;
2017
2018 /* do not show any keys to non-root user */
2019 error = suser(curproc->p_ucred, &curproc->p_acflag);
2020 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2021 if (nwkey->i_key[i].i_keydat == NULL)
2022 continue;
2023 /* error holds results of suser() for the first time */
2024 if (error)
2025 return error;
2026 len = le16toh(wk->wi_keys[i].wi_keylen);
2027 if (nwkey->i_key[i].i_keylen < len)
2028 return ENOSPC;
2029 nwkey->i_key[i].i_keylen = len;
2030 error = copyout(wk->wi_keys[i].wi_keydat,
2031 nwkey->i_key[i].i_keydat, len);
2032 if (error)
2033 return error;
2034 }
2035 return 0;
2036 }
2037
2038 static int
2039 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2040 {
2041
2042 sc->wi_pm_enabled = power->i_enabled;
2043 sc->wi_max_sleep = power->i_maxsleep;
2044
2045 if (sc->sc_enabled)
2046 return (wi_init(&sc->sc_ethercom.ec_if));
2047
2048 return (0);
2049 }
2050
2051 static int
2052 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2053 {
2054
2055 power->i_enabled = sc->wi_pm_enabled;
2056 power->i_maxsleep = sc->wi_max_sleep;
2057
2058 return (0);
2059 }
2060