wi.c revision 1.11 1 /* $NetBSD: wi.c,v 1.11 2001/05/16 10:45:36 tsubai 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 i, 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 for (i = 0; i < ltv->wi_len - 1; i++)
651 ptr[i] = CSR_READ_STREAM_2(sc, WI_DATA1);
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 for (i = 0; i < ltv->wi_len - 1; i++)
779 CSR_WRITE_STREAM_2(sc, WI_DATA1, ptr[i]);
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 int i;
834 u_int16_t *ptr;
835
836 if (wi_seek(sc, id, off, WI_BAP1))
837 return(EIO);
838
839 ptr = (u_int16_t *)buf;
840 for (i = 0; i < len / 2; i++)
841 ptr[i] = CSR_READ_STREAM_2(sc, WI_DATA1);
842
843 return(0);
844 }
845
846 /*
847 * According to the comments in the HCF Light code, there is a bug in
848 * the Hermes (or possibly in certain Hermes firmware revisions) where
849 * the chip's internal autoincrement counter gets thrown off during
850 * data writes: the autoincrement is missed, causing one data word to
851 * be overwritten and subsequent words to be written to the wrong memory
852 * locations. The end result is that we could end up transmitting bogus
853 * frames without realizing it. The workaround for this is to write a
854 * couple of extra guard words after the end of the transfer, then
855 * attempt to read then back. If we fail to locate the guard words where
856 * we expect them, we preform the transfer over again.
857 */
858 static int wi_write_data(sc, id, off, buf, len)
859 struct wi_softc *sc;
860 int id, off;
861 caddr_t buf;
862 int len;
863 {
864 int i;
865 u_int16_t *ptr;
866
867 #ifdef WI_HERMES_AUTOINC_WAR
868 again:
869 #endif
870
871 if (wi_seek(sc, id, off, WI_BAP0))
872 return(EIO);
873
874 ptr = (u_int16_t *)buf;
875 for (i = 0; i < (len / 2); i++)
876 CSR_WRITE_STREAM_2(sc, WI_DATA0, ptr[i]);
877
878 #ifdef WI_HERMES_AUTOINC_WAR
879 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
880 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
881
882 if (wi_seek(sc, id, off + len, WI_BAP0))
883 return(EIO);
884
885 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
886 CSR_READ_2(sc, WI_DATA0) != 0x5678)
887 goto again;
888 #endif
889
890 return(0);
891 }
892
893 /*
894 * Allocate a region of memory inside the NIC and zero
895 * it out.
896 */
897 static int wi_alloc_nicmem(sc, len, id)
898 struct wi_softc *sc;
899 int len;
900 int *id;
901 {
902 int i;
903
904 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
905 printf("%s: failed to allocate %d bytes on NIC\n",
906 sc->sc_dev.dv_xname, len);
907 return(ENOMEM);
908 }
909
910 for (i = 0; i < WI_TIMEOUT; i++) {
911 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
912 break;
913 }
914
915 if (i == WI_TIMEOUT) {
916 printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
917 return(ETIMEDOUT);
918 }
919
920 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
921 *id = CSR_READ_2(sc, WI_ALLOC_FID);
922
923 if (wi_seek(sc, *id, 0, WI_BAP0)) {
924 printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
925 return(EIO);
926 }
927
928 for (i = 0; i < len / 2; i++)
929 CSR_WRITE_2(sc, WI_DATA0, 0);
930
931 return(0);
932 }
933
934 static void wi_setmulti(sc)
935 struct wi_softc *sc;
936 {
937 struct ifnet *ifp;
938 int i = 0;
939 struct wi_ltv_mcast mcast;
940 struct ether_multi *enm;
941 struct ether_multistep estep;
942 struct ethercom *ec = &sc->sc_ethercom;
943
944 ifp = &sc->sc_ethercom.ec_if;
945
946 if ((ifp->if_flags & IFF_PROMISC) != 0) {
947 allmulti:
948 ifp->if_flags |= IFF_ALLMULTI;
949 bzero((char *)&mcast, sizeof(mcast));
950 mcast.wi_type = WI_RID_MCAST;
951 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
952
953 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
954 return;
955 }
956
957 i = 0;
958 ETHER_FIRST_MULTI(estep, ec, enm);
959 while (enm != NULL) {
960 /* Punt on ranges or too many multicast addresses. */
961 if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
962 ETHER_ADDR_LEN) != 0 ||
963 i >= 16)
964 goto allmulti;
965
966 bcopy(enm->enm_addrlo,
967 (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
968 i++;
969 ETHER_NEXT_MULTI(estep, enm);
970 }
971
972 ifp->if_flags &= ~IFF_ALLMULTI;
973 mcast.wi_type = WI_RID_MCAST;
974 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
975 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
976 }
977
978 static int
979 wi_setdef(sc, wreq)
980 struct wi_softc *sc;
981 struct wi_req *wreq;
982 {
983 struct sockaddr_dl *sdl;
984 struct ifnet *ifp;
985 int error = 0;
986
987 ifp = &sc->sc_ethercom.ec_if;
988
989 switch(wreq->wi_type) {
990 case WI_RID_MAC_NODE:
991 sdl = (struct sockaddr_dl *)ifp->if_sadl;
992 bcopy((char *)&wreq->wi_val, (char *)&sc->sc_macaddr,
993 ETHER_ADDR_LEN);
994 bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
995 break;
996 case WI_RID_PORTTYPE:
997 error = wi_sync_media(sc, le16toh(wreq->wi_val[0]), sc->wi_tx_rate);
998 break;
999 case WI_RID_TX_RATE:
1000 error = wi_sync_media(sc, sc->wi_ptype, le16toh(wreq->wi_val[0]));
1001 break;
1002 case WI_RID_MAX_DATALEN:
1003 sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
1004 break;
1005 case WI_RID_RTS_THRESH:
1006 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
1007 break;
1008 case WI_RID_SYSTEM_SCALE:
1009 sc->wi_ap_density = le16toh(wreq->wi_val[0]);
1010 break;
1011 case WI_RID_CREATE_IBSS:
1012 sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
1013 break;
1014 case WI_RID_OWN_CHNL:
1015 sc->wi_channel = le16toh(wreq->wi_val[0]);
1016 break;
1017 case WI_RID_NODENAME:
1018 error = wi_set_ssid(&sc->wi_nodeid,
1019 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1020 break;
1021 case WI_RID_DESIRED_SSID:
1022 error = wi_set_ssid(&sc->wi_netid,
1023 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1024 break;
1025 case WI_RID_OWN_SSID:
1026 error = wi_set_ssid(&sc->wi_ibssid,
1027 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
1028 break;
1029 case WI_RID_PM_ENABLED:
1030 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
1031 break;
1032 case WI_RID_MICROWAVE_OVEN:
1033 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
1034 break;
1035 case WI_RID_MAX_SLEEP:
1036 sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
1037 break;
1038 case WI_RID_AUTH_CNTL:
1039 sc->wi_authtype = le16toh(wreq->wi_val[0]);
1040 break;
1041 case WI_RID_ROAMING_MODE:
1042 sc->wi_roaming = le16toh(wreq->wi_val[0]);
1043 break;
1044 case WI_RID_ENCRYPTION:
1045 sc->wi_use_wep = le16toh(wreq->wi_val[0]);
1046 break;
1047 case WI_RID_TX_CRYPT_KEY:
1048 sc->wi_tx_key = le16toh(wreq->wi_val[0]);
1049 break;
1050 case WI_RID_DEFLT_CRYPT_KEYS:
1051 bcopy((char *)wreq, (char *)&sc->wi_keys,
1052 sizeof(struct wi_ltv_keys));
1053 break;
1054 default:
1055 error = EINVAL;
1056 break;
1057 }
1058
1059 return (error);
1060 }
1061
1062 static int
1063 wi_getdef(sc, wreq)
1064 struct wi_softc *sc;
1065 struct wi_req *wreq;
1066 {
1067 struct sockaddr_dl *sdl;
1068 struct ifnet *ifp;
1069 int error = 0;
1070
1071 ifp = &sc->sc_ethercom.ec_if;
1072
1073 wreq->wi_len = 2; /* XXX */
1074 switch (wreq->wi_type) {
1075 case WI_RID_MAC_NODE:
1076 wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
1077 sdl = (struct sockaddr_dl *)ifp->if_sadl;
1078 bcopy(&sc->sc_macaddr, &wreq->wi_val, ETHER_ADDR_LEN);
1079 bcopy(LLADDR(sdl), &wreq->wi_val, ETHER_ADDR_LEN);
1080 break;
1081 case WI_RID_PORTTYPE:
1082 wreq->wi_val[0] = htole16(sc->wi_ptype);
1083 break;
1084 case WI_RID_TX_RATE:
1085 wreq->wi_val[0] = htole16(sc->wi_tx_rate);
1086 break;
1087 case WI_RID_MAX_DATALEN:
1088 wreq->wi_val[0] = htole16(sc->wi_max_data_len);
1089 break;
1090 case WI_RID_RTS_THRESH:
1091 wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
1092 break;
1093 case WI_RID_SYSTEM_SCALE:
1094 wreq->wi_val[0] = htole16(sc->wi_ap_density);
1095 break;
1096 case WI_RID_CREATE_IBSS:
1097 wreq->wi_val[0] = htole16(sc->wi_create_ibss);
1098 break;
1099 case WI_RID_OWN_CHNL:
1100 wreq->wi_val[0] = htole16(sc->wi_channel);
1101 break;
1102 case WI_RID_NODENAME:
1103 wi_request_fill_ssid(wreq, &sc->wi_nodeid);
1104 break;
1105 case WI_RID_DESIRED_SSID:
1106 wi_request_fill_ssid(wreq, &sc->wi_netid);
1107 break;
1108 case WI_RID_OWN_SSID:
1109 wi_request_fill_ssid(wreq, &sc->wi_ibssid);
1110 break;
1111 case WI_RID_PM_ENABLED:
1112 wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
1113 break;
1114 case WI_RID_MICROWAVE_OVEN:
1115 wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
1116 break;
1117 case WI_RID_MAX_SLEEP:
1118 wreq->wi_val[0] = htole16(sc->wi_max_sleep);
1119 break;
1120 case WI_RID_AUTH_CNTL:
1121 wreq->wi_val[0] = htole16(sc->wi_authtype);
1122 break;
1123 case WI_RID_ROAMING_MODE:
1124 wreq->wi_val[0] = htole16(sc->wi_roaming);
1125 break;
1126 case WI_RID_WEP_AVAIL:
1127 wreq->wi_val[0] = htole16(sc->wi_has_wep);
1128 break;
1129 case WI_RID_ENCRYPTION:
1130 wreq->wi_val[0] = htole16(sc->wi_use_wep);
1131 break;
1132 case WI_RID_TX_CRYPT_KEY:
1133 wreq->wi_val[0] = htole16(sc->wi_tx_key);
1134 break;
1135 case WI_RID_DEFLT_CRYPT_KEYS:
1136 wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
1137 bcopy(&sc->wi_keys, wreq, sizeof(struct wi_ltv_keys));
1138 break;
1139 default:
1140 #if 0
1141 error = EIO;
1142 #else
1143 #ifdef WI_DEBUG
1144 printf("%s: wi_getdef: unknown request %d\n",
1145 sc->sc_dev.dv_xname, wreq->wi_type);
1146 #endif
1147 #endif
1148 break;
1149 }
1150
1151 return (error);
1152 }
1153
1154 static int
1155 wi_ioctl(ifp, command, data)
1156 struct ifnet *ifp;
1157 u_long command;
1158 caddr_t data;
1159 {
1160 int s, error = 0;
1161 struct wi_softc *sc = ifp->if_softc;
1162 struct wi_req wreq;
1163 struct ifreq *ifr;
1164 struct proc *p = curproc;
1165 struct ieee80211_nwid nwid;
1166
1167 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
1168 return (ENXIO);
1169
1170 s = splnet();
1171
1172 ifr = (struct ifreq *)data;
1173 switch (command) {
1174 case SIOCSIFADDR:
1175 case SIOCGIFADDR:
1176 case SIOCSIFMTU:
1177 error = ether_ioctl(ifp, command, data);
1178 break;
1179 case SIOCSIFFLAGS:
1180 if (ifp->if_flags & IFF_UP) {
1181 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, 1);
1185 } else if (ifp->if_flags & IFF_RUNNING &&
1186 !(ifp->if_flags & IFF_PROMISC) &&
1187 sc->wi_if_flags & IFF_PROMISC) {
1188 WI_SETVAL(WI_RID_PROMISC, 0);
1189 }
1190 wi_init(ifp);
1191 } else {
1192 if (ifp->if_flags & IFF_RUNNING) {
1193 wi_stop(ifp, 0);
1194 }
1195 }
1196 sc->wi_if_flags = ifp->if_flags;
1197
1198 if (!(ifp->if_flags & IFF_UP)) {
1199 if (sc->sc_enabled) {
1200 if (sc->sc_disable)
1201 (*sc->sc_disable)(sc);
1202 sc->sc_enabled = 0;
1203 ifp->if_flags &= ~IFF_RUNNING;
1204 }
1205 }
1206 error = 0;
1207 break;
1208 case SIOCADDMULTI:
1209 case SIOCDELMULTI:
1210 error = (command == SIOCADDMULTI) ?
1211 ether_addmulti(ifr, &sc->sc_ethercom) :
1212 ether_delmulti(ifr, &sc->sc_ethercom);
1213 if (error == ENETRESET) {
1214 if (sc->sc_enabled != 0) {
1215 /*
1216 * Multicast list has changed. Set the
1217 * hardware filter accordingly.
1218 */
1219 wi_setmulti(sc);
1220 }
1221 error = 0;
1222 }
1223 break;
1224 case SIOCSIFMEDIA:
1225 case SIOCGIFMEDIA:
1226 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1227 break;
1228 case SIOCGWAVELAN:
1229 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1230 if (error)
1231 break;
1232 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1233 /* XXX native byte order */
1234 bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1235 sizeof(sc->wi_stats));
1236 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1237 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
1238 /* For non-root user, return all-zeroes keys */
1239 if (suser(p->p_ucred, &p->p_acflag))
1240 bzero((char *)&wreq,
1241 sizeof(struct wi_ltv_keys));
1242 else
1243 bcopy((char *)&sc->wi_keys, (char *)&wreq,
1244 sizeof(struct wi_ltv_keys));
1245 } else {
1246 if (sc->sc_enabled == 0)
1247 error = wi_getdef(sc, &wreq);
1248 else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
1249 error = EINVAL;
1250 }
1251 if (error == 0)
1252 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1253 break;
1254 case SIOCSWAVELAN:
1255 error = suser(p->p_ucred, &p->p_acflag);
1256 if (error)
1257 break;
1258 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1259 if (error)
1260 break;
1261 if (wreq.wi_type == WI_RID_IFACE_STATS) {
1262 error = EINVAL;
1263 break;
1264 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1265 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1266 wreq.wi_len);
1267 } else {
1268 if (sc->sc_enabled != 0)
1269 error = wi_write_record(sc,
1270 (struct wi_ltv_gen *)&wreq);
1271 if (error == 0)
1272 error = wi_setdef(sc, &wreq);
1273 if (error == 0 && sc->sc_enabled != 0)
1274 /* Reinitialize WaveLAN. */
1275 wi_init(ifp);
1276 }
1277 break;
1278 case SIOCG80211NWID:
1279 if (sc->sc_enabled == 0) {
1280 /* Return the desired ID */
1281 error = copyout(&sc->wi_netid, ifr->ifr_data,
1282 sizeof(sc->wi_netid));
1283 } else {
1284 wreq.wi_type = WI_RID_CURRENT_SSID;
1285 wreq.wi_len = WI_MAX_DATALEN;
1286 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
1287 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
1288 error = EINVAL;
1289 else {
1290 wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
1291 le16toh(wreq.wi_val[0]));
1292 error = copyout(&nwid, ifr->ifr_data,
1293 sizeof(nwid));
1294 }
1295 }
1296 break;
1297 case SIOCS80211NWID:
1298 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
1299 if (error != 0)
1300 break;
1301 if (nwid.i_len > IEEE80211_NWID_LEN) {
1302 error = EINVAL;
1303 break;
1304 }
1305 if (sc->wi_netid.i_len == nwid.i_len &&
1306 memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
1307 break;
1308 wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
1309 if (sc->sc_enabled != 0)
1310 /* Reinitialize WaveLAN. */
1311 wi_init(ifp);
1312 break;
1313 case SIOCS80211NWKEY:
1314 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1315 break;
1316 case SIOCG80211NWKEY:
1317 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1318 break;
1319 case SIOCS80211POWER:
1320 error = wi_set_pm(sc, (struct ieee80211_power *)data);
1321 break;
1322 case SIOCG80211POWER:
1323 error = wi_get_pm(sc, (struct ieee80211_power *)data);
1324 break;
1325
1326 default:
1327 error = EINVAL;
1328 break;
1329 }
1330
1331 splx(s);
1332 return (error);
1333 }
1334
1335 static int
1336 wi_init(ifp)
1337 struct ifnet *ifp;
1338 {
1339 struct wi_softc *sc = ifp->if_softc;
1340 struct wi_req wreq;
1341 struct wi_ltv_macaddr mac;
1342 int error, id = 0;
1343
1344 if (!sc->sc_enabled) {
1345 if ((error = (*sc->sc_enable)(sc)) != 0)
1346 goto out;
1347 sc->sc_enabled = 1;
1348 }
1349
1350 wi_stop(ifp, 0);
1351 wi_reset(sc);
1352
1353 /* Program max data length. */
1354 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1355
1356 /* Enable/disable IBSS creation. */
1357 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1358
1359 /* Set the port type. */
1360 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1361
1362 /* Program the RTS/CTS threshold. */
1363 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1364
1365 /* Program the TX rate */
1366 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1367
1368 /* Access point density */
1369 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1370
1371 /* Power Management Enabled */
1372 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1373
1374 /* Power Managment Max Sleep */
1375 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1376
1377 /* Roaming type */
1378 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
1379
1380 /* Specify the IBSS name */
1381 wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
1382
1383 /* Specify the network name */
1384 wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
1385
1386 /* Specify the frequency to use */
1387 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1388
1389 /* Program the nodename. */
1390 wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
1391
1392 /* Set our MAC address. */
1393 mac.wi_len = 4;
1394 mac.wi_type = WI_RID_MAC_NODE;
1395 memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
1396 wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1397
1398 /* Initialize promisc mode. */
1399 if (ifp->if_flags & IFF_PROMISC) {
1400 WI_SETVAL(WI_RID_PROMISC, 1);
1401 } else {
1402 WI_SETVAL(WI_RID_PROMISC, 0);
1403 }
1404
1405 /* Configure WEP. */
1406 if (sc->wi_has_wep) {
1407 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1408 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1409 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1410 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1411 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1412 if (sc->sc_prism2 && sc->wi_use_wep) {
1413 /*
1414 * Prism2 Firmware version less than 0.8 variant3
1415 * If promiscuous mode disable, Prism2 chip
1416 * does not work with WEP .
1417 * It is under investigation for details.
1418 * (ichiro (at) netbsd.org)
1419 */
1420 if (sc->sc_prism2_ver < 83 ) {
1421 /* firm ver < 0.8 variant 3 */
1422 WI_SETVAL(WI_RID_PROMISC, 1);
1423 }
1424 WI_SETVAL(WI_RID_AUTH_CNTL, sc->wi_authtype);
1425 }
1426 }
1427
1428 /* Set multicast filter. */
1429 wi_setmulti(sc);
1430
1431 /* Enable desired port */
1432 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
1433
1434 if ((error = wi_alloc_nicmem(sc,
1435 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
1436 printf("%s: tx buffer allocation failed\n",
1437 sc->sc_dev.dv_xname);
1438 goto out;
1439 }
1440 sc->wi_tx_data_id = id;
1441
1442 if ((error = wi_alloc_nicmem(sc,
1443 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
1444 printf("%s: mgmt. buffer allocation failed\n",
1445 sc->sc_dev.dv_xname);
1446 goto out;
1447 }
1448 sc->wi_tx_mgmt_id = id;
1449
1450 /* Enable interrupts */
1451 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1452
1453 ifp->if_flags |= IFF_RUNNING;
1454 ifp->if_flags &= ~IFF_OACTIVE;
1455
1456 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
1457
1458 out:
1459 if (error) {
1460 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1461 ifp->if_timer = 0;
1462 printf("%s: interface not running\n", sc->sc_dev.dv_xname);
1463 }
1464 return (error);
1465 }
1466
1467 static void
1468 wi_start(ifp)
1469 struct ifnet *ifp;
1470 {
1471 struct wi_softc *sc;
1472 struct mbuf *m0;
1473 struct wi_frame tx_frame;
1474 struct ether_header *eh;
1475 int id;
1476
1477 sc = ifp->if_softc;
1478
1479 if (ifp->if_flags & IFF_OACTIVE)
1480 return;
1481
1482 IFQ_DEQUEUE(&ifp->if_snd, m0);
1483 if (m0 == NULL)
1484 return;
1485
1486 bzero((char *)&tx_frame, sizeof(tx_frame));
1487 id = sc->wi_tx_data_id;
1488 eh = mtod(m0, struct ether_header *);
1489
1490 /*
1491 * Use RFC1042 encoding for IP and ARP datagrams,
1492 * 802.3 for anything else.
1493 */
1494 if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
1495 ntohs(eh->ether_type) == ETHERTYPE_ARP ||
1496 ntohs(eh->ether_type) == ETHERTYPE_REVARP ||
1497 ntohs(eh->ether_type) == ETHERTYPE_IPV6) {
1498 bcopy((char *)&eh->ether_dhost,
1499 (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
1500 bcopy((char *)&eh->ether_shost,
1501 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
1502 bcopy((char *)&eh->ether_dhost,
1503 (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
1504 bcopy((char *)&eh->ether_shost,
1505 (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
1506
1507 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1508 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
1509 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
1510 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
1511 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
1512 tx_frame.wi_type = eh->ether_type;
1513
1514 m_copydata(m0, sizeof(struct ether_header),
1515 m0->m_pkthdr.len - sizeof(struct ether_header),
1516 (caddr_t)&sc->wi_txbuf);
1517
1518 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1519 sizeof(struct wi_frame));
1520 wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
1521 (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
1522 } else {
1523 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
1524
1525 m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
1526
1527 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
1528 sizeof(struct wi_frame));
1529 wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
1530 m0->m_pkthdr.len + 2);
1531 }
1532
1533 #if NBPFILTER > 0
1534 /*
1535 * If there's a BPF listener, bounce a copy of
1536 * this frame to him.
1537 */
1538 if (ifp->if_bpf)
1539 bpf_mtap(ifp->if_bpf, m0);
1540 #endif
1541
1542 m_freem(m0);
1543
1544 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
1545 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
1546
1547 ifp->if_flags |= IFF_OACTIVE;
1548
1549 /*
1550 * Set a timeout in case the chip goes out to lunch.
1551 */
1552 ifp->if_timer = 5;
1553
1554 return;
1555 }
1556
1557 static int
1558 wi_mgmt_xmit(sc, data, len)
1559 struct wi_softc *sc;
1560 caddr_t data;
1561 int len;
1562 {
1563 struct wi_frame tx_frame;
1564 int id;
1565 struct wi_80211_hdr *hdr;
1566 caddr_t dptr;
1567
1568 hdr = (struct wi_80211_hdr *)data;
1569 dptr = data + sizeof(struct wi_80211_hdr);
1570
1571 bzero((char *)&tx_frame, sizeof(tx_frame));
1572 id = sc->wi_tx_mgmt_id;
1573
1574 bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
1575 sizeof(struct wi_80211_hdr));
1576
1577 tx_frame.wi_dat_len = htole16(len - WI_SNAPHDR_LEN);
1578 tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
1579
1580 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
1581 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
1582 (len - sizeof(struct wi_80211_hdr)) + 2);
1583
1584 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
1585 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
1586 return(EIO);
1587 }
1588
1589 return(0);
1590 }
1591
1592 static void
1593 wi_stop(ifp, disable)
1594 struct ifnet *ifp;
1595 {
1596 struct wi_softc *sc = ifp->if_softc;
1597
1598 CSR_WRITE_2(sc, WI_INT_EN, 0);
1599 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
1600
1601 callout_stop(&sc->wi_inquire_ch);
1602
1603 if (disable) {
1604 if (sc->sc_enabled) {
1605 if (sc->sc_disable)
1606 (*sc->sc_disable)(sc);
1607 sc->sc_enabled = 0;
1608 }
1609 }
1610
1611 ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
1612 ifp->if_timer = 0;
1613 }
1614
1615 static void
1616 wi_watchdog(ifp)
1617 struct ifnet *ifp;
1618 {
1619 struct wi_softc *sc;
1620
1621 sc = ifp->if_softc;
1622
1623 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1624
1625 wi_init(ifp);
1626
1627 ifp->if_oerrors++;
1628
1629 return;
1630 }
1631
1632 void
1633 wi_shutdown(sc)
1634 struct wi_softc *sc;
1635 {
1636 int s;
1637
1638 s = splnet();
1639 if (sc->sc_enabled) {
1640 if (sc->sc_disable)
1641 (*sc->sc_disable)(sc);
1642 sc->sc_enabled = 0;
1643 }
1644 splx(s);
1645 }
1646
1647 int
1648 wi_activate(self, act)
1649 struct device *self;
1650 enum devact act;
1651 {
1652 struct wi_softc *sc = (struct wi_softc *)self;
1653 int rv = 0, s;
1654
1655 s = splnet();
1656 switch (act) {
1657 case DVACT_ACTIVATE:
1658 rv = EOPNOTSUPP;
1659 break;
1660
1661 case DVACT_DEACTIVATE:
1662 if_deactivate(&sc->sc_ethercom.ec_if);
1663 break;
1664 }
1665 splx(s);
1666 return (rv);
1667 }
1668
1669 static void
1670 wi_get_id(sc)
1671 struct wi_softc *sc;
1672 {
1673 struct wi_ltv_ver ver;
1674
1675 /* getting chip identity */
1676 memset(&ver, 0, sizeof(ver));
1677 ver.wi_type = WI_RID_CARDID;
1678 ver.wi_len = 5;
1679 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
1680 printf("%s: using ", sc->sc_dev.dv_xname);
1681 switch (le16toh(ver.wi_ver[0])) {
1682 case WI_NIC_EVB2:
1683 printf("PRISM I HFA3841(EVB2)");
1684 sc->sc_prism2 = 1;
1685 break;
1686 case WI_NIC_HWB3763:
1687 printf("PRISM II HWB3763 rev.B");
1688 sc->sc_prism2 = 1;
1689 break;
1690 case WI_NIC_HWB3163:
1691 printf("PRISM II HWB3163 rev.A");
1692 sc->sc_prism2 = 1;
1693 break;
1694 case WI_NIC_HWB3163B:
1695 printf("PRISM II HWB3163 rev.B");
1696 sc->sc_prism2 = 1;
1697 break;
1698 case WI_NIC_EVB3:
1699 printf("PRISM II HFA3842(EVB3)");
1700 sc->sc_prism2 = 1;
1701 break;
1702 case WI_NIC_HWB1153:
1703 printf("PRISM I HFA1153");
1704 sc->sc_prism2 = 1;
1705 break;
1706 case WI_NIC_P2_SST:
1707 printf("PRISM II HWB3163 SST-flash");
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