1 /* $NetBSD: wi.c,v 1.72 2002/04/18 05:24:28 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.72 2002/04/18 05:24:28 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)); 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 static int wi_mgmt_xmit __P((struct wi_softc *, caddr_t, int)); 132 133 static int wi_media_change __P((struct ifnet *)); 134 static void wi_media_status __P((struct ifnet *, struct ifmediareq *)); 135 136 static void wi_get_id __P((struct wi_softc *)); 137 138 static int wi_set_ssid __P((struct ieee80211_nwid *, u_int8_t *, int)); 139 static void wi_request_fill_ssid __P((struct wi_req *, 140 struct ieee80211_nwid *)); 141 static int wi_write_ssid __P((struct wi_softc *, int, struct wi_req *, 142 struct ieee80211_nwid *)); 143 static int wi_set_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *)); 144 static int wi_get_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *)); 145 static int wi_sync_media __P((struct wi_softc *, int, int)); 146 static int wi_set_pm(struct wi_softc *, struct ieee80211_power *); 147 static int wi_get_pm(struct wi_softc *, struct ieee80211_power *); 148 149 struct wi_card_ident wi_card_ident[] = { 150 /* CARD_ID CARD_NAME FIRM_TYPE */ 151 { WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT }, 152 { WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT }, 153 { WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT }, 154 { WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL }, 155 { WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL }, 156 { WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL }, 157 { WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL }, 158 { WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL }, 159 { WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL }, 160 { WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL }, 161 { WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL }, 162 { WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL }, 163 { WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, 164 { WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, 165 { WI_NIC_3842_PCMCIA_ATM_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, 166 { WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, 167 { WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, 168 { WI_NIC_3842_MINI_ATM_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, 169 { WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, 170 { WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, 171 { WI_NIC_3842_PCI_ATM_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, 172 { WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL }, 173 { WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL }, 174 { WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL }, 175 { WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL }, 176 { 0, NULL, 0 }, 177 }; 178 179 int 180 wi_attach(sc) 181 struct wi_softc *sc; 182 { 183 struct ifnet *ifp = sc->sc_ifp; 184 struct wi_ltv_macaddr mac; 185 struct wi_ltv_gen gen; 186 static const u_int8_t empty_macaddr[ETHER_ADDR_LEN] = { 187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 188 }; 189 int s; 190 191 s = splnet(); 192 193 callout_init(&sc->wi_inquire_ch); 194 callout_init(&sc->wi_scan_sh); 195 196 /* Make sure interrupts are disabled. */ 197 CSR_WRITE_2(sc, WI_INT_EN, 0); 198 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); 199 200 /* Reset the NIC. */ 201 wi_reset(sc); 202 203 memset(&mac, 0, sizeof(mac)); 204 /* Read the station address. */ 205 mac.wi_type = WI_RID_MAC_NODE; 206 mac.wi_len = 4; 207 wi_read_record(sc, (struct wi_ltv_gen *)&mac); 208 memcpy(sc->sc_macaddr, mac.wi_mac_addr, ETHER_ADDR_LEN); 209 210 /* 211 * Check if we got anything meaningful. 212 * 213 * Is it really enough just checking against null ethernet address? 214 * Or, check against possible vendor? XXX. 215 */ 216 if (memcmp(sc->sc_macaddr, empty_macaddr, ETHER_ADDR_LEN) == 0) { 217 printf("could not get mac address, attach failed\n"); 218 splx(s); 219 return 1; 220 } 221 222 printf(" 802.11 address %s\n", ether_sprintf(sc->sc_macaddr)); 223 224 /* Read NIC identification */ 225 wi_get_id(sc); 226 227 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 228 ifp->if_softc = sc; 229 ifp->if_start = wi_start; 230 ifp->if_ioctl = wi_ioctl; 231 ifp->if_watchdog = wi_watchdog; 232 ifp->if_init = wi_init; 233 ifp->if_stop = wi_stop; 234 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 235 #ifdef IFF_NOTRAILERS 236 ifp->if_flags |= IFF_NOTRAILERS; 237 #endif 238 IFQ_SET_READY(&ifp->if_snd); 239 240 (void)wi_set_ssid(&sc->wi_nodeid, WI_DEFAULT_NODENAME, 241 sizeof(WI_DEFAULT_NODENAME) - 1); 242 (void)wi_set_ssid(&sc->wi_netid, WI_DEFAULT_NETNAME, 243 sizeof(WI_DEFAULT_NETNAME) - 1); 244 (void)wi_set_ssid(&sc->wi_ibssid, WI_DEFAULT_IBSS, 245 sizeof(WI_DEFAULT_IBSS) - 1); 246 247 sc->wi_portnum = WI_DEFAULT_PORT; 248 sc->wi_ptype = WI_PORTTYPE_BSS; 249 sc->wi_ap_density = WI_DEFAULT_AP_DENSITY; 250 sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH; 251 sc->wi_tx_rate = WI_DEFAULT_TX_RATE; 252 sc->wi_max_data_len = WI_DEFAULT_DATALEN; 253 sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS; 254 sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED; 255 sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP; 256 sc->wi_roaming = WI_DEFAULT_ROAMING; 257 sc->wi_authtype = WI_DEFAULT_AUTHTYPE; 258 259 /* 260 * Read the default channel from the NIC. This may vary 261 * depending on the country where the NIC was purchased, so 262 * we can't hard-code a default and expect it to work for 263 * everyone. 264 */ 265 gen.wi_type = WI_RID_OWN_CHNL; 266 gen.wi_len = 2; 267 wi_read_record(sc, &gen); 268 sc->wi_channel = le16toh(gen.wi_val); 269 270 memset((char *)&sc->wi_stats, 0, sizeof(sc->wi_stats)); 271 272 /* AP info was filled with 0 */ 273 memset((char *)&sc->wi_aps, 0, sizeof(sc->wi_aps)); 274 sc->wi_scanning=0; 275 sc->wi_naps=0; 276 277 /* 278 * Find out if we support WEP on this card. 279 */ 280 gen.wi_type = WI_RID_WEP_AVAIL; 281 gen.wi_len = 2; 282 wi_read_record(sc, &gen); 283 sc->wi_has_wep = le16toh(gen.wi_val); 284 285 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status); 286 #define ADD(m, c) ifmedia_add(&sc->sc_media, (m), (c), NULL) 287 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0); 288 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0); 289 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); 290 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 291 IFM_IEEE80211_ADHOC, 0), 0); 292 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); 293 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 294 IFM_IEEE80211_ADHOC, 0), 0); 295 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); 296 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 297 IFM_IEEE80211_ADHOC, 0), 0); 298 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); 299 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 300 IFM_IEEE80211_ADHOC, 0), 0); 301 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0); 302 #undef ADD 303 ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0)); 304 305 /* 306 * Call MI attach routines. 307 */ 308 if_attach(ifp); 309 ether_ifattach(ifp, mac.wi_mac_addr); 310 311 ifp->if_baudrate = IF_Mbps(2); 312 313 /* Attach is successful. */ 314 sc->sc_attached = 1; 315 316 splx(s); 317 return 0; 318 } 319 320 static void wi_rxeof(sc) 321 struct wi_softc *sc; 322 { 323 struct ifnet *ifp; 324 struct ether_header *eh; 325 struct wi_frame rx_frame; 326 struct mbuf *m; 327 int id; 328 329 ifp = sc->sc_ifp; 330 331 id = CSR_READ_2(sc, WI_RX_FID); 332 333 /* First read in the frame header */ 334 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) { 335 ifp->if_ierrors++; 336 return; 337 } 338 339 /* 340 * Drop undecryptable or packets with receive errors here 341 */ 342 if (le16toh(rx_frame.wi_status) & WI_STAT_ERRSTAT) { 343 ifp->if_ierrors++; 344 return; 345 } 346 347 MGETHDR(m, M_DONTWAIT, MT_DATA); 348 if (m == NULL) { 349 ifp->if_ierrors++; 350 return; 351 } 352 MCLGET(m, M_DONTWAIT); 353 if (!(m->m_flags & M_EXT)) { 354 m_freem(m); 355 ifp->if_ierrors++; 356 return; 357 } 358 359 /* Align the data after the ethernet header */ 360 m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header)) 361 - sizeof(struct ether_header); 362 363 eh = mtod(m, struct ether_header *); 364 m->m_pkthdr.rcvif = ifp; 365 366 if (le16toh(rx_frame.wi_status) == WI_STAT_1042 || 367 le16toh(rx_frame.wi_status) == WI_STAT_TUNNEL || 368 le16toh(rx_frame.wi_status) == WI_STAT_WMP_MSG) { 369 if ((le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > MCLBYTES) { 370 printf("%s: oversized packet received " 371 "(wi_dat_len=%d, wi_status=0x%x)\n", 372 sc->sc_dev.dv_xname, 373 le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status)); 374 m_freem(m); 375 ifp->if_ierrors++; 376 return; 377 } 378 m->m_pkthdr.len = m->m_len = 379 le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN; 380 381 memcpy((char *)&eh->ether_dhost, (char *)&rx_frame.wi_dst_addr, 382 ETHER_ADDR_LEN); 383 memcpy((char *)&eh->ether_shost, (char *)&rx_frame.wi_src_addr, 384 ETHER_ADDR_LEN); 385 memcpy((char *)&eh->ether_type, (char *)&rx_frame.wi_type, 386 sizeof(u_int16_t)); 387 388 if (wi_read_data(sc, id, WI_802_11_OFFSET, 389 mtod(m, caddr_t) + sizeof(struct ether_header), 390 m->m_len + 2)) { 391 m_freem(m); 392 ifp->if_ierrors++; 393 return; 394 } 395 } else { 396 if ((le16toh(rx_frame.wi_dat_len) + 397 sizeof(struct ether_header)) > MCLBYTES) { 398 printf("%s: oversized packet received " 399 "(wi_dat_len=%d, wi_status=0x%x)\n", 400 sc->sc_dev.dv_xname, 401 le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status)); 402 m_freem(m); 403 ifp->if_ierrors++; 404 return; 405 } 406 m->m_pkthdr.len = m->m_len = 407 le16toh(rx_frame.wi_dat_len) + sizeof(struct ether_header); 408 409 if (wi_read_data(sc, id, WI_802_3_OFFSET, 410 mtod(m, caddr_t), m->m_len + 2)) { 411 m_freem(m); 412 ifp->if_ierrors++; 413 return; 414 } 415 } 416 417 ifp->if_ipackets++; 418 419 #if NBPFILTER > 0 420 /* Handle BPF listeners. */ 421 if (ifp->if_bpf) 422 bpf_mtap(ifp->if_bpf, m); 423 #endif 424 425 /* Receive packet. */ 426 (*ifp->if_input)(ifp, m); 427 } 428 429 static void wi_txeof(sc, status) 430 struct wi_softc *sc; 431 int status; 432 { 433 struct ifnet *ifp = sc->sc_ifp; 434 435 ifp->if_timer = 0; 436 ifp->if_flags &= ~IFF_OACTIVE; 437 438 if (status & WI_EV_TX_EXC) 439 ifp->if_oerrors++; 440 else 441 ifp->if_opackets++; 442 443 return; 444 } 445 446 void wi_inquire(xsc) 447 void *xsc; 448 { 449 struct wi_softc *sc; 450 struct ifnet *ifp; 451 int s; 452 453 sc = xsc; 454 ifp = &sc->sc_ethercom.ec_if; 455 456 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) 457 return; 458 459 KASSERT(sc->sc_enabled); 460 461 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc); 462 463 /* Don't do this while we're transmitting */ 464 if (ifp->if_flags & IFF_OACTIVE) 465 return; 466 467 s = splnet(); 468 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS); 469 splx(s); 470 } 471 472 void wi_wait_scan(xsc) 473 void *xsc; 474 { 475 struct wi_softc *sc; 476 struct ifnet *ifp; 477 int s, result; 478 479 sc = xsc; 480 ifp = &sc->sc_ethercom.ec_if; 481 482 /* If not scanning, ignore */ 483 if (!sc->wi_scanning) 484 return; 485 486 s = splnet(); 487 488 /* Wait for sending complete to make INQUIRE */ 489 if (ifp->if_flags & IFF_OACTIVE) { 490 callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc); 491 splx(s); 492 return; 493 } 494 495 /* try INQUIRE */ 496 result = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS); 497 if (result == ETIMEDOUT) 498 callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc); 499 500 splx(s); 501 } 502 503 void wi_update_stats(sc) 504 struct wi_softc *sc; 505 { 506 struct wi_ltv_gen gen; 507 struct wi_scan_header ap2_header; /* Prism2 header */ 508 struct wi_scan_data_p2 ap2; /* Prism2 scantable*/ 509 struct wi_scan_data ap; /* Lucent scantable */ 510 struct wi_assoc assoc; /* Association Status */ 511 u_int16_t id; 512 struct ifnet *ifp; 513 u_int32_t *ptr; 514 int len, naps, i, j; 515 u_int16_t t; 516 517 ifp = &sc->sc_ethercom.ec_if; 518 519 id = CSR_READ_2(sc, WI_INFO_FID); 520 521 if (wi_seek(sc, id, 0, WI_BAP1)) { 522 return; 523 } 524 525 gen.wi_len = CSR_READ_2(sc, WI_DATA1); 526 gen.wi_type = CSR_READ_2(sc, WI_DATA1); 527 528 switch (gen.wi_type) { 529 case WI_INFO_SCAN_RESULTS: 530 case WI_INFO_HOST_SCAN_RESULTS: 531 if (gen.wi_len <= 3) { 532 sc->wi_naps = 0; 533 sc->wi_scanning = 0; 534 break; 535 } 536 switch (sc->sc_firmware_type) { 537 case WI_INTERSIL: 538 case WI_SYMBOL: 539 if (sc->sc_firmware_type == WI_INTERSIL) { 540 naps = 2 * (gen.wi_len - 3) / sizeof(ap2); 541 /* Read Header */ 542 for(j=0; j < sizeof(ap2_header) / 2; j++) 543 ((u_int16_t *)&ap2_header)[j] = 544 CSR_READ_2(sc, WI_DATA1); 545 } else { /* WI_SYMBOL */ 546 naps = 2 * (gen.wi_len - 1) / (sizeof(ap2) + 6); 547 ap2_header.wi_reason = 0; 548 } 549 naps = naps > MAXAPINFO ? MAXAPINFO : naps; 550 sc->wi_naps = naps; 551 /* Read Data */ 552 for (i=0; i < naps; i++) { 553 for(j=0; j < sizeof(ap2) / 2; j++) 554 ((u_int16_t *)&ap2)[j] = 555 CSR_READ_2(sc, WI_DATA1); 556 if (sc->sc_firmware_type == WI_SYMBOL) { 557 /* 3 more words */ 558 for (j = 0; j < 3; j++) 559 CSR_READ_2(sc, WI_DATA1); 560 } 561 /* unswap 8 bit data fields: */ 562 for(j=0;j<sizeof(ap.wi_bssid)/2;j++) 563 LE16TOH(((u_int16_t *)&ap.wi_bssid[0])[j]); 564 for(j=0;j<sizeof(ap.wi_name)/2;j++) 565 LE16TOH(((u_int16_t *)&ap.wi_name[0])[j]); 566 sc->wi_aps[i].scanreason = ap2_header.wi_reason; 567 memcpy(sc->wi_aps[i].bssid, ap2.wi_bssid, 6); 568 sc->wi_aps[i].channel = ap2.wi_chid; 569 sc->wi_aps[i].signal = ap2.wi_signal; 570 sc->wi_aps[i].noise = ap2.wi_noise; 571 sc->wi_aps[i].quality = ap2.wi_signal - ap2.wi_noise; 572 sc->wi_aps[i].capinfo = ap2.wi_capinfo; 573 sc->wi_aps[i].interval = ap2.wi_interval; 574 sc->wi_aps[i].rate = ap2.wi_rate; 575 if (ap2.wi_namelen > 32) 576 ap2.wi_namelen = 32; 577 sc->wi_aps[i].namelen = ap2.wi_namelen; 578 memcpy(sc->wi_aps[i].name, ap2.wi_name, 579 ap2.wi_namelen); 580 } 581 break; 582 583 case WI_LUCENT: 584 naps = 2 * gen.wi_len / sizeof(ap); 585 naps = naps > MAXAPINFO ? MAXAPINFO : naps; 586 sc->wi_naps = naps; 587 /* Read Data*/ 588 for (i=0; i < naps; i++) { 589 for(j=0; j < sizeof(ap) / 2; j++) 590 ((u_int16_t *)&ap)[j] = 591 CSR_READ_2(sc, WI_DATA1); 592 /* unswap 8 bit data fields: */ 593 for(j=0;j<sizeof(ap.wi_bssid)/2;j++) 594 HTOLE16(((u_int16_t *)&ap.wi_bssid[0])[j]); 595 for(j=0;j<sizeof(ap.wi_name)/2;j++) 596 HTOLE16(((u_int16_t *)&ap.wi_name[0])[j]); 597 memcpy(sc->wi_aps[i].bssid, ap.wi_bssid, 6); 598 sc->wi_aps[i].channel = ap.wi_chid; 599 sc->wi_aps[i].signal = ap.wi_signal; 600 sc->wi_aps[i].noise = ap.wi_noise; 601 sc->wi_aps[i].quality = ap.wi_signal - ap.wi_noise; 602 sc->wi_aps[i].capinfo = ap.wi_capinfo; 603 sc->wi_aps[i].interval = ap.wi_interval; 604 if (ap.wi_namelen > 32) 605 ap.wi_namelen = 32; 606 sc->wi_aps[i].namelen = ap.wi_namelen; 607 memcpy(sc->wi_aps[i].name, ap.wi_name, 608 ap.wi_namelen); 609 } 610 break; 611 } 612 /* Done scanning */ 613 sc->wi_scanning = 0; 614 break; 615 616 case WI_INFO_COUNTERS: 617 /* some card versions have a larger stats structure */ 618 len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ? 619 gen.wi_len - 1 : sizeof(sc->wi_stats) / 4; 620 ptr = (u_int32_t *)&sc->wi_stats; 621 622 for (i = 0; i < len; i++) { 623 t = CSR_READ_2(sc, WI_DATA1); 624 #ifdef WI_HERMES_STATS_WAR 625 if (t > 0xF000) 626 t = ~t & 0xFFFF; 627 #endif 628 ptr[i] += t; 629 } 630 631 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries + 632 sc->wi_stats.wi_tx_multi_retries + 633 sc->wi_stats.wi_tx_retry_limit; 634 break; 635 636 case WI_INFO_LINK_STAT: { 637 static char *msg[] = { 638 "connected", 639 "disconnected", 640 "AP change", 641 "AP out of range", 642 "AP in range", 643 "Association Failed" 644 }; 645 646 if (gen.wi_len != 2) { 647 #ifdef WI_DEBUG 648 printf("WI_INFO_LINK_STAT: len=%d\n", gen.wi_len); 649 #endif 650 break; 651 } 652 t = CSR_READ_2(sc, WI_DATA1); 653 if ((t < 1) || (t > 6)) { 654 #ifdef WI_DEBUG 655 printf("WI_INFO_LINK_STAT: status %d\n", t); 656 #endif 657 break; 658 } 659 if (sc->sc_firmware_type == WI_SYMBOL && t == 4) { 660 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_HOST_SCAN_RESULTS); 661 break; 662 } 663 /* 664 * Some cards issue streams of "connected" messages while 665 * trying to find a peer. Don't bother the user with this 666 * unless he is debugging. 667 */ 668 if (ifp->if_flags & IFF_DEBUG) 669 printf("%s: %s\n", sc->sc_dev.dv_xname, msg[t - 1]); 670 break; 671 } 672 673 case WI_INFO_ASSOC_STAT: { 674 static char *msg[] = { 675 "STA Associated", 676 "STA Reassociated", 677 "STA Disassociated", 678 "Association Failure", 679 "Authentication Failed" 680 }; 681 if (gen.wi_len != 10) 682 break; 683 for (i=0; i < gen.wi_len - 1; i++) 684 ((u_int16_t *)&assoc)[i] = CSR_READ_2(sc, WI_DATA1); 685 /* unswap 8 bit data fields: */ 686 for(j=0;j<sizeof(assoc.wi_assoc_sta)/2;j++) 687 HTOLE16(((u_int16_t *)&assoc.wi_assoc_sta[0])[j]); 688 for(j=0;j<sizeof(assoc.wi_assoc_osta)/2;j++) 689 HTOLE16(((u_int16_t *)&assoc.wi_assoc_osta[0])[j]); 690 switch (assoc.wi_assoc_stat) { 691 case ASSOC: 692 case DISASSOC: 693 case ASSOCFAIL: 694 case AUTHFAIL: 695 printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x\n", 696 sc->sc_dev.dv_xname, 697 msg[assoc.wi_assoc_stat - 1], 698 assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff, 699 assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff, 700 assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff); 701 break; 702 case REASSOC: 703 printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x, " 704 "OldAP = %02x:%02x:%02x:%02x:%02x:%02x\n", 705 sc->sc_dev.dv_xname, msg[assoc.wi_assoc_stat - 1], 706 assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff, 707 assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff, 708 assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff, 709 assoc.wi_assoc_osta[0]&0xff, assoc.wi_assoc_osta[1]&0xff, 710 assoc.wi_assoc_osta[2]&0xff, assoc.wi_assoc_osta[3]&0xff, 711 assoc.wi_assoc_osta[4]&0xff, assoc.wi_assoc_osta[5]&0xff); 712 break; 713 } 714 } 715 716 default: 717 #ifdef WI_DEBUG 718 printf("%s: got info type: 0x%04x len=0x%04x\n", 719 sc->sc_dev.dv_xname, gen.wi_type,gen.wi_len); 720 #endif 721 #if 0 722 for (i = 0; i < gen.wi_len; i++) { 723 t = CSR_READ_2(sc, WI_DATA1); 724 printf("[0x%02x] = 0x%04x\n", i, t); 725 } 726 #endif 727 break; 728 } 729 } 730 731 int wi_intr(arg) 732 void *arg; 733 { 734 struct wi_softc *sc = arg; 735 struct ifnet *ifp; 736 u_int16_t status; 737 738 if (sc->sc_enabled == 0 || 739 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 || 740 (sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0) 741 return (0); 742 743 ifp = &sc->sc_ethercom.ec_if; 744 745 if (!(ifp->if_flags & IFF_UP)) { 746 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); 747 CSR_WRITE_2(sc, WI_INT_EN, 0); 748 return 1; 749 } 750 751 /* Disable interrupts. */ 752 CSR_WRITE_2(sc, WI_INT_EN, 0); 753 754 status = CSR_READ_2(sc, WI_EVENT_STAT); 755 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS); 756 757 if (status & WI_EV_RX) { 758 wi_rxeof(sc); 759 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 760 } 761 762 if (status & WI_EV_TX) { 763 wi_txeof(sc, status); 764 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX); 765 } 766 767 if (status & WI_EV_ALLOC) { 768 int id; 769 id = CSR_READ_2(sc, WI_ALLOC_FID); 770 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); 771 if (id == sc->wi_tx_data_id) 772 wi_txeof(sc, status); 773 } 774 775 if (status & WI_EV_INFO) { 776 wi_update_stats(sc); 777 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO); 778 } 779 780 if (status & WI_EV_TX_EXC) { 781 wi_txeof(sc, status); 782 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC); 783 } 784 785 if (status & WI_EV_INFO_DROP) { 786 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP); 787 } 788 789 /* Re-enable interrupts. */ 790 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); 791 792 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 793 wi_start(ifp); 794 795 return 1; 796 } 797 798 /* Must be called at proper protection level! */ 799 static int 800 wi_cmd(sc, cmd, val) 801 struct wi_softc *sc; 802 int cmd; 803 int val; 804 { 805 int i, s = 0; 806 807 /* wait for the busy bit to clear */ 808 for (i = 0; i < WI_TIMEOUT; i++) { 809 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) 810 break; 811 } 812 813 if (i == WI_TIMEOUT) { 814 printf("%s: wi_cmd: BUSY did not clear, cmd=0x%x\n", 815 sc->sc_dev.dv_xname, cmd); 816 return EIO; 817 } 818 819 CSR_WRITE_2(sc, WI_PARAM0, val); 820 CSR_WRITE_2(sc, WI_PARAM1, 0); 821 CSR_WRITE_2(sc, WI_PARAM2, 0); 822 CSR_WRITE_2(sc, WI_COMMAND, cmd); 823 824 /* wait for the cmd completed bit */ 825 for (i = 0; i < WI_TIMEOUT; i++) { 826 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD) 827 break; 828 DELAY(1); 829 } 830 831 /* Ack the command */ 832 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); 833 834 s = CSR_READ_2(sc, WI_STATUS); 835 if (s & WI_STAT_CMD_RESULT) 836 return(EIO); 837 838 if (i == WI_TIMEOUT) { 839 if (!sc->wi_scanning) 840 printf("%s: command timed out, cmd=0x%x\n", 841 sc->sc_dev.dv_xname, cmd); 842 return(ETIMEDOUT); 843 } 844 845 return(0); 846 } 847 848 static void 849 wi_reset(sc) 850 struct wi_softc *sc; 851 { 852 853 DELAY(100*1000); /* 100 m sec */ 854 if (wi_cmd(sc, WI_CMD_INI, 0)) 855 printf("%s: init failed\n", sc->sc_dev.dv_xname); 856 CSR_WRITE_2(sc, WI_INT_EN, 0); 857 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); 858 859 /* Calibrate timer. */ 860 WI_SETVAL(WI_RID_TICK_TIME, 8); 861 862 return; 863 } 864 865 /* 866 * Read an LTV record from the NIC. 867 */ 868 static int wi_read_record(sc, ltv) 869 struct wi_softc *sc; 870 struct wi_ltv_gen *ltv; 871 { 872 u_int16_t *ptr; 873 int len, code; 874 struct wi_ltv_gen *oltv, p2ltv; 875 876 if (sc->sc_firmware_type != WI_LUCENT) { 877 oltv = ltv; 878 switch (ltv->wi_type) { 879 case WI_RID_ENCRYPTION: 880 p2ltv.wi_type = WI_RID_P2_ENCRYPTION; 881 p2ltv.wi_len = 2; 882 ltv = &p2ltv; 883 break; 884 case WI_RID_TX_CRYPT_KEY: 885 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; 886 p2ltv.wi_len = 2; 887 ltv = &p2ltv; 888 break; 889 case WI_RID_ROAMING_MODE: 890 if (sc->sc_firmware_type == WI_INTERSIL) 891 break; 892 /* not supported */ 893 ltv->wi_len = 1; 894 return 0; 895 case WI_RID_MICROWAVE_OVEN: 896 /* not supported */ 897 ltv->wi_len = 1; 898 return 0; 899 } 900 } 901 902 /* Tell the NIC to enter record read mode. */ 903 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type)) 904 return(EIO); 905 906 /* Seek to the record. */ 907 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) 908 return(EIO); 909 910 /* 911 * Read the length and record type and make sure they 912 * match what we expect (this verifies that we have enough 913 * room to hold all of the returned data). 914 */ 915 len = CSR_READ_2(sc, WI_DATA1); 916 if (len > ltv->wi_len) 917 return(ENOSPC); 918 code = CSR_READ_2(sc, WI_DATA1); 919 if (code != ltv->wi_type) 920 return(EIO); 921 922 ltv->wi_len = len; 923 ltv->wi_type = code; 924 925 /* Now read the data. */ 926 ptr = <v->wi_val; 927 if (ltv->wi_len > 1) 928 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1); 929 930 if (sc->sc_firmware_type != WI_LUCENT) { 931 int v; 932 933 switch (oltv->wi_type) { 934 case WI_RID_TX_RATE: 935 case WI_RID_CUR_TX_RATE: 936 switch (le16toh(ltv->wi_val)) { 937 case 1: v = 1; break; 938 case 2: v = 2; break; 939 case 3: v = 6; break; 940 case 4: v = 5; break; 941 case 7: v = 7; break; 942 case 8: v = 11; break; 943 case 15: v = 3; break; 944 default: v = 0x100 + le16toh(ltv->wi_val); break; 945 } 946 oltv->wi_val = htole16(v); 947 break; 948 case WI_RID_ENCRYPTION: 949 oltv->wi_len = 2; 950 if (le16toh(ltv->wi_val) & 0x01) 951 oltv->wi_val = htole16(1); 952 else 953 oltv->wi_val = htole16(0); 954 break; 955 case WI_RID_TX_CRYPT_KEY: 956 oltv->wi_len = 2; 957 oltv->wi_val = ltv->wi_val; 958 break; 959 case WI_RID_AUTH_CNTL: 960 oltv->wi_len = 2; 961 if (le16toh(ltv->wi_val) & 0x01) 962 oltv->wi_val = htole16(1); 963 else if (le16toh(ltv->wi_val) & 0x02) 964 oltv->wi_val = htole16(2); 965 break; 966 } 967 } 968 969 return(0); 970 } 971 972 /* 973 * Same as read, except we inject data instead of reading it. 974 */ 975 static int wi_write_record(sc, ltv) 976 struct wi_softc *sc; 977 struct wi_ltv_gen *ltv; 978 { 979 u_int16_t *ptr; 980 int i; 981 struct wi_ltv_gen p2ltv; 982 983 if (sc->sc_firmware_type != WI_LUCENT) { 984 int v; 985 986 switch (ltv->wi_type) { 987 case WI_RID_TX_RATE: 988 p2ltv.wi_type = WI_RID_TX_RATE; 989 p2ltv.wi_len = 2; 990 switch (le16toh(ltv->wi_val)) { 991 case 1: v = 1; break; 992 case 2: v = 2; break; 993 case 3: v = 15; break; 994 case 5: v = 4; break; 995 case 6: v = 3; break; 996 case 7: v = 7; break; 997 case 11: v = 8; break; 998 default: return EINVAL; 999 } 1000 p2ltv.wi_val = htole16(v); 1001 ltv = &p2ltv; 1002 break; 1003 case WI_RID_ENCRYPTION: 1004 p2ltv.wi_type = WI_RID_P2_ENCRYPTION; 1005 p2ltv.wi_len = 2; 1006 if (le16toh(ltv->wi_val)) 1007 p2ltv.wi_val = htole16(PRIVACY_INVOKED | 1008 EXCLUDE_UNENCRYPTED); 1009 else 1010 p2ltv.wi_val = 1011 htole16(HOST_ENCRYPT | HOST_DECRYPT); 1012 ltv = &p2ltv; 1013 break; 1014 case WI_RID_TX_CRYPT_KEY: 1015 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; 1016 p2ltv.wi_len = 2; 1017 p2ltv.wi_val = ltv->wi_val; 1018 ltv = &p2ltv; 1019 break; 1020 case WI_RID_DEFLT_CRYPT_KEYS: 1021 { 1022 int error; 1023 int keylen; 1024 struct wi_ltv_str ws; 1025 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv; 1026 1027 keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen; 1028 1029 for (i = 0; i < 4; i++) { 1030 memset(&ws, 0, sizeof(ws)); 1031 ws.wi_len = (keylen > 5) ? 8 : 4; 1032 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i; 1033 memcpy(ws.wi_str, 1034 &wk->wi_keys[i].wi_keydat, keylen); 1035 error = wi_write_record(sc, 1036 (struct wi_ltv_gen *)&ws); 1037 if (error) 1038 return error; 1039 } 1040 return 0; 1041 } 1042 case WI_RID_AUTH_CNTL: 1043 p2ltv.wi_type = WI_RID_AUTH_CNTL; 1044 p2ltv.wi_len = 2; 1045 if (le16toh(ltv->wi_val) == 1) 1046 p2ltv.wi_val = htole16(0x01); 1047 else if (le16toh(ltv->wi_val) == 2) 1048 p2ltv.wi_val = htole16(0x02); 1049 ltv = &p2ltv; 1050 break; 1051 1052 case WI_RID_ROAMING_MODE: 1053 if (sc->sc_firmware_type == WI_INTERSIL) 1054 break; 1055 /* not supported */ 1056 return 0; 1057 1058 case WI_RID_MICROWAVE_OVEN: 1059 /* not supported */ 1060 return 0; 1061 } 1062 } 1063 1064 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) 1065 return(EIO); 1066 1067 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len); 1068 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type); 1069 1070 /* Write data */ 1071 ptr = <v->wi_val; 1072 if (ltv->wi_len > 1) 1073 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1); 1074 1075 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type)) 1076 return(EIO); 1077 1078 return(0); 1079 } 1080 1081 static int wi_seek(sc, id, off, chan) 1082 struct wi_softc *sc; 1083 int id, off, chan; 1084 { 1085 int i; 1086 int selreg, offreg; 1087 int status; 1088 1089 switch (chan) { 1090 case WI_BAP0: 1091 selreg = WI_SEL0; 1092 offreg = WI_OFF0; 1093 break; 1094 case WI_BAP1: 1095 selreg = WI_SEL1; 1096 offreg = WI_OFF1; 1097 break; 1098 default: 1099 printf("%s: invalid data path: %x\n", 1100 sc->sc_dev.dv_xname, chan); 1101 return(EIO); 1102 } 1103 1104 CSR_WRITE_2(sc, selreg, id); 1105 CSR_WRITE_2(sc, offreg, off); 1106 1107 for (i = 0; i < WI_TIMEOUT; i++) { 1108 status = CSR_READ_2(sc, offreg); 1109 if (!(status & (WI_OFF_BUSY|WI_OFF_ERR))) 1110 break; 1111 } 1112 1113 if (i == WI_TIMEOUT) { 1114 printf("%s: timeout in wi_seek to %x/%x; last status %x\n", 1115 sc->sc_dev.dv_xname, id, off, status); 1116 return(ETIMEDOUT); 1117 } 1118 return(0); 1119 } 1120 1121 static int wi_read_data(sc, id, off, buf, len) 1122 struct wi_softc *sc; 1123 int id, off; 1124 caddr_t buf; 1125 int len; 1126 { 1127 u_int16_t *ptr; 1128 1129 if (wi_seek(sc, id, off, WI_BAP1)) 1130 return(EIO); 1131 1132 ptr = (u_int16_t *)buf; 1133 CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2); 1134 1135 return(0); 1136 } 1137 1138 /* 1139 * According to the comments in the HCF Light code, there is a bug in 1140 * the Hermes (or possibly in certain Hermes firmware revisions) where 1141 * the chip's internal autoincrement counter gets thrown off during 1142 * data writes: the autoincrement is missed, causing one data word to 1143 * be overwritten and subsequent words to be written to the wrong memory 1144 * locations. The end result is that we could end up transmitting bogus 1145 * frames without realizing it. The workaround for this is to write a 1146 * couple of extra guard words after the end of the transfer, then 1147 * attempt to read then back. If we fail to locate the guard words where 1148 * we expect them, we preform the transfer over again. 1149 */ 1150 static int wi_write_data(sc, id, off, buf, len) 1151 struct wi_softc *sc; 1152 int id, off; 1153 caddr_t buf; 1154 int len; 1155 { 1156 u_int16_t *ptr; 1157 1158 #ifdef WI_HERMES_AUTOINC_WAR 1159 again: 1160 #endif 1161 1162 if (wi_seek(sc, id, off, WI_BAP0)) 1163 return(EIO); 1164 1165 ptr = (u_int16_t *)buf; 1166 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2); 1167 1168 #ifdef WI_HERMES_AUTOINC_WAR 1169 CSR_WRITE_2(sc, WI_DATA0, 0x1234); 1170 CSR_WRITE_2(sc, WI_DATA0, 0x5678); 1171 1172 if (wi_seek(sc, id, off + len, WI_BAP0)) 1173 return(EIO); 1174 1175 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 || 1176 CSR_READ_2(sc, WI_DATA0) != 0x5678) 1177 goto again; 1178 #endif 1179 1180 return(0); 1181 } 1182 1183 /* 1184 * Allocate a region of memory inside the NIC and zero 1185 * it out. 1186 */ 1187 static int wi_alloc_nicmem(sc, len, id) 1188 struct wi_softc *sc; 1189 int len; 1190 int *id; 1191 { 1192 int i; 1193 1194 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) { 1195 printf("%s: failed to allocate %d bytes on NIC\n", 1196 sc->sc_dev.dv_xname, len); 1197 return(ENOMEM); 1198 } 1199 1200 for (i = 0; i < WI_TIMEOUT; i++) { 1201 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) 1202 break; 1203 } 1204 1205 if (i == WI_TIMEOUT) { 1206 printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname); 1207 return(ETIMEDOUT); 1208 } 1209 1210 *id = CSR_READ_2(sc, WI_ALLOC_FID); 1211 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); 1212 1213 if (wi_seek(sc, *id, 0, WI_BAP0)) { 1214 printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname); 1215 return(EIO); 1216 } 1217 1218 for (i = 0; i < len / 2; i++) 1219 CSR_WRITE_2(sc, WI_DATA0, 0); 1220 1221 return(0); 1222 } 1223 1224 static void wi_setmulti(sc) 1225 struct wi_softc *sc; 1226 { 1227 struct ifnet *ifp; 1228 int i = 0; 1229 struct wi_ltv_mcast mcast; 1230 struct ether_multi *enm; 1231 struct ether_multistep estep; 1232 struct ethercom *ec = &sc->sc_ethercom; 1233 1234 ifp = &sc->sc_ethercom.ec_if; 1235 1236 if ((ifp->if_flags & IFF_PROMISC) != 0) { 1237 allmulti: 1238 ifp->if_flags |= IFF_ALLMULTI; 1239 memset((char *)&mcast, 0, sizeof(mcast)); 1240 mcast.wi_type = WI_RID_MCAST_LIST; 1241 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1; 1242 1243 wi_write_record(sc, (struct wi_ltv_gen *)&mcast); 1244 return; 1245 } 1246 1247 i = 0; 1248 ETHER_FIRST_MULTI(estep, ec, enm); 1249 while (enm != NULL) { 1250 /* Punt on ranges or too many multicast addresses. */ 1251 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 1252 ETHER_ADDR_LEN) != 0 || 1253 i >= 16) 1254 goto allmulti; 1255 1256 memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo, 1257 ETHER_ADDR_LEN); 1258 i++; 1259 ETHER_NEXT_MULTI(estep, enm); 1260 } 1261 1262 ifp->if_flags &= ~IFF_ALLMULTI; 1263 mcast.wi_type = WI_RID_MCAST_LIST; 1264 mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1; 1265 wi_write_record(sc, (struct wi_ltv_gen *)&mcast); 1266 } 1267 1268 static int 1269 wi_setdef(sc, wreq) 1270 struct wi_softc *sc; 1271 struct wi_req *wreq; 1272 { 1273 struct sockaddr_dl *sdl; 1274 struct ifnet *ifp; 1275 int error = 0; 1276 1277 ifp = &sc->sc_ethercom.ec_if; 1278 1279 switch(wreq->wi_type) { 1280 case WI_RID_MAC_NODE: 1281 sdl = (struct sockaddr_dl *)ifp->if_sadl; 1282 memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val, 1283 ETHER_ADDR_LEN); 1284 memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN); 1285 break; 1286 case WI_RID_PORTTYPE: 1287 error = wi_sync_media(sc, le16toh(wreq->wi_val[0]), sc->wi_tx_rate); 1288 break; 1289 case WI_RID_TX_RATE: 1290 error = wi_sync_media(sc, sc->wi_ptype, le16toh(wreq->wi_val[0])); 1291 break; 1292 case WI_RID_MAX_DATALEN: 1293 sc->wi_max_data_len = le16toh(wreq->wi_val[0]); 1294 break; 1295 case WI_RID_RTS_THRESH: 1296 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]); 1297 break; 1298 case WI_RID_SYSTEM_SCALE: 1299 sc->wi_ap_density = le16toh(wreq->wi_val[0]); 1300 break; 1301 case WI_RID_CREATE_IBSS: 1302 if (sc->sc_firmware_type != WI_INTERSIL) 1303 sc->wi_create_ibss = le16toh(wreq->wi_val[0]); 1304 break; 1305 case WI_RID_OWN_CHNL: 1306 sc->wi_channel = le16toh(wreq->wi_val[0]); 1307 break; 1308 case WI_RID_NODENAME: 1309 error = wi_set_ssid(&sc->wi_nodeid, 1310 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0])); 1311 break; 1312 case WI_RID_DESIRED_SSID: 1313 error = wi_set_ssid(&sc->wi_netid, 1314 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0])); 1315 break; 1316 case WI_RID_OWN_SSID: 1317 error = wi_set_ssid(&sc->wi_ibssid, 1318 (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0])); 1319 break; 1320 case WI_RID_PM_ENABLED: 1321 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]); 1322 break; 1323 case WI_RID_MICROWAVE_OVEN: 1324 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]); 1325 break; 1326 case WI_RID_MAX_SLEEP: 1327 sc->wi_max_sleep = le16toh(wreq->wi_val[0]); 1328 break; 1329 case WI_RID_AUTH_CNTL: 1330 sc->wi_authtype = le16toh(wreq->wi_val[0]); 1331 break; 1332 case WI_RID_ROAMING_MODE: 1333 sc->wi_roaming = le16toh(wreq->wi_val[0]); 1334 break; 1335 case WI_RID_ENCRYPTION: 1336 sc->wi_use_wep = le16toh(wreq->wi_val[0]); 1337 break; 1338 case WI_RID_TX_CRYPT_KEY: 1339 sc->wi_tx_key = le16toh(wreq->wi_val[0]); 1340 break; 1341 case WI_RID_DEFLT_CRYPT_KEYS: 1342 memcpy((char *)&sc->wi_keys, (char *)wreq, 1343 sizeof(struct wi_ltv_keys)); 1344 break; 1345 default: 1346 error = EINVAL; 1347 break; 1348 } 1349 1350 return (error); 1351 } 1352 1353 static int 1354 wi_getdef(sc, wreq) 1355 struct wi_softc *sc; 1356 struct wi_req *wreq; 1357 { 1358 struct sockaddr_dl *sdl; 1359 struct ifnet *ifp; 1360 int error = 0; 1361 1362 ifp = &sc->sc_ethercom.ec_if; 1363 1364 wreq->wi_len = 2; /* XXX */ 1365 switch (wreq->wi_type) { 1366 case WI_RID_MAC_NODE: 1367 wreq->wi_len += ETHER_ADDR_LEN / 2 - 1; 1368 sdl = (struct sockaddr_dl *)ifp->if_sadl; 1369 memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN); 1370 memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN); 1371 break; 1372 case WI_RID_PORTTYPE: 1373 wreq->wi_val[0] = htole16(sc->wi_ptype); 1374 break; 1375 case WI_RID_TX_RATE: 1376 wreq->wi_val[0] = htole16(sc->wi_tx_rate); 1377 break; 1378 case WI_RID_MAX_DATALEN: 1379 wreq->wi_val[0] = htole16(sc->wi_max_data_len); 1380 break; 1381 case WI_RID_RTS_THRESH: 1382 wreq->wi_val[0] = htole16(sc->wi_rts_thresh); 1383 break; 1384 case WI_RID_SYSTEM_SCALE: 1385 wreq->wi_val[0] = htole16(sc->wi_ap_density); 1386 break; 1387 case WI_RID_CREATE_IBSS: 1388 if (sc->sc_firmware_type != WI_INTERSIL) 1389 wreq->wi_val[0] = htole16(sc->wi_create_ibss); 1390 break; 1391 case WI_RID_OWN_CHNL: 1392 wreq->wi_val[0] = htole16(sc->wi_channel); 1393 break; 1394 case WI_RID_NODENAME: 1395 wi_request_fill_ssid(wreq, &sc->wi_nodeid); 1396 break; 1397 case WI_RID_DESIRED_SSID: 1398 wi_request_fill_ssid(wreq, &sc->wi_netid); 1399 break; 1400 case WI_RID_OWN_SSID: 1401 wi_request_fill_ssid(wreq, &sc->wi_ibssid); 1402 break; 1403 case WI_RID_PM_ENABLED: 1404 wreq->wi_val[0] = htole16(sc->wi_pm_enabled); 1405 break; 1406 case WI_RID_MICROWAVE_OVEN: 1407 wreq->wi_val[0] = htole16(sc->wi_mor_enabled); 1408 break; 1409 case WI_RID_MAX_SLEEP: 1410 wreq->wi_val[0] = htole16(sc->wi_max_sleep); 1411 break; 1412 case WI_RID_AUTH_CNTL: 1413 wreq->wi_val[0] = htole16(sc->wi_authtype); 1414 break; 1415 case WI_RID_ROAMING_MODE: 1416 wreq->wi_val[0] = htole16(sc->wi_roaming); 1417 break; 1418 case WI_RID_WEP_AVAIL: 1419 wreq->wi_val[0] = htole16(sc->wi_has_wep); 1420 break; 1421 case WI_RID_ENCRYPTION: 1422 wreq->wi_val[0] = htole16(sc->wi_use_wep); 1423 break; 1424 case WI_RID_TX_CRYPT_KEY: 1425 wreq->wi_val[0] = htole16(sc->wi_tx_key); 1426 break; 1427 case WI_RID_DEFLT_CRYPT_KEYS: 1428 wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1; 1429 memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys)); 1430 break; 1431 default: 1432 #if 0 1433 error = EIO; 1434 #else 1435 #ifdef WI_DEBUG 1436 printf("%s: wi_getdef: unknown request %d\n", 1437 sc->sc_dev.dv_xname, wreq->wi_type); 1438 #endif 1439 #endif 1440 break; 1441 } 1442 1443 return (error); 1444 } 1445 1446 static int 1447 wi_ioctl(ifp, command, data) 1448 struct ifnet *ifp; 1449 u_long command; 1450 caddr_t data; 1451 { 1452 int s, error = 0; 1453 int len; 1454 struct wi_softc *sc = ifp->if_softc; 1455 struct wi_req wreq; 1456 struct ifreq *ifr; 1457 struct proc *p = curproc; 1458 struct ieee80211_nwid nwid; 1459 1460 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) 1461 return (ENXIO); 1462 1463 s = splnet(); 1464 1465 ifr = (struct ifreq *)data; 1466 switch (command) { 1467 case SIOCSIFADDR: 1468 case SIOCGIFADDR: 1469 case SIOCSIFMTU: 1470 error = ether_ioctl(ifp, command, data); 1471 break; 1472 case SIOCSIFFLAGS: 1473 if (ifp->if_flags & IFF_UP) { 1474 if (ifp->if_flags & IFF_RUNNING && 1475 ifp->if_flags & IFF_PROMISC && 1476 !(sc->wi_if_flags & IFF_PROMISC)) { 1477 WI_SETVAL(WI_RID_PROMISC, 1); 1478 } else if (ifp->if_flags & IFF_RUNNING && 1479 !(ifp->if_flags & IFF_PROMISC) && 1480 sc->wi_if_flags & IFF_PROMISC) { 1481 WI_SETVAL(WI_RID_PROMISC, 0); 1482 } 1483 wi_init(ifp); 1484 } else { 1485 if (ifp->if_flags & IFF_RUNNING) { 1486 wi_stop(ifp, 0); 1487 } 1488 } 1489 sc->wi_if_flags = ifp->if_flags; 1490 1491 if (!(ifp->if_flags & IFF_UP)) { 1492 if (sc->sc_enabled) { 1493 if (sc->sc_disable) 1494 (*sc->sc_disable)(sc); 1495 sc->sc_enabled = 0; 1496 ifp->if_flags &= ~IFF_RUNNING; 1497 } 1498 } 1499 error = 0; 1500 break; 1501 case SIOCADDMULTI: 1502 case SIOCDELMULTI: 1503 error = (command == SIOCADDMULTI) ? 1504 ether_addmulti(ifr, &sc->sc_ethercom) : 1505 ether_delmulti(ifr, &sc->sc_ethercom); 1506 if (error == ENETRESET) { 1507 if (sc->sc_enabled != 0) { 1508 /* 1509 * Multicast list has changed. Set the 1510 * hardware filter accordingly. 1511 */ 1512 wi_setmulti(sc); 1513 } 1514 error = 0; 1515 } 1516 break; 1517 case SIOCSIFMEDIA: 1518 case SIOCGIFMEDIA: 1519 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command); 1520 break; 1521 case SIOCGWAVELAN: 1522 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1523 if (error) 1524 break; 1525 if (wreq.wi_type == WI_RID_IFACE_STATS) { 1526 memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats, 1527 sizeof(sc->wi_stats)); 1528 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1; 1529 } else if (wreq.wi_type == WI_RID_READ_APS) { 1530 if (sc->wi_scanning) { 1531 error = EINPROGRESS; 1532 break; 1533 } else { 1534 len = sc->wi_naps * sizeof(struct wi_apinfo); 1535 len = len > WI_MAX_DATALEN ? WI_MAX_DATALEN : len; 1536 len = len / sizeof(struct wi_apinfo); 1537 memcpy((char *)&wreq.wi_val, (char *)&len, sizeof(len)); 1538 memcpy((char *)&wreq.wi_val + sizeof(len), 1539 (char *)&sc->wi_aps, 1540 len * sizeof(struct wi_apinfo)); 1541 } 1542 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) { 1543 /* For non-root user, return all-zeroes keys */ 1544 if (suser(p->p_ucred, &p->p_acflag)) 1545 memset((char *)&wreq, 0, 1546 sizeof(struct wi_ltv_keys)); 1547 else 1548 memcpy((char *)&wreq, (char *)&sc->wi_keys, 1549 sizeof(struct wi_ltv_keys)); 1550 } else { 1551 if (sc->sc_enabled == 0) 1552 error = wi_getdef(sc, &wreq); 1553 else if (wreq.wi_len > WI_MAX_DATALEN) 1554 error = EINVAL; 1555 else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) 1556 error = EINVAL; 1557 } 1558 if (error == 0) 1559 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 1560 break; 1561 case SIOCSWAVELAN: 1562 error = suser(p->p_ucred, &p->p_acflag); 1563 if (error) 1564 break; 1565 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1566 if (error) 1567 break; 1568 if (wreq.wi_type == WI_RID_IFACE_STATS) { 1569 if (sc->sc_enabled) 1570 wi_inquire(sc); 1571 break; 1572 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) { 1573 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val, 1574 wreq.wi_len); 1575 } else if (wreq.wi_type == WI_RID_SCAN_APS) { 1576 if (wreq.wi_len != 4) { 1577 error = EINVAL; 1578 break; 1579 } 1580 if (!sc->wi_scanning) { 1581 switch (sc->sc_firmware_type) { 1582 case WI_LUCENT: 1583 break; 1584 case WI_INTERSIL: 1585 wreq.wi_type = WI_RID_SCAN_REQ; 1586 error = wi_write_record(sc, 1587 (struct wi_ltv_gen *)&wreq); 1588 break; 1589 case WI_SYMBOL: 1590 /* 1591 * XXX only supported on 3.x ? 1592 */ 1593 wreq.wi_type = WI_RID_BCAST_SCAN_REQ; 1594 wreq.wi_val[0] = 1595 BSCAN_BCAST | BSCAN_ONETIME; 1596 wreq.wi_len = 2; 1597 error = wi_write_record(sc, 1598 (struct wi_ltv_gen *)&wreq); 1599 break; 1600 } 1601 if (!error) { 1602 sc->wi_scanning = 1; 1603 callout_reset(&sc->wi_scan_sh, hz * 1, 1604 wi_wait_scan, sc); 1605 } 1606 } 1607 } else { 1608 if (wreq.wi_len > WI_MAX_DATALEN) 1609 error = EINVAL; 1610 else if (sc->sc_enabled != 0) 1611 error = wi_write_record(sc, 1612 (struct wi_ltv_gen *)&wreq); 1613 if (error == 0) 1614 error = wi_setdef(sc, &wreq); 1615 if (error == 0 && sc->sc_enabled != 0) 1616 /* Reinitialize WaveLAN. */ 1617 wi_init(ifp); 1618 } 1619 break; 1620 case SIOCG80211NWID: 1621 if (sc->sc_enabled == 0) { 1622 /* Return the desired ID */ 1623 error = copyout(&sc->wi_netid, ifr->ifr_data, 1624 sizeof(sc->wi_netid)); 1625 } else { 1626 wreq.wi_type = WI_RID_CURRENT_SSID; 1627 wreq.wi_len = WI_MAX_DATALEN; 1628 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) || 1629 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) 1630 error = EINVAL; 1631 else { 1632 wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1], 1633 le16toh(wreq.wi_val[0])); 1634 error = copyout(&nwid, ifr->ifr_data, 1635 sizeof(nwid)); 1636 } 1637 } 1638 break; 1639 case SIOCS80211NWID: 1640 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid)); 1641 if (error != 0) 1642 break; 1643 if (nwid.i_len > IEEE80211_NWID_LEN) { 1644 error = EINVAL; 1645 break; 1646 } 1647 if (sc->wi_netid.i_len == nwid.i_len && 1648 memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0) 1649 break; 1650 wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len); 1651 if (sc->sc_enabled != 0) 1652 /* Reinitialize WaveLAN. */ 1653 wi_init(ifp); 1654 break; 1655 case SIOCS80211NWKEY: 1656 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data); 1657 break; 1658 case SIOCG80211NWKEY: 1659 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data); 1660 break; 1661 case SIOCS80211POWER: 1662 error = wi_set_pm(sc, (struct ieee80211_power *)data); 1663 break; 1664 case SIOCG80211POWER: 1665 error = wi_get_pm(sc, (struct ieee80211_power *)data); 1666 break; 1667 1668 default: 1669 error = EINVAL; 1670 break; 1671 } 1672 1673 splx(s); 1674 return (error); 1675 } 1676 1677 static int 1678 wi_init(ifp) 1679 struct ifnet *ifp; 1680 { 1681 struct wi_softc *sc = ifp->if_softc; 1682 struct wi_req wreq; 1683 struct wi_ltv_macaddr mac; 1684 int error, id = 0, wasenabled; 1685 1686 wasenabled = sc->sc_enabled; 1687 if (!sc->sc_enabled) { 1688 if ((error = (*sc->sc_enable)(sc)) != 0) 1689 goto out; 1690 sc->sc_enabled = 1; 1691 } 1692 1693 wi_stop(ifp, 0); 1694 /* Symbol firmware cannot be initialized more than once */ 1695 if (!(sc->sc_firmware_type == WI_SYMBOL && wasenabled)) 1696 wi_reset(sc); 1697 1698 /* Program max data length. */ 1699 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len); 1700 1701 /* Enable/disable IBSS creation. */ 1702 if (sc->sc_firmware_type != WI_INTERSIL) 1703 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss); 1704 1705 /* Set the port type. */ 1706 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype); 1707 1708 /* Program the RTS/CTS threshold. */ 1709 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh); 1710 1711 /* Program the TX rate */ 1712 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate); 1713 1714 /* Access point density */ 1715 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density); 1716 1717 /* Power Management Enabled */ 1718 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled); 1719 1720 /* Power Managment Max Sleep */ 1721 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep); 1722 1723 /* Roaming type */ 1724 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming); 1725 1726 /* Specify the IBSS name */ 1727 wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid); 1728 1729 /* Specify the network name */ 1730 wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid); 1731 1732 /* Specify the frequency to use */ 1733 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel); 1734 1735 /* Program the nodename. */ 1736 wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid); 1737 1738 /* Set our MAC address. */ 1739 mac.wi_len = 4; 1740 mac.wi_type = WI_RID_MAC_NODE; 1741 memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN); 1742 wi_write_record(sc, (struct wi_ltv_gen *)&mac); 1743 1744 /* Initialize promisc mode. */ 1745 if (ifp->if_flags & IFF_PROMISC) { 1746 WI_SETVAL(WI_RID_PROMISC, 1); 1747 } else { 1748 WI_SETVAL(WI_RID_PROMISC, 0); 1749 } 1750 1751 /* Configure WEP. */ 1752 if (sc->wi_has_wep) { 1753 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep); 1754 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key); 1755 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1; 1756 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS; 1757 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys); 1758 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) { 1759 /* 1760 * ONLY HWB3163 EVAL-CARD Firmware version 1761 * less than 0.8 variant2 1762 * 1763 * If promiscuous mode disable, Prism2 chip 1764 * does not work with WEP . 1765 * It is under investigation for details. 1766 * (ichiro@netbsd.org) 1767 */ 1768 if (sc->sc_firmware_type == WI_INTERSIL && 1769 sc->sc_sta_firmware_ver < 802 ) { 1770 /* firm ver < 0.8 variant 2 */ 1771 WI_SETVAL(WI_RID_PROMISC, 1); 1772 } 1773 WI_SETVAL(WI_RID_AUTH_CNTL, sc->wi_authtype); 1774 } 1775 } 1776 1777 /* Set multicast filter. */ 1778 wi_setmulti(sc); 1779 1780 /* Enable desired port */ 1781 wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0); 1782 1783 /* scanning variable is modal, therefore reinit to OFF, in case it was on. */ 1784 sc->wi_scanning=0; 1785 sc->wi_naps=0; 1786 1787 if ((error = wi_alloc_nicmem(sc, 1788 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) { 1789 printf("%s: tx buffer allocation failed\n", 1790 sc->sc_dev.dv_xname); 1791 goto out; 1792 } 1793 sc->wi_tx_data_id = id; 1794 1795 if ((error = wi_alloc_nicmem(sc, 1796 1518 + sizeof(struct wi_frame) + 8, &id)) != 0) { 1797 printf("%s: mgmt. buffer allocation failed\n", 1798 sc->sc_dev.dv_xname); 1799 goto out; 1800 } 1801 sc->wi_tx_mgmt_id = id; 1802 1803 /* Enable interrupts */ 1804 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); 1805 1806 ifp->if_flags |= IFF_RUNNING; 1807 ifp->if_flags &= ~IFF_OACTIVE; 1808 1809 callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc); 1810 1811 out: 1812 if (error) { 1813 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1814 ifp->if_timer = 0; 1815 printf("%s: interface not running\n", sc->sc_dev.dv_xname); 1816 } 1817 return (error); 1818 } 1819 1820 static void 1821 wi_start(ifp) 1822 struct ifnet *ifp; 1823 { 1824 struct wi_softc *sc; 1825 struct mbuf *m0; 1826 struct wi_frame tx_frame; 1827 struct ether_header *eh; 1828 int id; 1829 1830 sc = ifp->if_softc; 1831 1832 if (ifp->if_flags & IFF_OACTIVE) 1833 return; 1834 1835 IFQ_DEQUEUE(&ifp->if_snd, m0); 1836 if (m0 == NULL) 1837 return; 1838 1839 memset((char *)&tx_frame, 0, sizeof(tx_frame)); 1840 id = sc->wi_tx_data_id; 1841 eh = mtod(m0, struct ether_header *); 1842 1843 /* 1844 * Use RFC1042 encoding for IP and ARP datagrams, 1845 * 802.3 for anything else. 1846 */ 1847 if (ntohs(eh->ether_type) == ETHERTYPE_IP || 1848 ntohs(eh->ether_type) == ETHERTYPE_ARP || 1849 ntohs(eh->ether_type) == ETHERTYPE_REVARP || 1850 ntohs(eh->ether_type) == ETHERTYPE_IPV6) { 1851 memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost, 1852 ETHER_ADDR_LEN); 1853 memcpy((char *)&tx_frame.wi_addr2, (char *)&eh->ether_shost, 1854 ETHER_ADDR_LEN); 1855 memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost, 1856 ETHER_ADDR_LEN); 1857 memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost, 1858 ETHER_ADDR_LEN); 1859 1860 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len - WI_SNAPHDR_LEN); 1861 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA); 1862 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0); 1863 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1); 1864 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN); 1865 tx_frame.wi_type = eh->ether_type; 1866 1867 m_copydata(m0, sizeof(struct ether_header), 1868 m0->m_pkthdr.len - sizeof(struct ether_header), 1869 (caddr_t)&sc->wi_txbuf); 1870 1871 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, 1872 sizeof(struct wi_frame)); 1873 wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf, 1874 (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2); 1875 } else { 1876 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len); 1877 1878 m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf); 1879 1880 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, 1881 sizeof(struct wi_frame)); 1882 wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf, 1883 m0->m_pkthdr.len + 2); 1884 } 1885 1886 #if NBPFILTER > 0 1887 /* 1888 * If there's a BPF listener, bounce a copy of 1889 * this frame to him. 1890 */ 1891 if (ifp->if_bpf) 1892 bpf_mtap(ifp->if_bpf, m0); 1893 #endif 1894 1895 m_freem(m0); 1896 1897 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) 1898 printf("%s: xmit failed\n", sc->sc_dev.dv_xname); 1899 1900 ifp->if_flags |= IFF_OACTIVE; 1901 1902 /* 1903 * Set a timeout in case the chip goes out to lunch. 1904 */ 1905 ifp->if_timer = 5; 1906 1907 return; 1908 } 1909 1910 static int 1911 wi_mgmt_xmit(sc, data, len) 1912 struct wi_softc *sc; 1913 caddr_t data; 1914 int len; 1915 { 1916 struct wi_frame tx_frame; 1917 int id; 1918 struct wi_80211_hdr *hdr; 1919 caddr_t dptr; 1920 1921 hdr = (struct wi_80211_hdr *)data; 1922 dptr = data + sizeof(struct wi_80211_hdr); 1923 1924 memset((char *)&tx_frame, 0, sizeof(tx_frame)); 1925 id = sc->wi_tx_mgmt_id; 1926 1927 memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr, 1928 sizeof(struct wi_80211_hdr)); 1929 1930 tx_frame.wi_dat_len = htole16(len - WI_SNAPHDR_LEN); 1931 tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN); 1932 1933 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame)); 1934 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr, 1935 (len - sizeof(struct wi_80211_hdr)) + 2); 1936 1937 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) { 1938 printf("%s: xmit failed\n", sc->sc_dev.dv_xname); 1939 return(EIO); 1940 } 1941 1942 return(0); 1943 } 1944 1945 static void 1946 wi_stop(ifp, disable) 1947 struct ifnet *ifp; 1948 { 1949 struct wi_softc *sc = ifp->if_softc; 1950 1951 CSR_WRITE_2(sc, WI_INT_EN, 0); 1952 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0); 1953 1954 callout_stop(&sc->wi_inquire_ch); 1955 callout_stop(&sc->wi_scan_sh); 1956 1957 if (disable) { 1958 if (sc->sc_enabled) { 1959 if (sc->sc_disable) 1960 (*sc->sc_disable)(sc); 1961 sc->sc_enabled = 0; 1962 } 1963 } 1964 1965 ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING); 1966 ifp->if_timer = 0; 1967 } 1968 1969 static void 1970 wi_watchdog(ifp) 1971 struct ifnet *ifp; 1972 { 1973 struct wi_softc *sc; 1974 1975 sc = ifp->if_softc; 1976 1977 printf("%s: device timeout\n", sc->sc_dev.dv_xname); 1978 1979 wi_init(ifp); 1980 1981 ifp->if_oerrors++; 1982 1983 return; 1984 } 1985 1986 void 1987 wi_shutdown(sc) 1988 struct wi_softc *sc; 1989 { 1990 int s; 1991 1992 s = splnet(); 1993 if (sc->sc_enabled) { 1994 if (sc->sc_disable) 1995 (*sc->sc_disable)(sc); 1996 sc->sc_enabled = 0; 1997 } 1998 splx(s); 1999 } 2000 2001 int 2002 wi_activate(self, act) 2003 struct device *self; 2004 enum devact act; 2005 { 2006 struct wi_softc *sc = (struct wi_softc *)self; 2007 int rv = 0, s; 2008 2009 s = splnet(); 2010 switch (act) { 2011 case DVACT_ACTIVATE: 2012 rv = EOPNOTSUPP; 2013 break; 2014 2015 case DVACT_DEACTIVATE: 2016 if_deactivate(&sc->sc_ethercom.ec_if); 2017 break; 2018 } 2019 splx(s); 2020 return (rv); 2021 } 2022 2023 static void 2024 wi_get_id(sc) 2025 struct wi_softc *sc; 2026 { 2027 struct wi_ltv_ver ver; 2028 struct wi_card_ident *id; 2029 2030 /* getting chip identity */ 2031 memset(&ver, 0, sizeof(ver)); 2032 ver.wi_type = WI_RID_CARD_ID; 2033 ver.wi_len = 5; 2034 wi_read_record(sc, (struct wi_ltv_gen *)&ver); 2035 printf("%s: using ", sc->sc_dev.dv_xname); 2036 2037 sc->sc_firmware_type = WI_NOTYPE; 2038 for (id = wi_card_ident; id->card_name != NULL; id++) { 2039 if (le16toh(ver.wi_ver[0]) == id->card_id) { 2040 printf("%s", id->card_name); 2041 sc->sc_firmware_type = id->firm_type; 2042 break; 2043 } 2044 } 2045 if (sc->sc_firmware_type == WI_NOTYPE) { 2046 if (le16toh(ver.wi_ver[0]) & 0x8000) { 2047 printf("Unknown PRISM2 chip"); 2048 sc->sc_firmware_type = WI_INTERSIL; 2049 } else { 2050 printf("Unknown Lucent chip"); 2051 sc->sc_firmware_type = WI_LUCENT; 2052 } 2053 } 2054 2055 /* get primary firmware version (Only Prism chips) */ 2056 if (sc->sc_firmware_type != WI_LUCENT) { 2057 memset(&ver, 0, sizeof(ver)); 2058 ver.wi_type = WI_RID_PRI_IDENTITY; 2059 ver.wi_len = 5; 2060 wi_read_record(sc, (struct wi_ltv_gen *)&ver); 2061 LE16TOH(ver.wi_ver[1]); 2062 LE16TOH(ver.wi_ver[2]); 2063 LE16TOH(ver.wi_ver[3]); 2064 sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 + 2065 ver.wi_ver[3] * 100 + ver.wi_ver[1]; 2066 } 2067 2068 /* get station firmware version */ 2069 memset(&ver, 0, sizeof(ver)); 2070 ver.wi_type = WI_RID_STA_IDENTITY; 2071 ver.wi_len = 5; 2072 wi_read_record(sc, (struct wi_ltv_gen *)&ver); 2073 LE16TOH(ver.wi_ver[1]); 2074 LE16TOH(ver.wi_ver[2]); 2075 LE16TOH(ver.wi_ver[3]); 2076 sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 + 2077 ver.wi_ver[3] * 100 + ver.wi_ver[1]; 2078 if (sc->sc_firmware_type == WI_INTERSIL && 2079 (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) { 2080 struct wi_ltv_str sver; 2081 char *p; 2082 2083 memset(&sver, 0, sizeof(sver)); 2084 sver.wi_type = WI_RID_SYMBOL_IDENTITY; 2085 sver.wi_len = 7; 2086 /* value should be the format like "V2.00-11" */ 2087 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 && 2088 *(p = (char *)sver.wi_str) >= 'A' && 2089 p[2] == '.' && p[5] == '-' && p[8] == '\0') { 2090 sc->sc_firmware_type = WI_SYMBOL; 2091 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 + 2092 (p[3] - '0') * 1000 + (p[4] - '0') * 100 + 2093 (p[6] - '0') * 10 + (p[7] - '0'); 2094 } 2095 } 2096 2097 printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname, 2098 sc->sc_firmware_type == WI_LUCENT ? "Lucent" : 2099 (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil")); 2100 if (sc->sc_firmware_type != WI_LUCENT) /* XXX */ 2101 printf("Primary (%u.%u.%u), ", sc->sc_pri_firmware_ver / 10000, 2102 (sc->sc_pri_firmware_ver % 10000) / 100, 2103 sc->sc_pri_firmware_ver % 100); 2104 printf("Station (%u.%u.%u)\n", 2105 sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100, 2106 sc->sc_sta_firmware_ver % 100); 2107 2108 return; 2109 } 2110 2111 int 2112 wi_detach(sc) 2113 struct wi_softc *sc; 2114 { 2115 struct ifnet *ifp = sc->sc_ifp; 2116 int s; 2117 2118 if (!sc->sc_attached) 2119 return (0); 2120 2121 s = splnet(); 2122 callout_stop(&sc->wi_inquire_ch); 2123 2124 /* Delete all remaining media. */ 2125 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); 2126 2127 ether_ifdetach(ifp); 2128 if_detach(ifp); 2129 if (sc->sc_enabled) { 2130 if (sc->sc_disable) 2131 (*sc->sc_disable)(sc); 2132 sc->sc_enabled = 0; 2133 } 2134 splx(s); 2135 return (0); 2136 } 2137 2138 void 2139 wi_power(sc, why) 2140 struct wi_softc *sc; 2141 int why; 2142 { 2143 int s; 2144 2145 if (!sc->sc_enabled) 2146 return; 2147 2148 s = splnet(); 2149 switch (why) { 2150 case PWR_SUSPEND: 2151 case PWR_STANDBY: 2152 wi_stop(sc->sc_ifp, 0); 2153 if (sc->sc_enabled) { 2154 if (sc->sc_disable) 2155 (*sc->sc_disable)(sc); 2156 } 2157 break; 2158 case PWR_RESUME: 2159 sc->sc_enabled = 0; 2160 wi_init(sc->sc_ifp); 2161 (void)wi_intr(sc); 2162 break; 2163 case PWR_SOFTSUSPEND: 2164 case PWR_SOFTSTANDBY: 2165 case PWR_SOFTRESUME: 2166 break; 2167 } 2168 splx(s); 2169 } 2170 2171 static int 2172 wi_set_ssid(ws, id, len) 2173 struct ieee80211_nwid *ws; 2174 u_int8_t *id; 2175 int len; 2176 { 2177 2178 if (len > IEEE80211_NWID_LEN) 2179 return (EINVAL); 2180 ws->i_len = len; 2181 memcpy(ws->i_nwid, id, len); 2182 return (0); 2183 } 2184 2185 static void 2186 wi_request_fill_ssid(wreq, ws) 2187 struct wi_req *wreq; 2188 struct ieee80211_nwid *ws; 2189 { 2190 int len = ws->i_len; 2191 2192 memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val)); 2193 wreq->wi_val[0] = htole16(len); 2194 wreq->wi_len = roundup(len, 2) / 2 + 2; 2195 memcpy(&wreq->wi_val[1], ws->i_nwid, len); 2196 } 2197 2198 static int 2199 wi_write_ssid(sc, type, wreq, ws) 2200 struct wi_softc *sc; 2201 int type; 2202 struct wi_req *wreq; 2203 struct ieee80211_nwid *ws; 2204 { 2205 2206 wreq->wi_type = type; 2207 wi_request_fill_ssid(wreq, ws); 2208 return (wi_write_record(sc, (struct wi_ltv_gen *)wreq)); 2209 } 2210 2211 static int 2212 wi_sync_media(sc, ptype, txrate) 2213 struct wi_softc *sc; 2214 int ptype; 2215 int txrate; 2216 { 2217 int media = sc->sc_media.ifm_cur->ifm_media; 2218 int options = IFM_OPTIONS(media); 2219 int subtype; 2220 2221 switch (txrate) { 2222 case 1: 2223 subtype = IFM_IEEE80211_DS1; 2224 break; 2225 case 2: 2226 subtype = IFM_IEEE80211_DS2; 2227 break; 2228 case 3: 2229 subtype = IFM_AUTO; 2230 break; 2231 case 5: 2232 subtype = IFM_IEEE80211_DS5; 2233 break; 2234 case 11: 2235 subtype = IFM_IEEE80211_DS11; 2236 break; 2237 default: 2238 subtype = IFM_MANUAL; /* Unable to represent */ 2239 break; 2240 } 2241 switch (ptype) { 2242 case WI_PORTTYPE_ADHOC: 2243 options |= IFM_IEEE80211_ADHOC; 2244 break; 2245 case WI_PORTTYPE_BSS: 2246 options &= ~IFM_IEEE80211_ADHOC; 2247 break; 2248 default: 2249 subtype = IFM_MANUAL; /* Unable to represent */ 2250 break; 2251 } 2252 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options, 2253 IFM_INST(media)); 2254 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL) 2255 return (EINVAL); 2256 ifmedia_set(&sc->sc_media, media); 2257 sc->wi_ptype = ptype; 2258 sc->wi_tx_rate = txrate; 2259 return (0); 2260 } 2261 2262 static int 2263 wi_media_change(ifp) 2264 struct ifnet *ifp; 2265 { 2266 struct wi_softc *sc = ifp->if_softc; 2267 int otype = sc->wi_ptype; 2268 int orate = sc->wi_tx_rate; 2269 2270 if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0) 2271 sc->wi_ptype = WI_PORTTYPE_ADHOC; 2272 else 2273 sc->wi_ptype = WI_PORTTYPE_BSS; 2274 2275 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) { 2276 case IFM_IEEE80211_DS1: 2277 sc->wi_tx_rate = 1; 2278 break; 2279 case IFM_IEEE80211_DS2: 2280 sc->wi_tx_rate = 2; 2281 break; 2282 case IFM_AUTO: 2283 sc->wi_tx_rate = 3; 2284 break; 2285 case IFM_IEEE80211_DS5: 2286 sc->wi_tx_rate = 5; 2287 break; 2288 case IFM_IEEE80211_DS11: 2289 sc->wi_tx_rate = 11; 2290 break; 2291 } 2292 2293 if (sc->sc_enabled != 0) { 2294 if (otype != sc->wi_ptype || 2295 orate != sc->wi_tx_rate) 2296 wi_init(ifp); 2297 } 2298 2299 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media); 2300 2301 return (0); 2302 } 2303 2304 static void 2305 wi_media_status(ifp, imr) 2306 struct ifnet *ifp; 2307 struct ifmediareq *imr; 2308 { 2309 struct wi_softc *sc = ifp->if_softc; 2310 2311 if (sc->sc_enabled == 0) { 2312 imr->ifm_active = IFM_IEEE80211|IFM_NONE; 2313 imr->ifm_status = 0; 2314 return; 2315 } 2316 2317 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media; 2318 imr->ifm_status = IFM_AVALID|IFM_ACTIVE; 2319 } 2320 2321 static int 2322 wi_set_nwkey(sc, nwkey) 2323 struct wi_softc *sc; 2324 struct ieee80211_nwkey *nwkey; 2325 { 2326 int i, error; 2327 size_t len; 2328 struct wi_req wreq; 2329 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq; 2330 2331 if (!sc->wi_has_wep) 2332 return ENODEV; 2333 if (nwkey->i_defkid <= 0 || 2334 nwkey->i_defkid > IEEE80211_WEP_NKID) 2335 return EINVAL; 2336 memcpy(wk, &sc->wi_keys, sizeof(*wk)); 2337 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2338 if (nwkey->i_key[i].i_keydat == NULL) 2339 continue; 2340 len = nwkey->i_key[i].i_keylen; 2341 if (len > sizeof(wk->wi_keys[i].wi_keydat)) 2342 return EINVAL; 2343 error = copyin(nwkey->i_key[i].i_keydat, 2344 wk->wi_keys[i].wi_keydat, len); 2345 if (error) 2346 return error; 2347 wk->wi_keys[i].wi_keylen = htole16(len); 2348 } 2349 2350 wk->wi_len = (sizeof(*wk) / 2) + 1; 2351 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS; 2352 if (sc->sc_enabled != 0) { 2353 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); 2354 if (error) 2355 return error; 2356 } 2357 error = wi_setdef(sc, &wreq); 2358 if (error) 2359 return error; 2360 2361 wreq.wi_len = 2; 2362 wreq.wi_type = WI_RID_TX_CRYPT_KEY; 2363 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1); 2364 if (sc->sc_enabled != 0) { 2365 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); 2366 if (error) 2367 return error; 2368 } 2369 error = wi_setdef(sc, &wreq); 2370 if (error) 2371 return error; 2372 2373 wreq.wi_type = WI_RID_ENCRYPTION; 2374 wreq.wi_val[0] = htole16(nwkey->i_wepon); 2375 if (sc->sc_enabled != 0) { 2376 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); 2377 if (error) 2378 return error; 2379 } 2380 error = wi_setdef(sc, &wreq); 2381 if (error) 2382 return error; 2383 2384 if (sc->sc_enabled != 0) 2385 wi_init(&sc->sc_ethercom.ec_if); 2386 return 0; 2387 } 2388 2389 static int 2390 wi_get_nwkey(sc, nwkey) 2391 struct wi_softc *sc; 2392 struct ieee80211_nwkey *nwkey; 2393 { 2394 int i, len, error; 2395 struct wi_ltv_keys *wk = &sc->wi_keys; 2396 2397 if (!sc->wi_has_wep) 2398 return ENODEV; 2399 nwkey->i_wepon = sc->wi_use_wep; 2400 nwkey->i_defkid = sc->wi_tx_key + 1; 2401 2402 /* do not show any keys to non-root user */ 2403 error = suser(curproc->p_ucred, &curproc->p_acflag); 2404 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2405 if (nwkey->i_key[i].i_keydat == NULL) 2406 continue; 2407 /* error holds results of suser() for the first time */ 2408 if (error) 2409 return error; 2410 len = le16toh(wk->wi_keys[i].wi_keylen); 2411 if (nwkey->i_key[i].i_keylen < len) 2412 return ENOSPC; 2413 nwkey->i_key[i].i_keylen = len; 2414 error = copyout(wk->wi_keys[i].wi_keydat, 2415 nwkey->i_key[i].i_keydat, len); 2416 if (error) 2417 return error; 2418 } 2419 return 0; 2420 } 2421 2422 static int 2423 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power) 2424 { 2425 2426 sc->wi_pm_enabled = power->i_enabled; 2427 sc->wi_max_sleep = power->i_maxsleep; 2428 2429 if (sc->sc_enabled) 2430 return (wi_init(&sc->sc_ethercom.ec_if)); 2431 2432 return (0); 2433 } 2434 2435 static int 2436 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power) 2437 { 2438 2439 power->i_enabled = sc->wi_pm_enabled; 2440 power->i_maxsleep = sc->wi_max_sleep; 2441 2442 return (0); 2443 } 2444