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