1 /* $OpenBSD: if_wi.c,v 1.101 2003/10/26 15:34:15 drahn Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 1998, 1999 5 * Bill Paul <wpaul@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 * From: if_wi.c,v 1.7 1999/07/04 14:40:22 wpaul Exp $ 35 */ 36 37 /* 38 * Lucent WaveLAN/IEEE 802.11 driver for OpenBSD. 39 * 40 * Originally written by Bill Paul <wpaul@ctr.columbia.edu> 41 * Electrical Engineering Department 42 * Columbia University, New York City 43 */ 44 45 /* 46 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN 47 * from Lucent. Unlike the older cards, the new ones are programmed 48 * entirely via a firmware-driven controller called the Hermes. 49 * Unfortunately, Lucent will not release the Hermes programming manual 50 * without an NDA (if at all). What they do release is an API library 51 * called the HCF (Hardware Control Functions) which is supposed to 52 * do the device-specific operations of a device driver for you. The 53 * publicly available version of the HCF library (the 'HCF Light') is 54 * a) extremely gross, b) lacks certain features, particularly support 55 * for 802.11 frames, and c) is contaminated by the GNU Public License. 56 * 57 * This driver does not use the HCF or HCF Light at all. Instead, it 58 * programs the Hermes controller directly, using information gleaned 59 * from the HCF Light code and corresponding documentation. 60 */ 61 62 #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */ 63 #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */ 64 65 #include "bpfilter.h" 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/sockio.h> 70 #include <sys/mbuf.h> 71 #include <sys/malloc.h> 72 #include <sys/kernel.h> 73 #include <sys/proc.h> 74 #include <sys/socket.h> 75 #include <sys/device.h> 76 77 #include <net/if.h> 78 #include <net/if_dl.h> 79 #include <net/if_media.h> 80 #include <net/if_types.h> 81 82 #ifdef INET 83 #include <netinet/in.h> 84 #include <netinet/in_systm.h> 85 #include <netinet/in_var.h> 86 #include <netinet/ip.h> 87 #include <netinet/if_ether.h> 88 #endif 89 90 #include <net/if_ieee80211.h> 91 92 #if NBPFILTER > 0 93 #include <net/bpf.h> 94 #endif 95 96 #include <machine/bus.h> 97 98 #include <dev/rndvar.h> 99 100 #include <dev/ic/if_wireg.h> 101 #include <dev/ic/if_wi_ieee.h> 102 #include <dev/ic/if_wivar.h> 103 104 #include <crypto/arc4.h> 105 106 #define BPF_MTAP(if,mbuf) bpf_mtap((if)->if_bpf, (mbuf)) 107 #define BPFATTACH(if_bpf,if,dlt,sz) 108 #define STATIC 109 110 #ifdef WIDEBUG 111 112 u_int32_t widebug = WIDEBUG; 113 114 #define WID_INTR 0x01 115 #define WID_START 0x02 116 #define WID_IOCTL 0x04 117 #define WID_INIT 0x08 118 #define WID_STOP 0x10 119 #define WID_RESET 0x20 120 121 #define DPRINTF(mask,args) if (widebug & (mask)) printf args; 122 123 #else /* !WIDEBUG */ 124 #define DPRINTF(mask,args) 125 #endif /* WIDEBUG */ 126 127 #if !defined(lint) && !defined(__OpenBSD__) 128 static const char rcsid[] = 129 "$OpenBSD: if_wi.c,v 1.101 2003/10/26 15:34:15 drahn Exp $"; 130 #endif /* lint */ 131 132 #ifdef foo 133 static u_int8_t wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 }; 134 #endif 135 136 STATIC void wi_reset(struct wi_softc *); 137 STATIC int wi_ioctl(struct ifnet *, u_long, caddr_t); 138 STATIC void wi_init_io(struct wi_softc *); 139 STATIC void wi_start(struct ifnet *); 140 STATIC void wi_watchdog(struct ifnet *); 141 STATIC void wi_shutdown(void *); 142 STATIC void wi_rxeof(struct wi_softc *); 143 STATIC void wi_txeof(struct wi_softc *, int); 144 STATIC void wi_update_stats(struct wi_softc *); 145 STATIC void wi_setmulti(struct wi_softc *); 146 147 STATIC int wi_cmd_io(struct wi_softc *, int, int, int, int); 148 STATIC int wi_read_record_io(struct wi_softc *, struct wi_ltv_gen *); 149 STATIC int wi_write_record_io(struct wi_softc *, struct wi_ltv_gen *); 150 STATIC int wi_read_data_io(struct wi_softc *, int, 151 int, caddr_t, int); 152 STATIC int wi_write_data_io(struct wi_softc *, int, 153 int, caddr_t, int); 154 STATIC int wi_seek(struct wi_softc *, int, int, int); 155 156 STATIC void wi_inquire(void *); 157 STATIC int wi_setdef(struct wi_softc *, struct wi_req *); 158 STATIC void wi_get_id(struct wi_softc *); 159 160 STATIC int wi_media_change(struct ifnet *); 161 STATIC void wi_media_status(struct ifnet *, struct ifmediareq *); 162 163 STATIC int wi_set_ssid(struct ieee80211_nwid *, u_int8_t *, int); 164 STATIC int wi_set_nwkey(struct wi_softc *, struct ieee80211_nwkey *); 165 STATIC int wi_get_nwkey(struct wi_softc *, struct ieee80211_nwkey *); 166 STATIC int wi_sync_media(struct wi_softc *, int, int); 167 STATIC int wi_set_pm(struct wi_softc *, struct ieee80211_power *); 168 STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *); 169 170 STATIC int wi_get_debug(struct wi_softc *, struct wi_req *); 171 STATIC int wi_set_debug(struct wi_softc *, struct wi_req *); 172 173 STATIC void wi_do_hostencrypt(struct wi_softc *, caddr_t, int); 174 STATIC int wi_do_hostdecrypt(struct wi_softc *, caddr_t, int); 175 176 STATIC int wi_alloc_nicmem_io(struct wi_softc *, int, int *); 177 STATIC int wi_get_fid_io(struct wi_softc *sc, int fid); 178 STATIC void wi_intr_enable(struct wi_softc *sc, int mode); 179 STATIC void wi_intr_ack(struct wi_softc *sc, int mode); 180 181 /* Autoconfig definition of driver back-end */ 182 struct cfdriver wi_cd = { 183 NULL, "wi", DV_IFNET 184 }; 185 186 const struct wi_card_ident wi_card_ident[] = { 187 WI_CARD_IDS 188 }; 189 190 struct wi_funcs wi_func_io = { 191 wi_cmd_io, 192 wi_read_record_io, 193 wi_write_record_io, 194 wi_alloc_nicmem_io, 195 wi_read_data_io, 196 wi_write_data_io, 197 wi_get_fid_io, 198 wi_init_io, 199 200 wi_start, 201 wi_ioctl, 202 wi_watchdog, 203 wi_inquire, 204 }; 205 206 int 207 wi_attach(struct wi_softc *sc, struct wi_funcs *funcs) 208 { 209 struct wi_ltv_macaddr mac; 210 struct wi_ltv_gen gen; 211 struct ifnet *ifp; 212 int error; 213 214 sc->sc_funcs = funcs; 215 216 wi_reset(sc); 217 218 /* Read the station address. */ 219 mac.wi_type = WI_RID_MAC_NODE; 220 mac.wi_len = 4; 221 error = wi_read_record(sc, (struct wi_ltv_gen *)&mac); 222 if (error) { 223 printf(": unable to read station address\n"); 224 return (error); 225 } 226 bcopy((char *)&mac.wi_mac_addr, (char *)&sc->sc_arpcom.ac_enaddr, 227 ETHER_ADDR_LEN); 228 229 wi_get_id(sc); 230 printf("address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr)); 231 232 ifp = &sc->sc_arpcom.ac_if; 233 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 234 ifp->if_softc = sc; 235 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 236 ifp->if_ioctl = funcs->f_ioctl; 237 ifp->if_start = funcs->f_start; 238 ifp->if_watchdog = funcs->f_watchdog; 239 ifp->if_baudrate = 10000000; 240 IFQ_SET_READY(&ifp->if_snd); 241 242 (void)wi_set_ssid(&sc->wi_node_name, WI_DEFAULT_NODENAME, 243 sizeof(WI_DEFAULT_NODENAME) - 1); 244 (void)wi_set_ssid(&sc->wi_net_name, WI_DEFAULT_NETNAME, 245 sizeof(WI_DEFAULT_NETNAME) - 1); 246 (void)wi_set_ssid(&sc->wi_ibss_name, WI_DEFAULT_IBSS, 247 sizeof(WI_DEFAULT_IBSS) - 1); 248 249 sc->wi_portnum = WI_DEFAULT_PORT; 250 sc->wi_ptype = WI_PORTTYPE_BSS; 251 sc->wi_ap_density = WI_DEFAULT_AP_DENSITY; 252 sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH; 253 sc->wi_tx_rate = WI_DEFAULT_TX_RATE; 254 sc->wi_max_data_len = WI_DEFAULT_DATALEN; 255 sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS; 256 sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED; 257 sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP; 258 sc->wi_roaming = WI_DEFAULT_ROAMING; 259 sc->wi_authtype = WI_DEFAULT_AUTHTYPE; 260 sc->wi_diversity = WI_DEFAULT_DIVERSITY; 261 sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP; 262 263 /* 264 * Read the default channel from the NIC. This may vary 265 * depending on the country where the NIC was purchased, so 266 * we can't hard-code a default and expect it to work for 267 * everyone. 268 */ 269 gen.wi_type = WI_RID_OWN_CHNL; 270 gen.wi_len = 2; 271 if (wi_read_record(sc, &gen) == 0) 272 sc->wi_channel = letoh16(gen.wi_val); 273 else 274 sc->wi_channel = 3; 275 276 /* 277 * Set flags based on firmware version. 278 */ 279 switch (sc->sc_firmware_type) { 280 case WI_LUCENT: 281 sc->wi_flags |= WI_FLAGS_HAS_ROAMING; 282 if (sc->sc_sta_firmware_ver >= 60000) 283 sc->wi_flags |= WI_FLAGS_HAS_MOR; 284 if (sc->sc_sta_firmware_ver >= 60006) { 285 sc->wi_flags |= WI_FLAGS_HAS_IBSS; 286 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; 287 } 288 sc->wi_ibss_port = htole16(1); 289 break; 290 case WI_INTERSIL: 291 sc->wi_flags |= WI_FLAGS_HAS_ROAMING; 292 if (sc->sc_sta_firmware_ver >= 800) { 293 #ifndef SMALL_KERNEL 294 sc->wi_flags |= WI_FLAGS_HAS_HOSTAP; 295 #endif 296 sc->wi_flags |= WI_FLAGS_HAS_IBSS; 297 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; 298 } 299 sc->wi_ibss_port = htole16(0); 300 break; 301 case WI_SYMBOL: 302 sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY; 303 if (sc->sc_sta_firmware_ver >= 20000) 304 sc->wi_flags |= WI_FLAGS_HAS_IBSS; 305 if (sc->sc_sta_firmware_ver >= 25000) 306 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; 307 sc->wi_ibss_port = htole16(4); 308 break; 309 } 310 311 /* 312 * Find out if we support WEP on this card. 313 */ 314 gen.wi_type = WI_RID_WEP_AVAIL; 315 gen.wi_len = 2; 316 if (wi_read_record(sc, &gen) == 0 && gen.wi_val != htole16(0)) 317 sc->wi_flags |= WI_FLAGS_HAS_WEP; 318 timeout_set(&sc->sc_timo, funcs->f_inquire, sc); 319 320 bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats)); 321 322 /* Find supported rates. */ 323 gen.wi_type = WI_RID_DATA_RATES; 324 gen.wi_len = 2; 325 if (wi_read_record(sc, &gen)) 326 sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M | 327 WI_SUPPRATES_5M | WI_SUPPRATES_11M; 328 else 329 sc->wi_supprates = gen.wi_val; 330 331 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status); 332 #define ADD(m, c) ifmedia_add(&sc->sc_media, (m), (c), NULL) 333 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0); 334 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0); 335 if (sc->wi_flags & WI_FLAGS_HAS_IBSS) 336 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS, 337 0), 0); 338 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) 339 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 340 IFM_IEEE80211_IBSSMASTER, 0), 0); 341 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) 342 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 343 IFM_IEEE80211_HOSTAP, 0), 0); 344 if (sc->wi_supprates & WI_SUPPRATES_1M) { 345 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); 346 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 347 IFM_IEEE80211_ADHOC, 0), 0); 348 if (sc->wi_flags & WI_FLAGS_HAS_IBSS) 349 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 350 IFM_IEEE80211_IBSS, 0), 0); 351 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) 352 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 353 IFM_IEEE80211_IBSSMASTER, 0), 0); 354 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) 355 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 356 IFM_IEEE80211_HOSTAP, 0), 0); 357 } 358 if (sc->wi_supprates & WI_SUPPRATES_2M) { 359 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); 360 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 361 IFM_IEEE80211_ADHOC, 0), 0); 362 if (sc->wi_flags & WI_FLAGS_HAS_IBSS) 363 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 364 IFM_IEEE80211_IBSS, 0), 0); 365 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) 366 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 367 IFM_IEEE80211_IBSSMASTER, 0), 0); 368 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) 369 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 370 IFM_IEEE80211_HOSTAP, 0), 0); 371 } 372 if (sc->wi_supprates & WI_SUPPRATES_5M) { 373 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); 374 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 375 IFM_IEEE80211_ADHOC, 0), 0); 376 if (sc->wi_flags & WI_FLAGS_HAS_IBSS) 377 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 378 IFM_IEEE80211_IBSS, 0), 0); 379 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) 380 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 381 IFM_IEEE80211_IBSSMASTER, 0), 0); 382 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) 383 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 384 IFM_IEEE80211_HOSTAP, 0), 0); 385 } 386 if (sc->wi_supprates & WI_SUPPRATES_11M) { 387 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); 388 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 389 IFM_IEEE80211_ADHOC, 0), 0); 390 if (sc->wi_flags & WI_FLAGS_HAS_IBSS) 391 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 392 IFM_IEEE80211_IBSS, 0), 0); 393 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) 394 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 395 IFM_IEEE80211_IBSSMASTER, 0), 0); 396 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) 397 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 398 IFM_IEEE80211_HOSTAP, 0), 0); 399 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0); 400 } 401 #undef ADD 402 ifmedia_set(&sc->sc_media, 403 IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0)); 404 405 /* 406 * Call MI attach routines. 407 */ 408 if_attach(ifp); 409 ether_ifattach(ifp); 410 printf("\n"); 411 412 sc->wi_flags |= WI_FLAGS_ATTACHED; 413 414 #if NBPFILTER > 0 415 BPFATTACH(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, 416 sizeof(struct ether_header)); 417 #endif 418 419 sc->sc_sdhook = shutdownhook_establish(wi_shutdown, sc); 420 421 wi_init(sc); 422 wi_stop(sc); 423 424 return (0); 425 } 426 427 STATIC void 428 wi_intr_enable(struct wi_softc *sc, int mode) 429 { 430 if (!(sc->wi_flags & WI_FLAGS_BUS_USB)) 431 CSR_WRITE_2(sc, WI_INT_EN, mode); 432 } 433 434 STATIC void 435 wi_intr_ack(struct wi_softc *sc, int mode) 436 { 437 if (!(sc->wi_flags & WI_FLAGS_BUS_USB)) 438 CSR_WRITE_2(sc, WI_EVENT_ACK, mode); 439 } 440 441 int 442 wi_intr(vsc) 443 void *vsc; 444 { 445 struct wi_softc *sc = vsc; 446 struct ifnet *ifp; 447 u_int16_t status; 448 449 DPRINTF(WID_INTR, ("wi_intr: sc %p\n", sc)); 450 451 ifp = &sc->sc_arpcom.ac_if; 452 453 if (!(sc->wi_flags & WI_FLAGS_ATTACHED) || !(ifp->if_flags & IFF_UP)) { 454 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); 455 CSR_WRITE_2(sc, WI_INT_EN, 0); 456 return (0); 457 } 458 459 /* Disable interrupts. */ 460 CSR_WRITE_2(sc, WI_INT_EN, 0); 461 462 status = CSR_READ_2(sc, WI_EVENT_STAT); 463 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS); 464 465 if (status & WI_EV_RX) { 466 wi_rxeof(sc); 467 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 468 } 469 470 if (status & WI_EV_TX) { 471 wi_txeof(sc, status); 472 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX); 473 } 474 475 if (status & WI_EV_ALLOC) { 476 int id; 477 id = CSR_READ_2(sc, WI_ALLOC_FID); 478 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); 479 if (id == sc->wi_tx_data_id) 480 wi_txeof(sc, status); 481 } 482 483 if (status & WI_EV_INFO) { 484 wi_update_stats(sc); 485 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO); 486 } 487 488 if (status & WI_EV_TX_EXC) { 489 wi_txeof(sc, status); 490 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC); 491 } 492 493 if (status & WI_EV_INFO_DROP) { 494 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP); 495 } 496 497 /* Re-enable interrupts. */ 498 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); 499 500 if (!IFQ_IS_EMPTY(&ifp->if_snd)) 501 wi_start(ifp); 502 503 return (1); 504 } 505 506 STATIC int 507 wi_get_fid_io(struct wi_softc *sc, int fid) 508 { 509 return CSR_READ_2(sc, fid); 510 } 511 512 513 void 514 wi_rxeof(sc) 515 struct wi_softc *sc; 516 { 517 struct ifnet *ifp; 518 struct ether_header *eh; 519 struct mbuf *m; 520 caddr_t olddata; 521 u_int16_t msg_type; 522 int maxlen; 523 int id; 524 525 ifp = &sc->sc_arpcom.ac_if; 526 527 id = wi_get_fid(sc, WI_RX_FID); 528 529 if (sc->wi_procframe || sc->wi_debug.wi_monitor) { 530 struct wi_frame *rx_frame; 531 int datlen, hdrlen; 532 533 MGETHDR(m, M_DONTWAIT, MT_DATA); 534 if (m == NULL) { 535 ifp->if_ierrors++; 536 return; 537 } 538 MCLGET(m, M_DONTWAIT); 539 if (!(m->m_flags & M_EXT)) { 540 m_freem(m); 541 ifp->if_ierrors++; 542 return; 543 } 544 545 m->m_pkthdr.rcvif = ifp; 546 547 if (wi_read_data(sc, id, 0, mtod(m, caddr_t), 548 sizeof(struct wi_frame))) { 549 m_freem(m); 550 ifp->if_ierrors++; 551 return; 552 } 553 554 rx_frame = mtod(m, struct wi_frame *); 555 556 if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)) { 557 m_freem(m); 558 ifp->if_ierrors++; 559 return; 560 } 561 562 switch ((letoh16(rx_frame->wi_status) & WI_STAT_MAC_PORT) 563 >> 8) { 564 case 7: 565 switch (letoh16(rx_frame->wi_frame_ctl) & 566 WI_FCTL_FTYPE) { 567 case WI_FTYPE_DATA: 568 hdrlen = WI_DATA_HDRLEN; 569 datlen = letoh16(rx_frame->wi_dat_len); 570 break; 571 case WI_FTYPE_MGMT: 572 hdrlen = WI_MGMT_HDRLEN; 573 datlen = letoh16(rx_frame->wi_dat_len); 574 break; 575 case WI_FTYPE_CTL: 576 hdrlen = WI_CTL_HDRLEN; 577 datlen = 0; 578 break; 579 default: 580 printf(WI_PRT_FMT ": received packet of " 581 "unknown type on port 7\n", WI_PRT_ARG(sc)); 582 m_freem(m); 583 ifp->if_ierrors++; 584 return; 585 } 586 break; 587 case 0: 588 hdrlen = WI_DATA_HDRLEN; 589 datlen = letoh16(rx_frame->wi_dat_len); 590 break; 591 default: 592 printf(WI_PRT_FMT ": received packet on invalid port " 593 "(wi_status=0x%x)\n", WI_PRT_ARG(sc), 594 letoh16(rx_frame->wi_status)); 595 m_freem(m); 596 ifp->if_ierrors++; 597 return; 598 } 599 600 if ((hdrlen + datlen + 2) > MCLBYTES) { 601 m_freem(m); 602 ifp->if_ierrors++; 603 return; 604 } 605 606 if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen, 607 datlen + 2)) { 608 m_freem(m); 609 ifp->if_ierrors++; 610 return; 611 } 612 613 m->m_pkthdr.len = m->m_len = hdrlen + datlen; 614 } else { 615 struct wi_frame rx_frame; 616 617 /* First read in the frame header */ 618 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, 619 sizeof(rx_frame))) { 620 ifp->if_ierrors++; 621 return; 622 } 623 624 /* Drop undecryptable or packets with receive errors here */ 625 if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) { 626 ifp->if_ierrors++; 627 return; 628 } 629 630 /* Stash message type in host byte order for later use */ 631 msg_type = letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE; 632 633 MGETHDR(m, M_DONTWAIT, MT_DATA); 634 if (m == NULL) { 635 ifp->if_ierrors++; 636 return; 637 } 638 MCLGET(m, M_DONTWAIT); 639 if (!(m->m_flags & M_EXT)) { 640 m_freem(m); 641 ifp->if_ierrors++; 642 return; 643 } 644 645 olddata = m->m_data; 646 /* Align the data after the ethernet header */ 647 m->m_data = (caddr_t)ALIGN(m->m_data + 648 sizeof(struct ether_header)) - sizeof(struct ether_header); 649 650 eh = mtod(m, struct ether_header *); 651 maxlen = MCLBYTES - (m->m_data - olddata); 652 m->m_pkthdr.rcvif = ifp; 653 654 if (msg_type == WI_STAT_MGMT && 655 sc->wi_ptype == WI_PORTTYPE_HOSTAP) { 656 657 u_int16_t rxlen = letoh16(rx_frame.wi_dat_len); 658 659 if ((WI_802_11_OFFSET_RAW + rxlen + 2) > maxlen) { 660 printf("%s: oversized mgmt packet received in " 661 "hostap mode (wi_dat_len=%d, " 662 "wi_status=0x%x)\n", sc->sc_dev.dv_xname, 663 rxlen, letoh16(rx_frame.wi_status)); 664 m_freem(m); 665 ifp->if_ierrors++; 666 return; 667 } 668 669 /* Put the whole header in there. */ 670 bcopy(&rx_frame, mtod(m, void *), 671 sizeof(struct wi_frame)); 672 if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW, 673 mtod(m, caddr_t) + WI_802_11_OFFSET_RAW, 674 rxlen + 2)) { 675 m_freem(m); 676 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG) 677 printf("wihap: failed to copy header\n"); 678 ifp->if_ierrors++; 679 return; 680 } 681 682 m->m_pkthdr.len = m->m_len = 683 WI_802_11_OFFSET_RAW + rxlen; 684 685 /* XXX: consider giving packet to bhp? */ 686 687 wihap_mgmt_input(sc, &rx_frame, m); 688 689 return; 690 } 691 692 switch (msg_type) { 693 case WI_STAT_1042: 694 case WI_STAT_TUNNEL: 695 case WI_STAT_WMP_MSG: 696 if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > 697 maxlen) { 698 printf(WI_PRT_FMT ": oversized packet received " 699 "(wi_dat_len=%d, wi_status=0x%x)\n", 700 WI_PRT_ARG(sc), 701 letoh16(rx_frame.wi_dat_len), 702 letoh16(rx_frame.wi_status)); 703 m_freem(m); 704 ifp->if_ierrors++; 705 return; 706 } 707 m->m_pkthdr.len = m->m_len = 708 letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN; 709 710 bcopy((char *)&rx_frame.wi_dst_addr, 711 (char *)&eh->ether_dhost, ETHER_ADDR_LEN); 712 bcopy((char *)&rx_frame.wi_src_addr, 713 (char *)&eh->ether_shost, ETHER_ADDR_LEN); 714 bcopy((char *)&rx_frame.wi_type, 715 (char *)&eh->ether_type, ETHER_TYPE_LEN); 716 717 if (wi_read_data(sc, id, WI_802_11_OFFSET, 718 mtod(m, caddr_t) + sizeof(struct ether_header), 719 m->m_len + 2)) { 720 ifp->if_ierrors++; 721 m_freem(m); 722 return; 723 } 724 break; 725 default: 726 if ((letoh16(rx_frame.wi_dat_len) + 727 sizeof(struct ether_header)) > maxlen) { 728 printf(WI_PRT_FMT ": oversized packet received " 729 "(wi_dat_len=%d, wi_status=0x%x)\n", 730 WI_PRT_ARG(sc), 731 letoh16(rx_frame.wi_dat_len), 732 letoh16(rx_frame.wi_status)); 733 m_freem(m); 734 ifp->if_ierrors++; 735 return; 736 } 737 m->m_pkthdr.len = m->m_len = 738 letoh16(rx_frame.wi_dat_len) + 739 sizeof(struct ether_header); 740 741 if (wi_read_data(sc, id, WI_802_3_OFFSET, 742 mtod(m, caddr_t), m->m_len + 2)) { 743 m_freem(m); 744 ifp->if_ierrors++; 745 return; 746 } 747 break; 748 } 749 750 ifp->if_ipackets++; 751 752 if (sc->wi_use_wep && 753 rx_frame.wi_frame_ctl & WI_FCTL_WEP) { 754 int len; 755 u_int8_t rx_buf[1596]; 756 757 switch (sc->wi_crypto_algorithm) { 758 case WI_CRYPTO_FIRMWARE_WEP: 759 break; 760 case WI_CRYPTO_SOFTWARE_WEP: 761 m_copydata(m, 0, m->m_pkthdr.len, 762 (caddr_t)rx_buf); 763 len = m->m_pkthdr.len - 764 sizeof(struct ether_header); 765 if (wi_do_hostdecrypt(sc, rx_buf + 766 sizeof(struct ether_header), len)) { 767 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG) 768 printf(WI_PRT_FMT ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc)); 769 m_freem(m); 770 ifp->if_ierrors++; 771 return; 772 } 773 len -= IEEE80211_WEP_IVLEN + 774 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN; 775 /* 776 * copy data back to mbufs: 777 * we need to ditch the IV & most LLC/SNAP stuff 778 * (except SNAP type, we're going use that to 779 * overwrite the ethertype in the ether_header) 780 */ 781 m_copyback(m, sizeof(struct ether_header) - 782 WI_ETHERTYPE_LEN, WI_ETHERTYPE_LEN + 783 (len - WI_SNAPHDR_LEN), 784 rx_buf + sizeof(struct ether_header) + 785 IEEE80211_WEP_IVLEN + 786 IEEE80211_WEP_KIDLEN + WI_SNAPHDR_LEN); 787 m_adj(m, -(WI_ETHERTYPE_LEN + 788 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 789 WI_SNAPHDR_LEN)); 790 break; 791 } 792 } 793 794 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) { 795 /* 796 * Give host AP code first crack at data packets. 797 * If it decides to handle it (or drop it), it will 798 * return a non-zero. Otherwise, it is destined for 799 * this host. 800 */ 801 if (wihap_data_input(sc, &rx_frame, m)) 802 return; 803 } 804 } 805 806 #if NBPFILTER > 0 807 /* Handle BPF listeners. */ 808 if (ifp->if_bpf) 809 BPF_MTAP(ifp, m); 810 #endif 811 812 /* Receive packet unless in procframe or monitor mode. */ 813 if (sc->wi_procframe || sc->wi_debug.wi_monitor) 814 m_freem(m); 815 else 816 ether_input_mbuf(ifp, m); 817 818 return; 819 } 820 821 void 822 wi_txeof(sc, status) 823 struct wi_softc *sc; 824 int status; 825 { 826 struct ifnet *ifp; 827 828 ifp = &sc->sc_arpcom.ac_if; 829 830 ifp->if_timer = 0; 831 ifp->if_flags &= ~IFF_OACTIVE; 832 833 if (status & WI_EV_TX_EXC) 834 ifp->if_oerrors++; 835 else 836 ifp->if_opackets++; 837 838 return; 839 } 840 841 void 842 wi_inquire(xsc) 843 void *xsc; 844 { 845 struct wi_softc *sc; 846 struct ifnet *ifp; 847 int s, rv; 848 849 sc = xsc; 850 ifp = &sc->sc_arpcom.ac_if; 851 852 timeout_add(&sc->sc_timo, hz * 60); 853 854 /* Don't do this while we're transmitting */ 855 if (ifp->if_flags & IFF_OACTIVE) 856 return; 857 858 s = splimp(); 859 rv = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0); 860 splx(s); 861 if (rv) 862 printf(WI_PRT_FMT ": wi_cmd failed with %d\n", WI_PRT_ARG(sc), 863 rv); 864 865 return; 866 } 867 868 void 869 wi_update_stats(sc) 870 struct wi_softc *sc; 871 { 872 struct wi_ltv_gen gen; 873 u_int16_t id; 874 struct ifnet *ifp; 875 u_int32_t *ptr; 876 int len, i; 877 u_int16_t t; 878 879 ifp = &sc->sc_arpcom.ac_if; 880 881 id = wi_get_fid(sc, WI_INFO_FID); 882 883 wi_read_data(sc, id, 0, (char *)&gen, 4); 884 885 if (gen.wi_type == htole16(WI_INFO_SCAN_RESULTS)) { 886 sc->wi_scanbuf_len = letoh16(gen.wi_len); 887 wi_read_data(sc, id, 4, (caddr_t)sc->wi_scanbuf, 888 sc->wi_scanbuf_len * 2); 889 return; 890 } else if (gen.wi_type != htole16(WI_INFO_COUNTERS)) 891 return; 892 893 /* Some card versions have a larger stats structure */ 894 len = (letoh16(gen.wi_len) - 1 < sizeof(sc->wi_stats) / 4) ? 895 letoh16(gen.wi_len) - 1 : sizeof(sc->wi_stats) / 4; 896 897 ptr = (u_int32_t *)&sc->wi_stats; 898 899 for (i = 0; i < len; i++) { 900 if (sc->wi_flags & WI_FLAGS_BUS_USB) { 901 wi_read_data(sc, id, 4 + i*2, (char *)&t, 2); 902 t = letoh16(t); 903 } else 904 t = CSR_READ_2(sc, WI_DATA1); 905 #ifdef WI_HERMES_STATS_WAR 906 if (t > 0xF000) 907 t = ~t & 0xFFFF; 908 #endif 909 ptr[i] += t; 910 } 911 912 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries + 913 sc->wi_stats.wi_tx_multi_retries + 914 sc->wi_stats.wi_tx_retry_limit; 915 916 return; 917 } 918 919 STATIC int 920 wi_cmd_io(sc, cmd, val0, val1, val2) 921 struct wi_softc *sc; 922 int cmd; 923 int val0; 924 int val1; 925 int val2; 926 { 927 int i, s = 0; 928 929 /* Wait for the busy bit to clear. */ 930 for (i = 0; i < WI_TIMEOUT; i++) { 931 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) 932 break; 933 DELAY(10); 934 } 935 936 CSR_WRITE_2(sc, WI_PARAM0, val0); 937 CSR_WRITE_2(sc, WI_PARAM1, val1); 938 CSR_WRITE_2(sc, WI_PARAM2, val2); 939 CSR_WRITE_2(sc, WI_COMMAND, cmd); 940 941 for (i = WI_TIMEOUT; i--; DELAY(10)) { 942 /* 943 * Wait for 'command complete' bit to be 944 * set in the event status register. 945 */ 946 s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD; 947 if (s) { 948 /* Ack the event and read result code. */ 949 s = CSR_READ_2(sc, WI_STATUS); 950 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); 951 #ifdef foo 952 if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK)) 953 return(EIO); 954 #endif 955 if (s & WI_STAT_CMD_RESULT) 956 return(EIO); 957 break; 958 } 959 } 960 961 if (i < 0) 962 return(ETIMEDOUT); 963 964 return(0); 965 } 966 967 STATIC void 968 wi_reset(sc) 969 struct wi_softc *sc; 970 { 971 DPRINTF(WID_RESET, ("wi_reset: sc %p\n", sc)); 972 973 /* Symbol firmware cannot be initialized more than once. */ 974 if (sc->sc_firmware_type == WI_SYMBOL && 975 (sc->wi_flags & WI_FLAGS_INITIALIZED)) 976 return; 977 978 if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) 979 printf(WI_PRT_FMT ": init failed\n", WI_PRT_ARG(sc)); 980 else 981 sc->wi_flags |= WI_FLAGS_INITIALIZED; 982 983 wi_intr_enable(sc, 0); 984 wi_intr_ack(sc, 0xffff); 985 986 /* Calibrate timer. */ 987 WI_SETVAL(WI_RID_TICK_TIME, 8); 988 989 return; 990 } 991 992 STATIC void 993 wi_cor_reset(sc) 994 struct wi_softc *sc; 995 { 996 u_int8_t cor_value; 997 998 DPRINTF(WID_RESET, ("wi_cor_reset: sc %p\n", sc)); 999 1000 /* 1001 * Do a soft reset of the card; this is required for Symbol cards. 1002 * This shouldn't hurt other cards but there have been reports 1003 * of the COR reset messing up old Lucent firmware revisions so 1004 * we only soft reset Symbol cards for now. 1005 */ 1006 if (sc->sc_firmware_type == WI_SYMBOL) { 1007 cor_value = bus_space_read_1(sc->wi_ltag, sc->wi_lhandle, 1008 sc->wi_cor_offset); 1009 bus_space_write_1(sc->wi_ltag, sc->wi_lhandle, 1010 sc->wi_cor_offset, (cor_value | WI_COR_SOFT_RESET)); 1011 DELAY(1000); 1012 bus_space_write_1(sc->wi_ltag, sc->wi_lhandle, 1013 sc->wi_cor_offset, (cor_value & ~WI_COR_SOFT_RESET)); 1014 DELAY(1000); 1015 } 1016 1017 return; 1018 } 1019 1020 /* 1021 * Read an LTV record from the NIC. 1022 */ 1023 STATIC int 1024 wi_read_record_io(sc, ltv) 1025 struct wi_softc *sc; 1026 struct wi_ltv_gen *ltv; 1027 { 1028 u_int8_t *ptr; 1029 int len, code; 1030 struct wi_ltv_gen *oltv, p2ltv; 1031 1032 if (sc->sc_firmware_type != WI_LUCENT) { 1033 oltv = ltv; 1034 switch (ltv->wi_type) { 1035 case WI_RID_ENCRYPTION: 1036 p2ltv.wi_type = WI_RID_P2_ENCRYPTION; 1037 p2ltv.wi_len = 2; 1038 ltv = &p2ltv; 1039 break; 1040 case WI_RID_TX_CRYPT_KEY: 1041 if (ltv->wi_val > WI_NLTV_KEYS) 1042 return (EINVAL); 1043 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; 1044 p2ltv.wi_len = 2; 1045 ltv = &p2ltv; 1046 break; 1047 } 1048 } 1049 1050 /* Tell the NIC to enter record read mode. */ 1051 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0)) 1052 return(EIO); 1053 1054 /* Seek to the record. */ 1055 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) 1056 return(EIO); 1057 1058 /* 1059 * Read the length and record type and make sure they 1060 * match what we expect (this verifies that we have enough 1061 * room to hold all of the returned data). 1062 */ 1063 len = CSR_READ_2(sc, WI_DATA1); 1064 if (len > ltv->wi_len) 1065 return(ENOSPC); 1066 code = CSR_READ_2(sc, WI_DATA1); 1067 if (code != ltv->wi_type) 1068 return(EIO); 1069 1070 ltv->wi_len = len; 1071 ltv->wi_type = code; 1072 1073 /* Now read the data. */ 1074 ptr = (u_int8_t *)<v->wi_val; 1075 if (ltv->wi_len > 1) 1076 CSR_READ_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1)*2); 1077 1078 if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS 1079 && ltv->wi_val == sc->wi_ibss_port) { 1080 /* 1081 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS. 1082 * Since Lucent uses port type 1 for BSS *and* IBSS we 1083 * have to rely on wi_ptype to distinguish this for us. 1084 */ 1085 ltv->wi_val = htole16(WI_PORTTYPE_IBSS); 1086 } else if (sc->sc_firmware_type != WI_LUCENT) { 1087 int v; 1088 1089 switch (oltv->wi_type) { 1090 case WI_RID_TX_RATE: 1091 case WI_RID_CUR_TX_RATE: 1092 switch (letoh16(ltv->wi_val)) { 1093 case 1: v = 1; break; 1094 case 2: v = 2; break; 1095 case 3: v = 6; break; 1096 case 4: v = 5; break; 1097 case 7: v = 7; break; 1098 case 8: v = 11; break; 1099 case 15: v = 3; break; 1100 default: v = 0x100 + letoh16(ltv->wi_val); break; 1101 } 1102 oltv->wi_val = htole16(v); 1103 break; 1104 case WI_RID_ENCRYPTION: 1105 oltv->wi_len = 2; 1106 if (ltv->wi_val & htole16(0x01)) 1107 oltv->wi_val = htole16(1); 1108 else 1109 oltv->wi_val = htole16(0); 1110 break; 1111 case WI_RID_TX_CRYPT_KEY: 1112 case WI_RID_CNFAUTHMODE: 1113 oltv->wi_len = 2; 1114 oltv->wi_val = ltv->wi_val; 1115 break; 1116 } 1117 } 1118 1119 return(0); 1120 } 1121 1122 /* 1123 * Same as read, except we inject data instead of reading it. 1124 */ 1125 STATIC int 1126 wi_write_record_io(sc, ltv) 1127 struct wi_softc *sc; 1128 struct wi_ltv_gen *ltv; 1129 { 1130 u_int8_t *ptr; 1131 u_int16_t val = 0; 1132 int i; 1133 struct wi_ltv_gen p2ltv; 1134 1135 if (ltv->wi_type == WI_RID_PORTTYPE && 1136 letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) { 1137 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */ 1138 p2ltv.wi_type = WI_RID_PORTTYPE; 1139 p2ltv.wi_len = 2; 1140 p2ltv.wi_val = sc->wi_ibss_port; 1141 ltv = &p2ltv; 1142 } else if (sc->sc_firmware_type != WI_LUCENT) { 1143 int v; 1144 1145 switch (ltv->wi_type) { 1146 case WI_RID_TX_RATE: 1147 p2ltv.wi_type = WI_RID_TX_RATE; 1148 p2ltv.wi_len = 2; 1149 switch (letoh16(ltv->wi_val)) { 1150 case 1: v = 1; break; 1151 case 2: v = 2; break; 1152 case 3: v = 15; break; 1153 case 5: v = 4; break; 1154 case 6: v = 3; break; 1155 case 7: v = 7; break; 1156 case 11: v = 8; break; 1157 default: return EINVAL; 1158 } 1159 p2ltv.wi_val = htole16(v); 1160 ltv = &p2ltv; 1161 break; 1162 case WI_RID_ENCRYPTION: 1163 p2ltv.wi_type = WI_RID_P2_ENCRYPTION; 1164 p2ltv.wi_len = 2; 1165 if (ltv->wi_val & htole16(0x01)) { 1166 val = PRIVACY_INVOKED; 1167 /* 1168 * If using shared key WEP we must set the 1169 * EXCLUDE_UNENCRYPTED bit. Symbol cards 1170 * need this bit set even when not using 1171 * shared key. We can't just test for 1172 * IEEE80211_AUTH_SHARED since Symbol cards 1173 * have 2 shared key modes. 1174 */ 1175 if (sc->wi_authtype != IEEE80211_AUTH_OPEN || 1176 sc->sc_firmware_type == WI_SYMBOL) 1177 val |= EXCLUDE_UNENCRYPTED; 1178 1179 switch (sc->wi_crypto_algorithm) { 1180 case WI_CRYPTO_FIRMWARE_WEP: 1181 /* 1182 * TX encryption is broken in 1183 * Host AP mode. 1184 */ 1185 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) 1186 val |= HOST_ENCRYPT; 1187 break; 1188 case WI_CRYPTO_SOFTWARE_WEP: 1189 val |= HOST_ENCRYPT|HOST_DECRYPT; 1190 break; 1191 } 1192 p2ltv.wi_val = htole16(val); 1193 } else 1194 p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT); 1195 ltv = &p2ltv; 1196 break; 1197 case WI_RID_TX_CRYPT_KEY: 1198 if (ltv->wi_val > WI_NLTV_KEYS) 1199 return (EINVAL); 1200 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; 1201 p2ltv.wi_len = 2; 1202 p2ltv.wi_val = ltv->wi_val; 1203 ltv = &p2ltv; 1204 break; 1205 case WI_RID_DEFLT_CRYPT_KEYS: { 1206 int error; 1207 int keylen; 1208 struct wi_ltv_str ws; 1209 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv; 1210 keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen; 1211 1212 for (i = 0; i < 4; i++) { 1213 bzero(&ws, sizeof(ws)); 1214 ws.wi_len = (keylen > 5) ? 8 : 4; 1215 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i; 1216 bcopy(&wk->wi_keys[i].wi_keydat, 1217 ws.wi_str, keylen); 1218 error = wi_write_record(sc, 1219 (struct wi_ltv_gen *)&ws); 1220 if (error) 1221 return (error); 1222 } 1223 } 1224 return (0); 1225 } 1226 } 1227 1228 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) 1229 return(EIO); 1230 1231 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len); 1232 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type); 1233 1234 ptr = (u_int8_t *)<v->wi_val; 1235 if (ltv->wi_len > 1) 1236 CSR_WRITE_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1) *2); 1237 1238 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0)) 1239 return(EIO); 1240 1241 return(0); 1242 } 1243 1244 STATIC int 1245 wi_seek(sc, id, off, chan) 1246 struct wi_softc *sc; 1247 int id, off, chan; 1248 { 1249 int i; 1250 int selreg, offreg; 1251 1252 switch (chan) { 1253 case WI_BAP0: 1254 selreg = WI_SEL0; 1255 offreg = WI_OFF0; 1256 break; 1257 case WI_BAP1: 1258 selreg = WI_SEL1; 1259 offreg = WI_OFF1; 1260 break; 1261 default: 1262 printf(WI_PRT_FMT ": invalid data path: %x\n", WI_PRT_ARG(sc), 1263 chan); 1264 return(EIO); 1265 } 1266 1267 CSR_WRITE_2(sc, selreg, id); 1268 CSR_WRITE_2(sc, offreg, off); 1269 1270 for (i = WI_TIMEOUT; i--; DELAY(10)) 1271 if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR))) 1272 break; 1273 1274 if (i < 0) 1275 return(ETIMEDOUT); 1276 1277 return(0); 1278 } 1279 1280 STATIC int 1281 wi_read_data_io(sc, id, off, buf, len) 1282 struct wi_softc *sc; 1283 int id, off; 1284 caddr_t buf; 1285 int len; 1286 { 1287 u_int8_t *ptr; 1288 1289 if (wi_seek(sc, id, off, WI_BAP1)) 1290 return(EIO); 1291 1292 ptr = (u_int8_t *)buf; 1293 CSR_READ_RAW_2(sc, WI_DATA1, ptr, len); 1294 1295 return(0); 1296 } 1297 1298 /* 1299 * According to the comments in the HCF Light code, there is a bug in 1300 * the Hermes (or possibly in certain Hermes firmware revisions) where 1301 * the chip's internal autoincrement counter gets thrown off during 1302 * data writes: the autoincrement is missed, causing one data word to 1303 * be overwritten and subsequent words to be written to the wrong memory 1304 * locations. The end result is that we could end up transmitting bogus 1305 * frames without realizing it. The workaround for this is to write a 1306 * couple of extra guard words after the end of the transfer, then 1307 * attempt to read then back. If we fail to locate the guard words where 1308 * we expect them, we preform the transfer over again. 1309 */ 1310 STATIC int 1311 wi_write_data_io(sc, id, off, buf, len) 1312 struct wi_softc *sc; 1313 int id, off; 1314 caddr_t buf; 1315 int len; 1316 { 1317 u_int8_t *ptr; 1318 1319 #ifdef WI_HERMES_AUTOINC_WAR 1320 again: 1321 #endif 1322 1323 if (wi_seek(sc, id, off, WI_BAP0)) 1324 return(EIO); 1325 1326 ptr = (u_int8_t *)buf; 1327 CSR_WRITE_RAW_2(sc, WI_DATA0, ptr, len); 1328 1329 #ifdef WI_HERMES_AUTOINC_WAR 1330 CSR_WRITE_2(sc, WI_DATA0, 0x1234); 1331 CSR_WRITE_2(sc, WI_DATA0, 0x5678); 1332 1333 if (wi_seek(sc, id, off + len, WI_BAP0)) 1334 return(EIO); 1335 1336 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 || 1337 CSR_READ_2(sc, WI_DATA0) != 0x5678) 1338 goto again; 1339 #endif 1340 1341 return(0); 1342 } 1343 1344 /* 1345 * Allocate a region of memory inside the NIC and zero 1346 * it out. 1347 */ 1348 STATIC int 1349 wi_alloc_nicmem_io(sc, len, id) 1350 struct wi_softc *sc; 1351 int len; 1352 int *id; 1353 { 1354 int i; 1355 1356 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) { 1357 printf(WI_PRT_FMT ": failed to allocate %d bytes on NIC\n", 1358 WI_PRT_ARG(sc), len); 1359 return(ENOMEM); 1360 } 1361 1362 for (i = WI_TIMEOUT; i--; DELAY(10)) { 1363 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) 1364 break; 1365 } 1366 1367 if (i < 0) 1368 return(ETIMEDOUT); 1369 1370 *id = CSR_READ_2(sc, WI_ALLOC_FID); 1371 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); 1372 1373 if (wi_seek(sc, *id, 0, WI_BAP0)) 1374 return(EIO); 1375 1376 for (i = 0; i < len / 2; i++) 1377 CSR_WRITE_2(sc, WI_DATA0, 0); 1378 1379 return(0); 1380 } 1381 1382 STATIC void 1383 wi_setmulti(sc) 1384 struct wi_softc *sc; 1385 { 1386 struct ifnet *ifp; 1387 int i = 0; 1388 struct wi_ltv_mcast mcast; 1389 struct ether_multistep step; 1390 struct ether_multi *enm; 1391 1392 ifp = &sc->sc_arpcom.ac_if; 1393 1394 bzero((char *)&mcast, sizeof(mcast)); 1395 1396 mcast.wi_type = WI_RID_MCAST_LIST; 1397 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1; 1398 1399 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 1400 wi_write_record(sc, (struct wi_ltv_gen *)&mcast); 1401 return; 1402 } 1403 1404 ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm); 1405 while (enm != NULL) { 1406 if (i >= 16) { 1407 bzero((char *)&mcast, sizeof(mcast)); 1408 break; 1409 } 1410 1411 /* Punt on ranges. */ 1412 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 1413 sizeof(enm->enm_addrlo)) != 0) 1414 break; 1415 bcopy(enm->enm_addrlo, (char *)&mcast.wi_mcast[i], 1416 ETHER_ADDR_LEN); 1417 i++; 1418 ETHER_NEXT_MULTI(step, enm); 1419 } 1420 1421 mcast.wi_len = (i * 3) + 1; 1422 wi_write_record(sc, (struct wi_ltv_gen *)&mcast); 1423 1424 return; 1425 } 1426 1427 STATIC int 1428 wi_setdef(sc, wreq) 1429 struct wi_softc *sc; 1430 struct wi_req *wreq; 1431 { 1432 struct ifnet *ifp; 1433 int error = 0; 1434 1435 ifp = &sc->sc_arpcom.ac_if; 1436 1437 switch(wreq->wi_type) { 1438 case WI_RID_MAC_NODE: 1439 bcopy((char *)&wreq->wi_val, LLADDR(ifp->if_sadl), 1440 ETHER_ADDR_LEN); 1441 bcopy((char *)&wreq->wi_val, (char *)&sc->sc_arpcom.ac_enaddr, 1442 ETHER_ADDR_LEN); 1443 break; 1444 case WI_RID_PORTTYPE: 1445 error = wi_sync_media(sc, letoh16(wreq->wi_val[0]), 1446 sc->wi_tx_rate); 1447 break; 1448 case WI_RID_TX_RATE: 1449 error = wi_sync_media(sc, sc->wi_ptype, 1450 letoh16(wreq->wi_val[0])); 1451 break; 1452 case WI_RID_MAX_DATALEN: 1453 sc->wi_max_data_len = letoh16(wreq->wi_val[0]); 1454 break; 1455 case WI_RID_RTS_THRESH: 1456 sc->wi_rts_thresh = letoh16(wreq->wi_val[0]); 1457 break; 1458 case WI_RID_SYSTEM_SCALE: 1459 sc->wi_ap_density = letoh16(wreq->wi_val[0]); 1460 break; 1461 case WI_RID_CREATE_IBSS: 1462 sc->wi_create_ibss = letoh16(wreq->wi_val[0]); 1463 error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate); 1464 break; 1465 case WI_RID_OWN_CHNL: 1466 sc->wi_channel = letoh16(wreq->wi_val[0]); 1467 break; 1468 case WI_RID_NODENAME: 1469 error = wi_set_ssid(&sc->wi_node_name, 1470 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0])); 1471 break; 1472 case WI_RID_DESIRED_SSID: 1473 error = wi_set_ssid(&sc->wi_net_name, 1474 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0])); 1475 break; 1476 case WI_RID_OWN_SSID: 1477 error = wi_set_ssid(&sc->wi_ibss_name, 1478 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0])); 1479 break; 1480 case WI_RID_PM_ENABLED: 1481 sc->wi_pm_enabled = letoh16(wreq->wi_val[0]); 1482 break; 1483 case WI_RID_MICROWAVE_OVEN: 1484 sc->wi_mor_enabled = letoh16(wreq->wi_val[0]); 1485 break; 1486 case WI_RID_MAX_SLEEP: 1487 sc->wi_max_sleep = letoh16(wreq->wi_val[0]); 1488 break; 1489 case WI_RID_CNFAUTHMODE: 1490 sc->wi_authtype = letoh16(wreq->wi_val[0]); 1491 break; 1492 case WI_RID_ROAMING_MODE: 1493 sc->wi_roaming = letoh16(wreq->wi_val[0]); 1494 break; 1495 case WI_RID_SYMBOL_DIVERSITY: 1496 sc->wi_diversity = letoh16(wreq->wi_val[0]); 1497 break; 1498 case WI_RID_ENCRYPTION: 1499 sc->wi_use_wep = letoh16(wreq->wi_val[0]); 1500 break; 1501 case WI_RID_TX_CRYPT_KEY: 1502 sc->wi_tx_key = letoh16(wreq->wi_val[0]); 1503 break; 1504 case WI_RID_DEFLT_CRYPT_KEYS: 1505 bcopy((char *)wreq, (char *)&sc->wi_keys, 1506 sizeof(struct wi_ltv_keys)); 1507 break; 1508 case WI_FRID_CRYPTO_ALG: 1509 switch (letoh16(wreq->wi_val[0])) { 1510 case WI_CRYPTO_FIRMWARE_WEP: 1511 sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP; 1512 break; 1513 case WI_CRYPTO_SOFTWARE_WEP: 1514 sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP; 1515 break; 1516 default: 1517 printf(WI_PRT_FMT ": unsupported crypto algorithm %d\n", 1518 WI_PRT_ARG(sc), letoh16(wreq->wi_val[0])); 1519 error = EINVAL; 1520 } 1521 break; 1522 default: 1523 error = EINVAL; 1524 break; 1525 } 1526 1527 return (error); 1528 } 1529 1530 STATIC int 1531 wi_ioctl(ifp, command, data) 1532 struct ifnet *ifp; 1533 u_long command; 1534 caddr_t data; 1535 { 1536 int s, error = 0; 1537 struct wi_softc *sc; 1538 struct wi_req wreq; 1539 struct ifreq *ifr; 1540 struct proc *p = curproc; 1541 struct ifaddr *ifa = (struct ifaddr *)data; 1542 struct ieee80211_nwid nwid; 1543 1544 s = splimp(); 1545 1546 sc = ifp->if_softc; 1547 ifr = (struct ifreq *)data; 1548 1549 if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) { 1550 splx(s); 1551 return(ENODEV); 1552 } 1553 1554 DPRINTF (WID_IOCTL, ("wi_ioctl: command %lu data %p\n", 1555 command, data)); 1556 1557 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) { 1558 splx(s); 1559 return error; 1560 } 1561 1562 switch(command) { 1563 case SIOCSWAVELAN: 1564 case SIOCSPRISM2DEBUG: 1565 case SIOCS80211NWID: 1566 case SIOCS80211NWKEY: 1567 case SIOCS80211POWER: 1568 error = suser(p, 0); 1569 if (error) { 1570 splx(s); 1571 return (error); 1572 } 1573 default: 1574 break; 1575 } 1576 1577 switch(command) { 1578 case SIOCSIFADDR: 1579 ifp->if_flags |= IFF_UP; 1580 switch (ifa->ifa_addr->sa_family) { 1581 #ifdef INET 1582 case AF_INET: 1583 wi_init(sc); 1584 arp_ifinit(&sc->sc_arpcom, ifa); 1585 break; 1586 #endif /* INET */ 1587 default: 1588 wi_init(sc); 1589 break; 1590 } 1591 break; 1592 1593 case SIOCSIFMTU: 1594 if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) { 1595 error = EINVAL; 1596 } else if (ifp->if_mtu != ifr->ifr_mtu) { 1597 ifp->if_mtu = ifr->ifr_mtu; 1598 } 1599 break; 1600 1601 case SIOCSIFFLAGS: 1602 if (ifp->if_flags & IFF_UP) { 1603 if (ifp->if_flags & IFF_RUNNING && 1604 ifp->if_flags & IFF_PROMISC && 1605 !(sc->wi_if_flags & IFF_PROMISC)) { 1606 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP) 1607 WI_SETVAL(WI_RID_PROMISC, 1); 1608 } else if (ifp->if_flags & IFF_RUNNING && 1609 !(ifp->if_flags & IFF_PROMISC) && 1610 sc->wi_if_flags & IFF_PROMISC) { 1611 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP) 1612 WI_SETVAL(WI_RID_PROMISC, 0); 1613 } else 1614 wi_init(sc); 1615 } else if (ifp->if_flags & IFF_RUNNING) 1616 wi_stop(sc); 1617 sc->wi_if_flags = ifp->if_flags; 1618 error = 0; 1619 break; 1620 case SIOCADDMULTI: 1621 case SIOCDELMULTI: 1622 /* Update our multicast list. */ 1623 error = (command == SIOCADDMULTI) ? 1624 ether_addmulti(ifr, &sc->sc_arpcom) : 1625 ether_delmulti(ifr, &sc->sc_arpcom); 1626 if (error == ENETRESET) { 1627 /* 1628 * Multicast list has changed; set the hardware filter 1629 * accordingly. 1630 */ 1631 wi_setmulti(sc); 1632 error = 0; 1633 } 1634 break; 1635 case SIOCSIFMEDIA: 1636 case SIOCGIFMEDIA: 1637 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command); 1638 break; 1639 case SIOCGWAVELAN: 1640 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1641 if (error) 1642 break; 1643 if (wreq.wi_len > WI_MAX_DATALEN) { 1644 error = EINVAL; 1645 break; 1646 } 1647 switch (wreq.wi_type) { 1648 case WI_RID_IFACE_STATS: 1649 /* XXX native byte order */ 1650 bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val, 1651 sizeof(sc->wi_stats)); 1652 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1; 1653 break; 1654 case WI_RID_DEFLT_CRYPT_KEYS: 1655 /* For non-root user, return all-zeroes keys */ 1656 if (suser(p, 0)) 1657 bzero((char *)&wreq, 1658 sizeof(struct wi_ltv_keys)); 1659 else 1660 bcopy((char *)&sc->wi_keys, (char *)&wreq, 1661 sizeof(struct wi_ltv_keys)); 1662 break; 1663 case WI_RID_PROCFRAME: 1664 wreq.wi_len = 2; 1665 wreq.wi_val[0] = htole16(sc->wi_procframe); 1666 break; 1667 case WI_RID_PRISM2: 1668 wreq.wi_len = 2; 1669 wreq.wi_val[0] = htole16(sc->sc_firmware_type == 1670 WI_LUCENT ? 0 : 1); 1671 break; 1672 case WI_FRID_CRYPTO_ALG: 1673 wreq.wi_val[0] = 1674 htole16((u_int16_t)sc->wi_crypto_algorithm); 1675 wreq.wi_len = 1; 1676 break; 1677 case WI_RID_SCAN_RES: 1678 if (sc->sc_firmware_type == WI_LUCENT) { 1679 memcpy((char *)wreq.wi_val, 1680 (char *)sc->wi_scanbuf, 1681 sc->wi_scanbuf_len * 2); 1682 wreq.wi_len = sc->wi_scanbuf_len; 1683 break; 1684 } 1685 /* FALLTHROUGH */ 1686 default: 1687 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) { 1688 error = EINVAL; 1689 } 1690 break; 1691 } 1692 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 1693 break; 1694 case SIOCSWAVELAN: 1695 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1696 if (error) 1697 break; 1698 error = EINVAL; 1699 if (wreq.wi_len > WI_MAX_DATALEN) 1700 break; 1701 switch (wreq.wi_type) { 1702 case WI_RID_IFACE_STATS: 1703 break; 1704 case WI_RID_MGMT_XMIT: 1705 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val, 1706 wreq.wi_len); 1707 break; 1708 case WI_RID_PROCFRAME: 1709 sc->wi_procframe = letoh16(wreq.wi_val[0]); 1710 error = 0; 1711 break; 1712 case WI_RID_SCAN_REQ: 1713 error = 0; 1714 if (sc->sc_firmware_type == WI_LUCENT) 1715 wi_cmd(sc, WI_CMD_INQUIRE, 1716 WI_INFO_SCAN_RESULTS, 0, 0); 1717 else 1718 error = wi_write_record(sc, 1719 (struct wi_ltv_gen *)&wreq); 1720 break; 1721 case WI_FRID_CRYPTO_ALG: 1722 if (sc->sc_firmware_type != WI_LUCENT) { 1723 error = wi_setdef(sc, &wreq); 1724 if (!error && (ifp->if_flags & IFF_UP)) 1725 wi_init(sc); 1726 } 1727 break; 1728 case WI_RID_SYMBOL_DIVERSITY: 1729 case WI_RID_ROAMING_MODE: 1730 case WI_RID_CREATE_IBSS: 1731 case WI_RID_MICROWAVE_OVEN: 1732 case WI_RID_OWN_SSID: 1733 /* 1734 * Check for features that may not be supported 1735 * (must be just before default case). 1736 */ 1737 if ((wreq.wi_type == WI_RID_SYMBOL_DIVERSITY && 1738 !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)) || 1739 (wreq.wi_type == WI_RID_ROAMING_MODE && 1740 !(sc->wi_flags & WI_FLAGS_HAS_ROAMING)) || 1741 (wreq.wi_type == WI_RID_CREATE_IBSS && 1742 !(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) || 1743 (wreq.wi_type == WI_RID_MICROWAVE_OVEN && 1744 !(sc->wi_flags & WI_FLAGS_HAS_MOR)) || 1745 (wreq.wi_type == WI_RID_OWN_SSID && 1746 wreq.wi_len != 0)) 1747 break; 1748 /* FALLTHROUGH */ 1749 default: 1750 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); 1751 if (!error) 1752 error = wi_setdef(sc, &wreq); 1753 if (!error && (ifp->if_flags & IFF_UP)) 1754 wi_init(sc); 1755 } 1756 break; 1757 case SIOCGPRISM2DEBUG: 1758 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1759 if (error) 1760 break; 1761 if (!(ifp->if_flags & IFF_RUNNING) || 1762 sc->sc_firmware_type == WI_LUCENT) { 1763 error = EIO; 1764 break; 1765 } 1766 error = wi_get_debug(sc, &wreq); 1767 if (error == 0) 1768 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 1769 break; 1770 case SIOCSPRISM2DEBUG: 1771 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1772 if (error) 1773 break; 1774 error = wi_set_debug(sc, &wreq); 1775 break; 1776 case SIOCG80211NWID: 1777 if ((ifp->if_flags & IFF_UP) && sc->wi_net_name.i_len > 0) { 1778 /* Return the desired ID */ 1779 error = copyout(&sc->wi_net_name, ifr->ifr_data, 1780 sizeof(sc->wi_net_name)); 1781 } else { 1782 wreq.wi_type = WI_RID_CURRENT_SSID; 1783 wreq.wi_len = WI_MAX_DATALEN; 1784 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) || 1785 letoh16(wreq.wi_val[0]) > IEEE80211_NWID_LEN) 1786 error = EINVAL; 1787 else { 1788 wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1], 1789 letoh16(wreq.wi_val[0])); 1790 error = copyout(&nwid, ifr->ifr_data, 1791 sizeof(nwid)); 1792 } 1793 } 1794 break; 1795 case SIOCS80211NWID: 1796 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid)); 1797 if (error) 1798 break; 1799 if (nwid.i_len > IEEE80211_NWID_LEN) { 1800 error = EINVAL; 1801 break; 1802 } 1803 if (sc->wi_net_name.i_len == nwid.i_len && 1804 memcmp(sc->wi_net_name.i_nwid, nwid.i_nwid, nwid.i_len) == 0) 1805 break; 1806 wi_set_ssid(&sc->wi_net_name, nwid.i_nwid, nwid.i_len); 1807 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name); 1808 if (ifp->if_flags & IFF_UP) 1809 /* Reinitialize WaveLAN. */ 1810 wi_init(sc); 1811 break; 1812 case SIOCS80211NWKEY: 1813 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data); 1814 break; 1815 case SIOCG80211NWKEY: 1816 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data); 1817 break; 1818 case SIOCS80211POWER: 1819 error = wi_set_pm(sc, (struct ieee80211_power *)data); 1820 break; 1821 case SIOCG80211POWER: 1822 error = wi_get_pm(sc, (struct ieee80211_power *)data); 1823 break; 1824 case SIOCHOSTAP_ADD: 1825 case SIOCHOSTAP_DEL: 1826 case SIOCHOSTAP_GET: 1827 case SIOCHOSTAP_GETALL: 1828 case SIOCHOSTAP_GFLAGS: 1829 case SIOCHOSTAP_SFLAGS: 1830 /* Send all Host AP specific ioctl's to Host AP code. */ 1831 error = wihap_ioctl(sc, command, data); 1832 break; 1833 default: 1834 error = EINVAL; 1835 break; 1836 } 1837 1838 splx(s); 1839 return(error); 1840 } 1841 1842 STATIC void 1843 wi_init_io(sc) 1844 struct wi_softc *sc; 1845 { 1846 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 1847 int s; 1848 struct wi_ltv_macaddr mac; 1849 int id = 0; 1850 1851 if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) 1852 return; 1853 1854 DPRINTF(WID_INIT, ("wi_init: sc %p\n", sc)); 1855 1856 s = splimp(); 1857 1858 if (ifp->if_flags & IFF_RUNNING) 1859 wi_stop(sc); 1860 1861 wi_reset(sc); 1862 1863 /* Program max data length. */ 1864 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len); 1865 1866 /* Set the port type. */ 1867 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype); 1868 1869 /* Enable/disable IBSS creation. */ 1870 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss); 1871 1872 /* Program the RTS/CTS threshold. */ 1873 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh); 1874 1875 /* Program the TX rate */ 1876 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate); 1877 1878 /* Access point density */ 1879 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density); 1880 1881 /* Power Management Enabled */ 1882 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled); 1883 1884 /* Power Management Max Sleep */ 1885 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep); 1886 1887 /* Set Roaming Mode unless this is a Symbol card. */ 1888 if (sc->wi_flags & WI_FLAGS_HAS_ROAMING) 1889 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming); 1890 1891 /* Set Antenna Diversity if this is a Symbol card. */ 1892 if (sc->wi_flags & WI_FLAGS_HAS_DIVERSITY) 1893 WI_SETVAL(WI_RID_SYMBOL_DIVERSITY, sc->wi_diversity); 1894 1895 /* Specify the network name */ 1896 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name); 1897 1898 /* Specify the IBSS name */ 1899 if (sc->wi_net_name.i_len != 0 && (sc->wi_ptype == WI_PORTTYPE_HOSTAP || 1900 (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS))) 1901 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_net_name); 1902 else 1903 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name); 1904 1905 /* Specify the frequency to use */ 1906 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel); 1907 1908 /* Program the nodename. */ 1909 WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name); 1910 1911 /* Set our MAC address. */ 1912 mac.wi_len = 4; 1913 mac.wi_type = WI_RID_MAC_NODE; 1914 bcopy((char *)&sc->sc_arpcom.ac_enaddr, 1915 (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN); 1916 wi_write_record(sc, (struct wi_ltv_gen *)&mac); 1917 1918 /* 1919 * Initialize promisc mode. 1920 * Being in the Host-AP mode causes 1921 * great deal of pain if promisc mode is set. 1922 * Therefore we avoid confusing the firmware 1923 * and always reset promisc mode in Host-AP regime, 1924 * it shows us all the packets anyway. 1925 */ 1926 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP && ifp->if_flags & IFF_PROMISC) 1927 WI_SETVAL(WI_RID_PROMISC, 1); 1928 else 1929 WI_SETVAL(WI_RID_PROMISC, 0); 1930 1931 /* Configure WEP. */ 1932 if (sc->wi_flags & WI_FLAGS_HAS_WEP) { 1933 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep); 1934 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key); 1935 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1; 1936 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS; 1937 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys); 1938 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) { 1939 /* 1940 * HWB3163 EVAL-CARD Firmware version less than 0.8.2. 1941 * 1942 * If promiscuous mode is disabled, the Prism2 chip 1943 * does not work with WEP . 1944 * I'm currently investigating the details of this. 1945 * (ichiro@netbsd.org) 1946 */ 1947 if (sc->sc_firmware_type == WI_INTERSIL && 1948 sc->sc_sta_firmware_ver < 802 ) { 1949 /* firm ver < 0.8.2 */ 1950 WI_SETVAL(WI_RID_PROMISC, 1); 1951 } 1952 WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype); 1953 } 1954 } 1955 1956 /* Set multicast filter. */ 1957 wi_setmulti(sc); 1958 1959 /* Enable desired port */ 1960 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0); 1961 1962 if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id)) 1963 printf(WI_PRT_FMT ": tx buffer allocation failed\n", 1964 WI_PRT_ARG(sc)); 1965 sc->wi_tx_data_id = id; 1966 1967 if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id)) 1968 printf(WI_PRT_FMT ": mgmt. buffer allocation failed\n", 1969 WI_PRT_ARG(sc)); 1970 sc->wi_tx_mgmt_id = id; 1971 1972 /* enable interrupts */ 1973 wi_intr_enable(sc, WI_INTRS); 1974 1975 wihap_init(sc); 1976 1977 splx(s); 1978 1979 ifp->if_flags |= IFF_RUNNING; 1980 ifp->if_flags &= ~IFF_OACTIVE; 1981 1982 timeout_add(&sc->sc_timo, hz * 60); 1983 1984 return; 1985 } 1986 1987 static const u_int32_t crc32tab[] = { 1988 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 1989 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 1990 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 1991 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 1992 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 1993 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 1994 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 1995 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 1996 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 1997 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 1998 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 1999 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 2000 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 2001 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 2002 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 2003 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 2004 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 2005 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 2006 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 2007 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 2008 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 2009 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 2010 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 2011 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 2012 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 2013 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 2014 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 2015 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 2016 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 2017 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 2018 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 2019 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 2020 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 2021 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 2022 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 2023 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 2024 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 2025 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 2026 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 2027 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 2028 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 2029 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 2030 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 2031 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 2032 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 2033 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 2034 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 2035 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 2036 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 2037 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 2038 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 2039 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 2040 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 2041 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 2042 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 2043 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 2044 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 2045 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 2046 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 2047 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 2048 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 2049 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 2050 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 2051 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL 2052 }; 2053 2054 STATIC void 2055 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len) 2056 { 2057 u_int32_t i, crc, klen; 2058 u_int8_t key[RC4KEYLEN]; 2059 u_int8_t *dat; 2060 struct rc4_ctx ctx; 2061 2062 if (!sc->wi_icv_flag) { 2063 sc->wi_icv = arc4random(); 2064 sc->wi_icv_flag++; 2065 } else 2066 sc->wi_icv++; 2067 /* 2068 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir: 2069 * (B, 255, N) with 3 <= B < 8 2070 */ 2071 if (sc->wi_icv >= 0x03ff00 && 2072 (sc->wi_icv & 0xf8ff00) == 0x00ff00) 2073 sc->wi_icv += 0x000100; 2074 2075 /* prepend 24bit IV to tx key, byte order does not matter */ 2076 bzero(key, sizeof(key)); 2077 key[0] = sc->wi_icv >> 16; 2078 key[1] = sc->wi_icv >> 8; 2079 key[2] = sc->wi_icv; 2080 2081 klen = sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen; 2082 bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat, 2083 (char *)key + IEEE80211_WEP_IVLEN, klen); 2084 klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2; 2085 2086 /* rc4 keysetup */ 2087 rc4_keysetup(&ctx, key, klen); 2088 2089 /* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */ 2090 dat = buf; 2091 dat[0] = key[0]; 2092 dat[1] = key[1]; 2093 dat[2] = key[2]; 2094 dat[3] = sc->wi_tx_key << 6; /* pad and keyid */ 2095 dat += 4; 2096 2097 /* compute crc32 over data and encrypt */ 2098 crc = ~0; 2099 for (i = 0; i < len; i++) 2100 crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8); 2101 crc = ~crc; 2102 rc4_crypt(&ctx, dat, dat, len); 2103 dat += len; 2104 2105 /* append little-endian crc32 and encrypt */ 2106 dat[0] = crc; 2107 dat[1] = crc >> 8; 2108 dat[2] = crc >> 16; 2109 dat[3] = crc >> 24; 2110 rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN); 2111 } 2112 2113 STATIC int 2114 wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len) 2115 { 2116 u_int32_t i, crc, klen, kid; 2117 u_int8_t key[RC4KEYLEN]; 2118 u_int8_t *dat; 2119 struct rc4_ctx ctx; 2120 2121 if (len < IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 2122 IEEE80211_WEP_CRCLEN) 2123 return -1; 2124 len -= (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 2125 IEEE80211_WEP_CRCLEN); 2126 2127 dat = buf; 2128 2129 bzero(key, sizeof(key)); 2130 key[0] = dat[0]; 2131 key[1] = dat[1]; 2132 key[2] = dat[2]; 2133 kid = (dat[3] >> 6) % 4; 2134 dat += 4; 2135 2136 klen = sc->wi_keys.wi_keys[kid].wi_keylen; 2137 bcopy((char *)&sc->wi_keys.wi_keys[kid].wi_keydat, 2138 (char *)key + IEEE80211_WEP_IVLEN, klen); 2139 klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2; 2140 2141 /* rc4 keysetup */ 2142 rc4_keysetup(&ctx, key, klen); 2143 2144 /* decrypt and compute crc32 over data */ 2145 rc4_crypt(&ctx, dat, dat, len); 2146 crc = ~0; 2147 for (i = 0; i < len; i++) 2148 crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8); 2149 crc = ~crc; 2150 dat += len; 2151 2152 /* decrypt little-endian crc32 and verify */ 2153 rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN); 2154 2155 if ((dat[0] != crc) && (dat[1] != crc >> 8) && 2156 (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) { 2157 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG) 2158 printf(WI_PRT_FMT ": wi_do_hostdecrypt: iv mismatch: " 2159 "0x%02x%02x%02x%02x vs. 0x%x\n", WI_PRT_ARG(sc), 2160 dat[3], dat[2], dat[1], dat[0], crc); 2161 return -1; 2162 } 2163 2164 return 0; 2165 } 2166 2167 void 2168 wi_start(ifp) 2169 struct ifnet *ifp; 2170 { 2171 struct wi_softc *sc; 2172 struct mbuf *m0; 2173 struct wi_frame tx_frame; 2174 struct ether_header *eh; 2175 int id; 2176 2177 sc = ifp->if_softc; 2178 2179 DPRINTF(WID_START, ("wi_start: ifp %p sc %p\n", ifp, sc)); 2180 2181 if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) 2182 return; 2183 2184 if (ifp->if_flags & IFF_OACTIVE) 2185 return; 2186 2187 nextpkt: 2188 IFQ_DEQUEUE(&ifp->if_snd, m0); 2189 if (m0 == NULL) 2190 return; 2191 2192 bzero((char *)&tx_frame, sizeof(tx_frame)); 2193 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA); 2194 id = sc->wi_tx_data_id; 2195 eh = mtod(m0, struct ether_header *); 2196 2197 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) { 2198 if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost, 2199 &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC)) { 2200 if (ifp->if_flags & IFF_DEBUG) 2201 printf(WI_PRT_FMT 2202 ": wi_start: dropping unassoc dst %s\n", 2203 WI_PRT_ARG(sc), 2204 ether_sprintf(eh->ether_dhost)); 2205 m_freem(m0); 2206 goto nextpkt; 2207 } 2208 } 2209 2210 /* 2211 * Use RFC1042 encoding for IP and ARP datagrams, 2212 * 802.3 for anything else. 2213 */ 2214 if (eh->ether_type == htons(ETHERTYPE_IP) || 2215 eh->ether_type == htons(ETHERTYPE_ARP) || 2216 eh->ether_type == htons(ETHERTYPE_REVARP) || 2217 eh->ether_type == htons(ETHERTYPE_IPV6)) { 2218 bcopy((char *)&eh->ether_dhost, 2219 (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN); 2220 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) { 2221 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */ 2222 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS); 2223 if (sc->wi_use_wep) 2224 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP); 2225 bcopy((char *)&sc->sc_arpcom.ac_enaddr, 2226 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN); 2227 bcopy((char *)&eh->ether_shost, 2228 (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN); 2229 } else 2230 bcopy((char *)&eh->ether_shost, 2231 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN); 2232 bcopy((char *)&eh->ether_dhost, 2233 (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN); 2234 bcopy((char *)&eh->ether_shost, 2235 (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN); 2236 2237 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN; 2238 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0); 2239 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1); 2240 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN); 2241 tx_frame.wi_type = eh->ether_type; 2242 2243 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) { 2244 2245 /* Do host encryption. */ 2246 bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8); 2247 2248 m_copydata(m0, sizeof(struct ether_header), 2249 m0->m_pkthdr.len - sizeof(struct ether_header), 2250 (caddr_t)&sc->wi_txbuf[12]); 2251 2252 wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf, 2253 tx_frame.wi_dat_len); 2254 2255 tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN + 2256 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN; 2257 2258 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len); 2259 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, 2260 sizeof(struct wi_frame)); 2261 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, 2262 (caddr_t)&sc->wi_txbuf, 2263 (m0->m_pkthdr.len - 2264 sizeof(struct ether_header)) + 18); 2265 } else { 2266 m_copydata(m0, sizeof(struct ether_header), 2267 m0->m_pkthdr.len - sizeof(struct ether_header), 2268 (caddr_t)&sc->wi_txbuf); 2269 2270 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len); 2271 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, 2272 sizeof(struct wi_frame)); 2273 wi_write_data(sc, id, WI_802_11_OFFSET, 2274 (caddr_t)&sc->wi_txbuf, 2275 (m0->m_pkthdr.len - 2276 sizeof(struct ether_header)) + 2); 2277 } 2278 } else { 2279 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len); 2280 2281 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) { 2282 2283 /* Do host encryption. (XXX - not implemented) */ 2284 printf(WI_PRT_FMT 2285 ": host encrypt not implemented for 802.3\n", 2286 WI_PRT_ARG(sc)); 2287 } else { 2288 m_copydata(m0, 0, m0->m_pkthdr.len, 2289 (caddr_t)&sc->wi_txbuf); 2290 2291 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, 2292 sizeof(struct wi_frame)); 2293 wi_write_data(sc, id, WI_802_3_OFFSET, 2294 (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2); 2295 } 2296 } 2297 2298 #if NBPFILTER > 0 2299 /* 2300 * If there's a BPF listener, bounce a copy of 2301 * this frame to him. 2302 */ 2303 if (ifp->if_bpf) 2304 BPF_MTAP(ifp, m0); 2305 #endif 2306 2307 m_freem(m0); 2308 2309 ifp->if_flags |= IFF_OACTIVE; 2310 2311 /* 2312 * Set a timeout in case the chip goes out to lunch. 2313 */ 2314 ifp->if_timer = 5; 2315 2316 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) 2317 printf(WI_PRT_FMT ": wi_start: xmit failed\n", WI_PRT_ARG(sc)); 2318 2319 return; 2320 } 2321 2322 STATIC int 2323 wi_mgmt_xmit(sc, data, len) 2324 struct wi_softc *sc; 2325 caddr_t data; 2326 int len; 2327 { 2328 struct wi_frame tx_frame; 2329 int id; 2330 struct wi_80211_hdr *hdr; 2331 caddr_t dptr; 2332 2333 if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) 2334 return(ENODEV); 2335 2336 hdr = (struct wi_80211_hdr *)data; 2337 dptr = data + sizeof(struct wi_80211_hdr); 2338 2339 bzero((char *)&tx_frame, sizeof(tx_frame)); 2340 id = sc->wi_tx_mgmt_id; 2341 2342 bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl, 2343 sizeof(struct wi_80211_hdr)); 2344 2345 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); 2346 tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr); 2347 tx_frame.wi_len = htole16(tx_frame.wi_dat_len); 2348 2349 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len); 2350 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame)); 2351 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr, 2352 (len - sizeof(struct wi_80211_hdr)) + 2); 2353 2354 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) { 2355 printf(WI_PRT_FMT ": wi_mgmt_xmit: xmit failed\n", 2356 WI_PRT_ARG(sc)); 2357 return(EIO); 2358 } 2359 2360 return(0); 2361 } 2362 2363 void 2364 wi_stop(sc) 2365 struct wi_softc *sc; 2366 { 2367 struct ifnet *ifp; 2368 2369 wihap_shutdown(sc); 2370 2371 if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) 2372 return; 2373 2374 DPRINTF(WID_STOP, ("wi_stop: sc %p\n", sc)); 2375 2376 timeout_del(&sc->sc_timo); 2377 2378 ifp = &sc->sc_arpcom.ac_if; 2379 2380 wi_intr_enable(sc, 0); 2381 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0); 2382 2383 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 2384 ifp->if_timer = 0; 2385 2386 return; 2387 } 2388 2389 2390 void 2391 wi_watchdog(ifp) 2392 struct ifnet *ifp; 2393 { 2394 struct wi_softc *sc; 2395 2396 sc = ifp->if_softc; 2397 2398 printf(WI_PRT_FMT ": device timeout\n", WI_PRT_ARG(sc)); 2399 2400 wi_cor_reset(sc); 2401 wi_init(sc); 2402 2403 ifp->if_oerrors++; 2404 2405 return; 2406 } 2407 2408 void 2409 wi_detach(sc) 2410 struct wi_softc *sc; 2411 { 2412 struct ifnet *ifp; 2413 ifp = &sc->sc_arpcom.ac_if; 2414 2415 if (ifp->if_flags & IFF_RUNNING) 2416 wi_stop(sc); 2417 2418 if (sc->wi_flags & WI_FLAGS_ATTACHED) { 2419 sc->wi_flags &= ~WI_FLAGS_ATTACHED; 2420 shutdownhook_disestablish(sc->sc_sdhook); 2421 } 2422 } 2423 2424 STATIC void 2425 wi_shutdown(arg) 2426 void *arg; 2427 { 2428 struct wi_softc *sc; 2429 2430 sc = arg; 2431 wi_stop(sc); 2432 2433 return; 2434 } 2435 2436 STATIC void 2437 wi_get_id(sc) 2438 struct wi_softc *sc; 2439 { 2440 struct wi_ltv_ver ver; 2441 const struct wi_card_ident *id; 2442 u_int16_t pri_fw_ver[3]; 2443 const char *card_name; 2444 u_int16_t card_id; 2445 2446 /* get chip identity */ 2447 bzero(&ver, sizeof(ver)); 2448 ver.wi_type = WI_RID_CARD_ID; 2449 ver.wi_len = 5; 2450 wi_read_record(sc, (struct wi_ltv_gen *)&ver); 2451 card_id = letoh16(ver.wi_ver[0]); 2452 for (id = wi_card_ident; id->firm_type != WI_NOTYPE; id++) { 2453 if (card_id == id->card_id) 2454 break; 2455 } 2456 if (id->firm_type != WI_NOTYPE) { 2457 sc->sc_firmware_type = id->firm_type; 2458 card_name = id->card_name; 2459 } else if (ver.wi_ver[0] & htole16(0x8000)) { 2460 sc->sc_firmware_type = WI_INTERSIL; 2461 card_name = "Unknown PRISM2 chip"; 2462 } else { 2463 sc->sc_firmware_type = WI_LUCENT; 2464 } 2465 2466 /* get primary firmware version (XXX - how to do Lucent?) */ 2467 if (sc->sc_firmware_type != WI_LUCENT) { 2468 bzero(&ver, sizeof(ver)); 2469 ver.wi_type = WI_RID_PRI_IDENTITY; 2470 ver.wi_len = 5; 2471 wi_read_record(sc, (struct wi_ltv_gen *)&ver); 2472 pri_fw_ver[0] = letoh16(ver.wi_ver[2]); 2473 pri_fw_ver[1] = letoh16(ver.wi_ver[3]); 2474 pri_fw_ver[2] = letoh16(ver.wi_ver[1]); 2475 } 2476 2477 /* get station firmware version */ 2478 bzero(&ver, sizeof(ver)); 2479 ver.wi_type = WI_RID_STA_IDENTITY; 2480 ver.wi_len = 5; 2481 wi_read_record(sc, (struct wi_ltv_gen *)&ver); 2482 ver.wi_ver[1] = letoh16(ver.wi_ver[1]); 2483 ver.wi_ver[2] = letoh16(ver.wi_ver[2]); 2484 ver.wi_ver[3] = letoh16(ver.wi_ver[3]); 2485 sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 + 2486 ver.wi_ver[3] * 100 + ver.wi_ver[1]; 2487 2488 if (sc->sc_firmware_type == WI_INTERSIL && 2489 (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) { 2490 struct wi_ltv_str sver; 2491 char *p; 2492 2493 bzero(&sver, sizeof(sver)); 2494 sver.wi_type = WI_RID_SYMBOL_IDENTITY; 2495 sver.wi_len = 7; 2496 /* value should be something like "V2.00-11" */ 2497 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 && 2498 *(p = (char *)sver.wi_str) >= 'A' && 2499 p[2] == '.' && p[5] == '-' && p[8] == '\0') { 2500 sc->sc_firmware_type = WI_SYMBOL; 2501 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 + 2502 (p[3] - '0') * 1000 + (p[4] - '0') * 100 + 2503 (p[6] - '0') * 10 + (p[7] - '0'); 2504 } 2505 } 2506 2507 if (sc->sc_firmware_type == WI_LUCENT) { 2508 printf("\n%s: Firmware %d.%02d variant %d, ", WI_PRT_ARG(sc), 2509 ver.wi_ver[2], ver.wi_ver[3], ver.wi_ver[1]); 2510 } else { 2511 printf("\n%s: %s%s, Firmware %d.%d.%d (primary), %d.%d.%d (station), ", 2512 WI_PRT_ARG(sc), 2513 sc->sc_firmware_type == WI_SYMBOL ? "Symbol " : "", 2514 card_name, pri_fw_ver[0], pri_fw_ver[1], pri_fw_ver[2], 2515 sc->sc_sta_firmware_ver / 10000, 2516 (sc->sc_sta_firmware_ver % 10000) / 100, 2517 sc->sc_sta_firmware_ver % 100); 2518 } 2519 } 2520 2521 STATIC int 2522 wi_sync_media(sc, ptype, txrate) 2523 struct wi_softc *sc; 2524 int ptype; 2525 int txrate; 2526 { 2527 int media = sc->sc_media.ifm_cur->ifm_media; 2528 int options = IFM_OPTIONS(media); 2529 int subtype; 2530 2531 switch (txrate) { 2532 case 1: 2533 subtype = IFM_IEEE80211_DS1; 2534 break; 2535 case 2: 2536 subtype = IFM_IEEE80211_DS2; 2537 break; 2538 case 3: 2539 subtype = IFM_AUTO; 2540 break; 2541 case 5: 2542 subtype = IFM_IEEE80211_DS5; 2543 break; 2544 case 11: 2545 subtype = IFM_IEEE80211_DS11; 2546 break; 2547 default: 2548 subtype = IFM_MANUAL; /* Unable to represent */ 2549 break; 2550 } 2551 2552 options &= ~IFM_OMASK; 2553 switch (ptype) { 2554 case WI_PORTTYPE_BSS: 2555 /* default port type */ 2556 break; 2557 case WI_PORTTYPE_ADHOC: 2558 options |= IFM_IEEE80211_ADHOC; 2559 break; 2560 case WI_PORTTYPE_HOSTAP: 2561 options |= IFM_IEEE80211_HOSTAP; 2562 break; 2563 case WI_PORTTYPE_IBSS: 2564 if (sc->wi_create_ibss) 2565 options |= IFM_IEEE80211_IBSSMASTER; 2566 else 2567 options |= IFM_IEEE80211_IBSS; 2568 break; 2569 default: 2570 subtype = IFM_MANUAL; /* Unable to represent */ 2571 break; 2572 } 2573 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options, 2574 IFM_INST(media)); 2575 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL) 2576 return (EINVAL); 2577 ifmedia_set(&sc->sc_media, media); 2578 sc->wi_ptype = ptype; 2579 sc->wi_tx_rate = txrate; 2580 return (0); 2581 } 2582 2583 STATIC int 2584 wi_media_change(ifp) 2585 struct ifnet *ifp; 2586 { 2587 struct wi_softc *sc = ifp->if_softc; 2588 int otype = sc->wi_ptype; 2589 int orate = sc->wi_tx_rate; 2590 int ocreate_ibss = sc->wi_create_ibss; 2591 2592 if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) && 2593 sc->sc_firmware_type != WI_INTERSIL) 2594 return (EINVAL); 2595 2596 sc->wi_create_ibss = 0; 2597 2598 switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) { 2599 case 0: 2600 sc->wi_ptype = WI_PORTTYPE_BSS; 2601 break; 2602 case IFM_IEEE80211_ADHOC: 2603 sc->wi_ptype = WI_PORTTYPE_ADHOC; 2604 break; 2605 case IFM_IEEE80211_HOSTAP: 2606 sc->wi_ptype = WI_PORTTYPE_HOSTAP; 2607 break; 2608 case IFM_IEEE80211_IBSSMASTER: 2609 case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS: 2610 if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) 2611 return (EINVAL); 2612 sc->wi_create_ibss = 1; 2613 /* FALLTHROUGH */ 2614 case IFM_IEEE80211_IBSS: 2615 sc->wi_ptype = WI_PORTTYPE_IBSS; 2616 break; 2617 default: 2618 /* Invalid combination. */ 2619 return (EINVAL); 2620 } 2621 2622 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) { 2623 case IFM_IEEE80211_DS1: 2624 sc->wi_tx_rate = 1; 2625 break; 2626 case IFM_IEEE80211_DS2: 2627 sc->wi_tx_rate = 2; 2628 break; 2629 case IFM_AUTO: 2630 sc->wi_tx_rate = 3; 2631 break; 2632 case IFM_IEEE80211_DS5: 2633 sc->wi_tx_rate = 5; 2634 break; 2635 case IFM_IEEE80211_DS11: 2636 sc->wi_tx_rate = 11; 2637 break; 2638 } 2639 2640 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) { 2641 if (otype != sc->wi_ptype || orate != sc->wi_tx_rate || 2642 ocreate_ibss != sc->wi_create_ibss) 2643 wi_init(sc); 2644 } 2645 2646 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media); 2647 2648 return (0); 2649 } 2650 2651 STATIC void 2652 wi_media_status(ifp, imr) 2653 struct ifnet *ifp; 2654 struct ifmediareq *imr; 2655 { 2656 struct wi_softc *sc = ifp->if_softc; 2657 struct wi_req wreq; 2658 2659 if (!(sc->sc_arpcom.ac_if.if_flags & IFF_UP)) { 2660 imr->ifm_active = IFM_IEEE80211|IFM_NONE; 2661 imr->ifm_status = 0; 2662 return; 2663 } 2664 2665 if (sc->wi_tx_rate == 3) { 2666 imr->ifm_active = IFM_IEEE80211|IFM_AUTO; 2667 2668 wreq.wi_type = WI_RID_CUR_TX_RATE; 2669 wreq.wi_len = WI_MAX_DATALEN; 2670 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) { 2671 switch (letoh16(wreq.wi_val[0])) { 2672 case 1: 2673 imr->ifm_active |= IFM_IEEE80211_DS1; 2674 break; 2675 case 2: 2676 imr->ifm_active |= IFM_IEEE80211_DS2; 2677 break; 2678 case 6: 2679 imr->ifm_active |= IFM_IEEE80211_DS5; 2680 break; 2681 case 11: 2682 imr->ifm_active |= IFM_IEEE80211_DS11; 2683 break; 2684 } 2685 } 2686 } else { 2687 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media; 2688 } 2689 2690 imr->ifm_status = IFM_AVALID; 2691 switch (sc->wi_ptype) { 2692 case WI_PORTTYPE_ADHOC: 2693 case WI_PORTTYPE_IBSS: 2694 /* 2695 * XXX: It would be nice if we could give some actually 2696 * useful status like whether we joined another IBSS or 2697 * created one ourselves. 2698 */ 2699 /* FALLTHROUGH */ 2700 case WI_PORTTYPE_HOSTAP: 2701 imr->ifm_status |= IFM_ACTIVE; 2702 break; 2703 default: 2704 wreq.wi_type = WI_RID_COMMQUAL; 2705 wreq.wi_len = WI_MAX_DATALEN; 2706 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 && 2707 letoh16(wreq.wi_val[0]) != 0) 2708 imr->ifm_status |= IFM_ACTIVE; 2709 } 2710 } 2711 2712 STATIC int 2713 wi_set_nwkey(sc, nwkey) 2714 struct wi_softc *sc; 2715 struct ieee80211_nwkey *nwkey; 2716 { 2717 int i, len, error; 2718 struct wi_req wreq; 2719 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq; 2720 2721 if (!(sc->wi_flags & WI_FLAGS_HAS_WEP)) 2722 return ENODEV; 2723 if (nwkey->i_defkid <= 0 || nwkey->i_defkid > IEEE80211_WEP_NKID) 2724 return EINVAL; 2725 memcpy(wk, &sc->wi_keys, sizeof(*wk)); 2726 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2727 if (nwkey->i_key[i].i_keydat == NULL) 2728 continue; 2729 len = nwkey->i_key[i].i_keylen; 2730 if (len > sizeof(wk->wi_keys[i].wi_keydat)) 2731 return EINVAL; 2732 error = copyin(nwkey->i_key[i].i_keydat, 2733 wk->wi_keys[i].wi_keydat, len); 2734 if (error) 2735 return error; 2736 wk->wi_keys[i].wi_keylen = htole16(len); 2737 } 2738 2739 wk->wi_len = (sizeof(*wk) / 2) + 1; 2740 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS; 2741 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) { 2742 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); 2743 if (error) 2744 return error; 2745 } 2746 if ((error = wi_setdef(sc, &wreq))) 2747 return (error); 2748 2749 wreq.wi_len = 2; 2750 wreq.wi_type = WI_RID_TX_CRYPT_KEY; 2751 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1); 2752 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) { 2753 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); 2754 if (error) 2755 return error; 2756 } 2757 if ((error = wi_setdef(sc, &wreq))) 2758 return (error); 2759 2760 wreq.wi_type = WI_RID_ENCRYPTION; 2761 wreq.wi_val[0] = htole16(nwkey->i_wepon); 2762 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) { 2763 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); 2764 if (error) 2765 return error; 2766 } 2767 if ((error = wi_setdef(sc, &wreq))) 2768 return (error); 2769 2770 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) 2771 wi_init(sc); 2772 return 0; 2773 } 2774 2775 STATIC int 2776 wi_get_nwkey(sc, nwkey) 2777 struct wi_softc *sc; 2778 struct ieee80211_nwkey *nwkey; 2779 { 2780 int i, len, error; 2781 struct wi_ltv_keys *wk = &sc->wi_keys; 2782 2783 if (!(sc->wi_flags & WI_FLAGS_HAS_WEP)) 2784 return ENODEV; 2785 nwkey->i_wepon = sc->wi_use_wep; 2786 nwkey->i_defkid = sc->wi_tx_key + 1; 2787 2788 /* do not show any keys to non-root user */ 2789 error = suser(curproc, 0); 2790 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2791 if (nwkey->i_key[i].i_keydat == NULL) 2792 continue; 2793 /* error holds results of suser() for the first time */ 2794 if (error) 2795 return error; 2796 len = letoh16(wk->wi_keys[i].wi_keylen); 2797 if (nwkey->i_key[i].i_keylen < len) 2798 return ENOSPC; 2799 nwkey->i_key[i].i_keylen = len; 2800 error = copyout(wk->wi_keys[i].wi_keydat, 2801 nwkey->i_key[i].i_keydat, len); 2802 if (error) 2803 return error; 2804 } 2805 return 0; 2806 } 2807 2808 STATIC int 2809 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power) 2810 { 2811 2812 sc->wi_pm_enabled = power->i_enabled; 2813 sc->wi_max_sleep = power->i_maxsleep; 2814 2815 if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) 2816 wi_init(sc); 2817 2818 return (0); 2819 } 2820 2821 STATIC int 2822 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power) 2823 { 2824 2825 power->i_enabled = sc->wi_pm_enabled; 2826 power->i_maxsleep = sc->wi_max_sleep; 2827 2828 return (0); 2829 } 2830 2831 STATIC int 2832 wi_set_ssid(ws, id, len) 2833 struct ieee80211_nwid *ws; 2834 u_int8_t *id; 2835 int len; 2836 { 2837 2838 if (len > IEEE80211_NWID_LEN) 2839 return (EINVAL); 2840 ws->i_len = len; 2841 memcpy(ws->i_nwid, id, len); 2842 return (0); 2843 } 2844 2845 STATIC int 2846 wi_get_debug(sc, wreq) 2847 struct wi_softc *sc; 2848 struct wi_req *wreq; 2849 { 2850 int error = 0; 2851 2852 wreq->wi_len = 1; 2853 2854 switch (wreq->wi_type) { 2855 case WI_DEBUG_SLEEP: 2856 wreq->wi_len++; 2857 wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep); 2858 break; 2859 case WI_DEBUG_DELAYSUPP: 2860 wreq->wi_len++; 2861 wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp); 2862 break; 2863 case WI_DEBUG_TXSUPP: 2864 wreq->wi_len++; 2865 wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp); 2866 break; 2867 case WI_DEBUG_MONITOR: 2868 wreq->wi_len++; 2869 wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor); 2870 break; 2871 case WI_DEBUG_LEDTEST: 2872 wreq->wi_len += 3; 2873 wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest); 2874 wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0); 2875 wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1); 2876 break; 2877 case WI_DEBUG_CONTTX: 2878 wreq->wi_len += 2; 2879 wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx); 2880 wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0); 2881 break; 2882 case WI_DEBUG_CONTRX: 2883 wreq->wi_len++; 2884 wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx); 2885 break; 2886 case WI_DEBUG_SIGSTATE: 2887 wreq->wi_len += 2; 2888 wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate); 2889 wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0); 2890 break; 2891 case WI_DEBUG_CONFBITS: 2892 wreq->wi_len += 2; 2893 wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits); 2894 wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0); 2895 break; 2896 default: 2897 error = EIO; 2898 break; 2899 } 2900 2901 return (error); 2902 } 2903 2904 STATIC int 2905 wi_set_debug(sc, wreq) 2906 struct wi_softc *sc; 2907 struct wi_req *wreq; 2908 { 2909 int error = 0; 2910 u_int16_t cmd, param0 = 0, param1 = 0; 2911 2912 switch (wreq->wi_type) { 2913 case WI_DEBUG_RESET: 2914 case WI_DEBUG_INIT: 2915 case WI_DEBUG_CALENABLE: 2916 break; 2917 case WI_DEBUG_SLEEP: 2918 sc->wi_debug.wi_sleep = 1; 2919 break; 2920 case WI_DEBUG_WAKE: 2921 sc->wi_debug.wi_sleep = 0; 2922 break; 2923 case WI_DEBUG_CHAN: 2924 param0 = letoh16(wreq->wi_val[0]); 2925 break; 2926 case WI_DEBUG_DELAYSUPP: 2927 sc->wi_debug.wi_delaysupp = 1; 2928 break; 2929 case WI_DEBUG_TXSUPP: 2930 sc->wi_debug.wi_txsupp = 1; 2931 break; 2932 case WI_DEBUG_MONITOR: 2933 sc->wi_debug.wi_monitor = 1; 2934 break; 2935 case WI_DEBUG_LEDTEST: 2936 param0 = letoh16(wreq->wi_val[0]); 2937 param1 = letoh16(wreq->wi_val[1]); 2938 sc->wi_debug.wi_ledtest = 1; 2939 sc->wi_debug.wi_ledtest_param0 = param0; 2940 sc->wi_debug.wi_ledtest_param1 = param1; 2941 break; 2942 case WI_DEBUG_CONTTX: 2943 param0 = letoh16(wreq->wi_val[0]); 2944 sc->wi_debug.wi_conttx = 1; 2945 sc->wi_debug.wi_conttx_param0 = param0; 2946 break; 2947 case WI_DEBUG_STOPTEST: 2948 sc->wi_debug.wi_delaysupp = 0; 2949 sc->wi_debug.wi_txsupp = 0; 2950 sc->wi_debug.wi_monitor = 0; 2951 sc->wi_debug.wi_ledtest = 0; 2952 sc->wi_debug.wi_ledtest_param0 = 0; 2953 sc->wi_debug.wi_ledtest_param1 = 0; 2954 sc->wi_debug.wi_conttx = 0; 2955 sc->wi_debug.wi_conttx_param0 = 0; 2956 sc->wi_debug.wi_contrx = 0; 2957 sc->wi_debug.wi_sigstate = 0; 2958 sc->wi_debug.wi_sigstate_param0 = 0; 2959 break; 2960 case WI_DEBUG_CONTRX: 2961 sc->wi_debug.wi_contrx = 1; 2962 break; 2963 case WI_DEBUG_SIGSTATE: 2964 param0 = letoh16(wreq->wi_val[0]); 2965 sc->wi_debug.wi_sigstate = 1; 2966 sc->wi_debug.wi_sigstate_param0 = param0; 2967 break; 2968 case WI_DEBUG_CONFBITS: 2969 param0 = letoh16(wreq->wi_val[0]); 2970 param1 = letoh16(wreq->wi_val[1]); 2971 sc->wi_debug.wi_confbits = param0; 2972 sc->wi_debug.wi_confbits_param0 = param1; 2973 break; 2974 default: 2975 error = EIO; 2976 break; 2977 } 2978 2979 if (error) 2980 return (error); 2981 2982 cmd = WI_CMD_DEBUG | (wreq->wi_type << 8); 2983 error = wi_cmd(sc, cmd, param0, param1, 0); 2984 2985 return (error); 2986 } 2987