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