1 /* $NetBSD: wi.c,v 1.130 2003/06/19 06:16:36 rh 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.130 2003/06/19 06:16:36 rh 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_llc.h> 93 #include <net/if_media.h> 94 #include <net/if_ether.h> 95 #include <net/if_ieee80211.h> 96 97 #if NBPFILTER > 0 98 #include <net/bpf.h> 99 #include <net/bpfdesc.h> 100 #endif 101 102 #include <machine/bus.h> 103 104 #include <dev/ic/wi_ieee.h> 105 #include <dev/ic/wireg.h> 106 #include <dev/ic/wivar.h> 107 108 static int wi_init(struct ifnet *); 109 static void wi_stop(struct ifnet *, int); 110 static void wi_start(struct ifnet *); 111 static int wi_reset(struct wi_softc *); 112 static void wi_watchdog(struct ifnet *); 113 static int wi_ioctl(struct ifnet *, u_long, caddr_t); 114 static int wi_media_change(struct ifnet *); 115 static void wi_media_status(struct ifnet *, struct ifmediareq *); 116 117 static void wi_rx_intr(struct wi_softc *); 118 static void wi_tx_intr(struct wi_softc *); 119 static void wi_tx_ex_intr(struct wi_softc *); 120 static void wi_info_intr(struct wi_softc *); 121 122 static int wi_get_cfg(struct ifnet *, u_long, caddr_t); 123 static int wi_set_cfg(struct ifnet *, u_long, caddr_t); 124 static int wi_write_txrate(struct wi_softc *); 125 static int wi_write_wep(struct wi_softc *); 126 static int wi_write_multi(struct wi_softc *); 127 static int wi_alloc_fid(struct wi_softc *, int, int *); 128 static void wi_read_nicid(struct wi_softc *); 129 static int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int); 130 131 static int wi_cmd(struct wi_softc *, int, int, int, int); 132 static int wi_seek_bap(struct wi_softc *, int, int); 133 static int wi_read_bap(struct wi_softc *, int, int, void *, int); 134 static int wi_write_bap(struct wi_softc *, int, int, void *, int); 135 static int wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int); 136 static int wi_read_rid(struct wi_softc *, int, void *, int *); 137 static int wi_write_rid(struct wi_softc *, int, void *, int); 138 139 static int wi_newstate(void *, enum ieee80211_state); 140 static int wi_set_tim(struct ieee80211com *, int, int); 141 142 static int wi_scan_ap(struct wi_softc *, u_int16_t, u_int16_t); 143 static void wi_scan_result(struct wi_softc *, int, int); 144 145 static void wi_dump_pkt(struct wi_frame *, struct ieee80211_node *, int rssi); 146 147 static inline int 148 wi_write_val(struct wi_softc *sc, int rid, u_int16_t val) 149 { 150 151 val = htole16(val); 152 return wi_write_rid(sc, rid, &val, sizeof(val)); 153 } 154 155 static struct timeval lasttxerror; /* time of last tx error msg */ 156 static int curtxeps = 0; /* current tx error msgs/sec */ 157 static int wi_txerate = 0; /* tx error rate: max msgs/sec */ 158 159 #ifdef WI_DEBUG 160 int wi_debug = 0; 161 162 #define DPRINTF(X) if (wi_debug) printf X 163 #define DPRINTF2(X) if (wi_debug > 1) printf X 164 #define IFF_DUMPPKTS(_ifp) \ 165 (((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) 166 #else 167 #define DPRINTF(X) 168 #define DPRINTF2(X) 169 #define IFF_DUMPPKTS(_ifp) 0 170 #endif 171 172 #define WI_INTRS (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO) 173 174 struct wi_card_ident 175 wi_card_ident[] = { 176 /* CARD_ID CARD_NAME FIRM_TYPE */ 177 { WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT }, 178 { WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT }, 179 { WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT }, 180 { WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL }, 181 { WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL }, 182 { WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL }, 183 { WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL }, 184 { WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL }, 185 { WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL }, 186 { WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL }, 187 { WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL }, 188 { WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL }, 189 { WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, 190 { WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, 191 { WI_NIC_3842_PCMCIA_ATM_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, 192 { WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, 193 { WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, 194 { WI_NIC_3842_MINI_ATM_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, 195 { WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, 196 { WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, 197 { WI_NIC_3842_PCI_ATM_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, 198 { WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL }, 199 { WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL }, 200 { WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL }, 201 { WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL }, 202 { 0, NULL, 0 }, 203 }; 204 205 int 206 wi_attach(struct wi_softc *sc) 207 { 208 struct ieee80211com *ic = &sc->sc_ic; 209 struct ifnet *ifp = &ic->ic_if; 210 int i, nrate, mword, buflen; 211 u_int8_t r; 212 u_int16_t val; 213 u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE]; 214 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { 215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 216 }; 217 int s; 218 219 s = splnet(); 220 221 /* Make sure interrupts are disabled. */ 222 CSR_WRITE_2(sc, WI_INT_EN, 0); 223 CSR_WRITE_2(sc, WI_EVENT_ACK, ~0); 224 225 sc->sc_invalid = 0; 226 227 /* Reset the NIC. */ 228 if (wi_reset(sc) != 0) { 229 sc->sc_invalid = 1; 230 splx(s); 231 return 1; 232 } 233 234 buflen = IEEE80211_ADDR_LEN; 235 if (wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen) != 0 || 236 IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) { 237 printf(" could not get mac address, attach failed\n"); 238 splx(s); 239 return 1; 240 } 241 242 printf(" 802.11 address %s\n", ether_sprintf(ic->ic_myaddr)); 243 244 /* Read NIC identification */ 245 wi_read_nicid(sc); 246 247 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 248 ifp->if_softc = sc; 249 ifp->if_start = wi_start; 250 ifp->if_ioctl = wi_ioctl; 251 ifp->if_watchdog = wi_watchdog; 252 ifp->if_init = wi_init; 253 ifp->if_stop = wi_stop; 254 ifp->if_flags = 255 IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST | IFF_NOTRAILERS; 256 IFQ_SET_READY(&ifp->if_snd); 257 258 ic->ic_phytype = IEEE80211_T_DS; 259 ic->ic_opmode = IEEE80211_M_STA; 260 ic->ic_flags = IEEE80211_F_HASPMGT | IEEE80211_F_HASAHDEMO; 261 ic->ic_state = IEEE80211_S_INIT; 262 ic->ic_newstate = wi_newstate; 263 ic->ic_set_tim = wi_set_tim; 264 ic->ic_max_aid = WI_MAX_AID; 265 266 /* Find available channel */ 267 buflen = sizeof(val); 268 if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0) 269 val = htole16(0x1fff); /* assume 1-11 */ 270 for (i = 0; i < 16; i++) { 271 if (isset((u_int8_t*)&val, i)) 272 setbit(ic->ic_chan_avail, i + 1); 273 } 274 275 sc->sc_dbm_adjust = 100; /* default */ 276 277 buflen = sizeof(val); 278 if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) && 279 wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0) { 280 sc->sc_dbm_adjust = le16toh(val); 281 } 282 283 /* Find default IBSS channel */ 284 buflen = sizeof(val); 285 if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) 286 ic->ic_ibss_chan = le16toh(val); 287 else { 288 /* use lowest available channel */ 289 for (i = 0; i < 16; i++) { 290 if (isset(ic->ic_chan_avail, i)) 291 break; 292 } 293 ic->ic_ibss_chan = i; 294 } 295 296 /* 297 * Set flags based on firmware version. 298 */ 299 switch (sc->sc_firmware_type) { 300 case WI_LUCENT: 301 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE; 302 #ifdef WI_HERMES_AUTOINC_WAR 303 /* XXX: not confirmed, but never seen for recent firmware */ 304 if (sc->sc_sta_firmware_ver < 40000) { 305 sc->sc_flags |= WI_FLAGS_BUG_AUTOINC; 306 } 307 #endif 308 if (sc->sc_sta_firmware_ver >= 60000) 309 sc->sc_flags |= WI_FLAGS_HAS_MOR; 310 if (sc->sc_sta_firmware_ver >= 60006) { 311 ic->ic_flags |= IEEE80211_F_HASIBSS; 312 ic->ic_flags |= IEEE80211_F_HASMONITOR; 313 } 314 sc->sc_ibss_port = 1; 315 break; 316 317 case WI_INTERSIL: 318 sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR; 319 sc->sc_flags |= WI_FLAGS_HAS_ROAMING; 320 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE; 321 if (sc->sc_sta_firmware_ver > 10101) 322 sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST; 323 if (sc->sc_sta_firmware_ver >= 800) { 324 if (sc->sc_sta_firmware_ver != 10402) 325 ic->ic_flags |= IEEE80211_F_HASHOSTAP; 326 ic->ic_flags |= IEEE80211_F_HASIBSS; 327 ic->ic_flags |= IEEE80211_F_HASMONITOR; 328 } 329 sc->sc_ibss_port = 0; 330 break; 331 332 case WI_SYMBOL: 333 sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY; 334 if (sc->sc_sta_firmware_ver >= 20000) 335 ic->ic_flags |= IEEE80211_F_HASIBSS; 336 sc->sc_ibss_port = 4; 337 break; 338 } 339 340 /* 341 * Find out if we support WEP on this card. 342 */ 343 buflen = sizeof(val); 344 if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 && 345 val != htole16(0)) 346 ic->ic_flags |= IEEE80211_F_HASWEP; 347 348 /* Find supported rates. */ 349 buflen = sizeof(ratebuf); 350 if (wi_read_rid(sc, WI_RID_DATA_RATES, ratebuf, &buflen) == 0) { 351 nrate = le16toh(*(u_int16_t *)ratebuf); 352 if (nrate > IEEE80211_RATE_SIZE) 353 nrate = IEEE80211_RATE_SIZE; 354 memcpy(ic->ic_sup_rates, ratebuf + 2, nrate); 355 } 356 buflen = sizeof(val); 357 358 sc->sc_max_datalen = 2304; 359 sc->sc_rts_thresh = 2347; 360 sc->sc_frag_thresh = 2346; 361 sc->sc_system_scale = 1; 362 sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN; 363 sc->sc_roaming_mode = 1; 364 365 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status); 366 printf("%s: supported rates: ", sc->sc_dev.dv_xname); 367 #define ADD(s, o) ifmedia_add(&sc->sc_media, \ 368 IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL) 369 ADD(IFM_AUTO, 0); 370 if (ic->ic_flags & IEEE80211_F_HASHOSTAP) 371 ADD(IFM_AUTO, IFM_IEEE80211_HOSTAP); 372 if (ic->ic_flags & IEEE80211_F_HASIBSS) 373 ADD(IFM_AUTO, IFM_IEEE80211_ADHOC); 374 if (ic->ic_flags & IEEE80211_F_HASMONITOR) 375 ADD(IFM_AUTO, IFM_IEEE80211_MONITOR); 376 ADD(IFM_AUTO, IFM_IEEE80211_ADHOC | IFM_FLAG0); 377 for (i = 0; i < nrate; i++) { 378 r = ic->ic_sup_rates[i]; 379 mword = ieee80211_rate2media(r, IEEE80211_T_DS); 380 if (mword == 0) 381 continue; 382 printf("%s%d%sMbps", (i != 0 ? " " : ""), 383 (r & IEEE80211_RATE_VAL) / 2, ((r & 0x1) != 0 ? ".5" : "")); 384 ADD(mword, 0); 385 if (ic->ic_flags & IEEE80211_F_HASHOSTAP) 386 ADD(mword, IFM_IEEE80211_HOSTAP); 387 if (ic->ic_flags & IEEE80211_F_HASIBSS) 388 ADD(mword, IFM_IEEE80211_ADHOC); 389 if (ic->ic_flags & IEEE80211_F_HASMONITOR) 390 ADD(mword, IFM_IEEE80211_MONITOR); 391 ADD(mword, IFM_IEEE80211_ADHOC | IFM_FLAG0); 392 } 393 printf("\n"); 394 ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0)); 395 #undef ADD 396 397 /* 398 * Call MI attach routines. 399 */ 400 401 if_attach(ifp); 402 ieee80211_ifattach(ifp); 403 404 /* Attach is successful. */ 405 sc->sc_attached = 1; 406 407 splx(s); 408 return 0; 409 } 410 411 int 412 wi_detach(struct wi_softc *sc) 413 { 414 struct ifnet *ifp = &sc->sc_ic.ic_if; 415 int s; 416 417 if (!sc->sc_attached) 418 return 0; 419 420 s = splnet(); 421 422 sc->sc_invalid = 1; 423 wi_stop(ifp, 1); 424 425 /* Delete all remaining media. */ 426 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); 427 428 ieee80211_ifdetach(ifp); 429 if_detach(ifp); 430 splx(s); 431 return 0; 432 } 433 434 #ifdef __NetBSD__ 435 int 436 wi_activate(struct device *self, enum devact act) 437 { 438 struct wi_softc *sc = (struct wi_softc *)self; 439 int rv = 0, s; 440 441 s = splnet(); 442 switch (act) { 443 case DVACT_ACTIVATE: 444 rv = EOPNOTSUPP; 445 break; 446 447 case DVACT_DEACTIVATE: 448 if_deactivate(&sc->sc_ic.ic_if); 449 break; 450 } 451 splx(s); 452 return rv; 453 } 454 455 void 456 wi_power(struct wi_softc *sc, int why) 457 { 458 struct ifnet *ifp = &sc->sc_ic.ic_if; 459 int s; 460 461 s = splnet(); 462 switch (why) { 463 case PWR_SUSPEND: 464 case PWR_STANDBY: 465 wi_stop(ifp, 1); 466 break; 467 case PWR_RESUME: 468 if (ifp->if_flags & IFF_UP) { 469 wi_init(ifp); 470 (void)wi_intr(sc); 471 } 472 break; 473 case PWR_SOFTSUSPEND: 474 case PWR_SOFTSTANDBY: 475 case PWR_SOFTRESUME: 476 break; 477 } 478 splx(s); 479 } 480 #endif /* __NetBSD__ */ 481 482 void 483 wi_shutdown(struct wi_softc *sc) 484 { 485 struct ifnet *ifp = &sc->sc_ic.ic_if; 486 487 if (sc->sc_attached) 488 wi_stop(ifp, 1); 489 } 490 491 int 492 wi_intr(void *arg) 493 { 494 int i; 495 struct wi_softc *sc = arg; 496 struct ifnet *ifp = &sc->sc_ic.ic_if; 497 u_int16_t status; 498 499 if (sc->sc_enabled == 0 || 500 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 || 501 (ifp->if_flags & IFF_RUNNING) == 0) 502 return 0; 503 504 if ((ifp->if_flags & IFF_UP) == 0) { 505 CSR_WRITE_2(sc, WI_INT_EN, 0); 506 CSR_WRITE_2(sc, WI_EVENT_ACK, ~0); 507 return 1; 508 } 509 510 /* This is superfluous on Prism, but Lucent breaks if we 511 * do not disable interrupts. 512 */ 513 CSR_WRITE_2(sc, WI_INT_EN, 0); 514 515 /* maximum 10 loops per interrupt */ 516 for (i = 0; i < 10; i++) { 517 /* 518 * Only believe a status bit when we enter wi_intr, or when 519 * the bit was "off" the last time through the loop. This is 520 * my strategy to avoid racing the hardware/firmware if I 521 * can re-read the event status register more quickly than 522 * it is updated. 523 */ 524 status = CSR_READ_2(sc, WI_EVENT_STAT); 525 if ((status & WI_INTRS) == 0) 526 break; 527 528 if (status & WI_EV_RX) 529 wi_rx_intr(sc); 530 531 if (status & WI_EV_ALLOC) 532 wi_tx_intr(sc); 533 534 if (status & WI_EV_TX_EXC) 535 wi_tx_ex_intr(sc); 536 537 if (status & WI_EV_INFO) 538 wi_info_intr(sc); 539 540 if ((ifp->if_flags & IFF_OACTIVE) == 0 && 541 (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 && 542 !IFQ_IS_EMPTY(&ifp->if_snd)) 543 wi_start(ifp); 544 } 545 546 /* re-enable interrupts */ 547 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); 548 549 return 1; 550 } 551 552 static int 553 wi_init(struct ifnet *ifp) 554 { 555 struct wi_softc *sc = ifp->if_softc; 556 struct ieee80211com *ic = &sc->sc_ic; 557 struct wi_joinreq join; 558 int i; 559 int error = 0, wasenabled; 560 561 DPRINTF(("wi_init: enabled %d\n", sc->sc_enabled)); 562 wasenabled = sc->sc_enabled; 563 if (!sc->sc_enabled) { 564 if ((error = (*sc->sc_enable)(sc)) != 0) 565 goto out; 566 sc->sc_enabled = 1; 567 } else 568 wi_stop(ifp, 0); 569 570 /* Symbol firmware cannot be initialized more than once */ 571 if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) 572 if ((error = wi_reset(sc)) != 0) 573 goto out; 574 575 /* common 802.11 configuration */ 576 ic->ic_flags &= ~IEEE80211_F_IBSSON; 577 sc->sc_flags &= ~WI_FLAGS_OUTRANGE; 578 switch (ic->ic_opmode) { 579 case IEEE80211_M_STA: 580 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS); 581 break; 582 case IEEE80211_M_IBSS: 583 wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port); 584 ic->ic_flags |= IEEE80211_F_IBSSON; 585 sc->sc_syn_timer = 5; 586 ifp->if_timer = 1; 587 break; 588 case IEEE80211_M_AHDEMO: 589 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC); 590 break; 591 case IEEE80211_M_HOSTAP: 592 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP); 593 break; 594 case IEEE80211_M_MONITOR: 595 if (sc->sc_firmware_type == WI_LUCENT) 596 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC); 597 wi_cmd(sc, WI_CMD_TEST | (WI_TEST_MONITOR << 8), 0, 0, 0); 598 break; 599 } 600 601 /* Intersil interprets this RID as joining ESS even in IBSS mode */ 602 if (sc->sc_firmware_type == WI_LUCENT && 603 (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0) 604 wi_write_val(sc, WI_RID_CREATE_IBSS, 1); 605 else 606 wi_write_val(sc, WI_RID_CREATE_IBSS, 0); 607 wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval); 608 wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid, 609 ic->ic_des_esslen); 610 wi_write_val(sc, WI_RID_OWN_CHNL, ic->ic_ibss_chan); 611 wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen); 612 IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl)); 613 wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN); 614 wi_write_val(sc, WI_RID_PM_ENABLED, 615 (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0); 616 617 /* not yet common 802.11 configuration */ 618 wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen); 619 wi_write_val(sc, WI_RID_RTS_THRESH, sc->sc_rts_thresh); 620 if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) 621 wi_write_val(sc, WI_RID_FRAG_THRESH, sc->sc_frag_thresh); 622 623 /* driver specific 802.11 configuration */ 624 if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) 625 wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale); 626 if (sc->sc_flags & WI_FLAGS_HAS_ROAMING) 627 wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode); 628 if (sc->sc_flags & WI_FLAGS_HAS_MOR) 629 wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven); 630 wi_write_txrate(sc); 631 wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen); 632 633 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 634 sc->sc_firmware_type == WI_INTERSIL) { 635 wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_lintval); 636 wi_write_val(sc, WI_RID_BASIC_RATE, 0x03); /* 1, 2 */ 637 wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */ 638 wi_write_val(sc, WI_RID_DTIM_PERIOD, 1); 639 } 640 641 /* 642 * Initialize promisc mode. 643 * Being in the Host-AP mode causes a great 644 * deal of pain if primisc mode is set. 645 * Therefore we avoid confusing the firmware 646 * and always reset promisc mode in Host-AP 647 * mode. Host-AP sees all the packets anyway. 648 */ 649 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 650 (ifp->if_flags & IFF_PROMISC) != 0) { 651 wi_write_val(sc, WI_RID_PROMISC, 1); 652 } else { 653 wi_write_val(sc, WI_RID_PROMISC, 0); 654 } 655 656 /* Configure WEP. */ 657 if (ic->ic_flags & IEEE80211_F_HASWEP) 658 wi_write_wep(sc); 659 660 /* Set multicast filter. */ 661 wi_write_multi(sc); 662 663 if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) { 664 sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame); 665 if (sc->sc_firmware_type == WI_SYMBOL) 666 sc->sc_buflen = 1585; /* XXX */ 667 for (i = 0; i < WI_NTXBUF; i++) { 668 error = wi_alloc_fid(sc, sc->sc_buflen, 669 &sc->sc_txd[i].d_fid); 670 if (error) { 671 printf("%s: tx buffer allocation failed\n", 672 sc->sc_dev.dv_xname); 673 goto out; 674 } 675 DPRINTF2(("wi_init: txbuf %d allocated %x\n", i, 676 sc->sc_txd[i].d_fid)); 677 sc->sc_txd[i].d_len = 0; 678 } 679 } 680 sc->sc_txcur = sc->sc_txnext = 0; 681 682 /* Enable desired port */ 683 wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0); 684 ifp->if_flags |= IFF_RUNNING; 685 ifp->if_flags &= ~IFF_OACTIVE; 686 if (ic->ic_opmode == IEEE80211_M_AHDEMO || 687 ic->ic_opmode == IEEE80211_M_MONITOR || 688 ic->ic_opmode == IEEE80211_M_HOSTAP) 689 wi_newstate(sc, IEEE80211_S_RUN); 690 691 /* Enable interrupts */ 692 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); 693 694 if (!wasenabled && 695 ic->ic_opmode == IEEE80211_M_HOSTAP && 696 sc->sc_firmware_type == WI_INTERSIL) { 697 /* XXX: some card need to be re-enabled for hostap */ 698 wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0); 699 wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0); 700 } 701 702 if (ic->ic_opmode == IEEE80211_M_STA && 703 ((ic->ic_flags & IEEE80211_F_DESBSSID) || 704 ic->ic_des_chan != IEEE80211_CHAN_ANY)) { 705 memset(&join, 0, sizeof(join)); 706 if (ic->ic_flags & IEEE80211_F_DESBSSID) 707 IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid); 708 if (ic->ic_des_chan != IEEE80211_CHAN_ANY) 709 join.wi_chan = htole16(ic->ic_des_chan); 710 /* Lucent firmware does not support the JOIN RID. */ 711 if (sc->sc_firmware_type != WI_LUCENT) 712 wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join)); 713 } 714 715 out: 716 if (error) { 717 printf("%s: interface not running\n", sc->sc_dev.dv_xname); 718 wi_stop(ifp, 0); 719 } 720 DPRINTF(("wi_init: return %d\n", error)); 721 return error; 722 } 723 724 static void 725 wi_stop(struct ifnet *ifp, int disable) 726 { 727 struct wi_softc *sc = ifp->if_softc; 728 int s; 729 730 if (!sc->sc_enabled) 731 return; 732 733 s = splnet(); 734 735 DPRINTF(("wi_stop: disable %d\n", disable)); 736 737 ieee80211_new_state(ifp, IEEE80211_S_INIT, -1); 738 if (!sc->sc_invalid) { 739 CSR_WRITE_2(sc, WI_INT_EN, 0); 740 wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0); 741 } 742 743 sc->sc_tx_timer = 0; 744 sc->sc_scan_timer = 0; 745 sc->sc_syn_timer = 0; 746 sc->sc_false_syns = 0; 747 sc->sc_naps = 0; 748 ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING); 749 ifp->if_timer = 0; 750 751 if (disable) { 752 if (sc->sc_disable) 753 (*sc->sc_disable)(sc); 754 sc->sc_enabled = 0; 755 } 756 splx(s); 757 } 758 759 static void 760 wi_start(struct ifnet *ifp) 761 { 762 struct wi_softc *sc = ifp->if_softc; 763 struct ieee80211com *ic = &sc->sc_ic; 764 struct ieee80211_node *ni; 765 struct ieee80211_frame *wh; 766 struct mbuf *m0; 767 struct wi_frame frmhdr; 768 int cur, fid, off; 769 770 if (!sc->sc_enabled || sc->sc_invalid) 771 return; 772 if (sc->sc_flags & WI_FLAGS_OUTRANGE) 773 return; 774 775 memset(&frmhdr, 0, sizeof(frmhdr)); 776 cur = sc->sc_txnext; 777 for (;;) { 778 if (!IF_IS_EMPTY(&ic->ic_mgtq)) { 779 if (sc->sc_txd[cur].d_len != 0) { 780 ifp->if_flags |= IFF_OACTIVE; 781 break; 782 } 783 IF_DEQUEUE(&ic->ic_mgtq, m0); 784 m_copydata(m0, 4, ETHER_ADDR_LEN * 2, 785 (caddr_t)&frmhdr.wi_ehdr); 786 frmhdr.wi_ehdr.ether_type = 0; 787 wh = mtod(m0, struct ieee80211_frame *); 788 } else if (!IF_IS_EMPTY(&ic->ic_pwrsaveq)) { 789 struct llc *llc; 790 791 /* 792 * Should these packets be processed after the 793 * regular packets or before? Since they are being 794 * probed for, they are probably less time critical 795 * than other packets, but, on the other hand, 796 * we want the power saving nodes to go back to 797 * sleep as quickly as possible to save power... 798 */ 799 800 if (ic->ic_state != IEEE80211_S_RUN) 801 break; 802 803 if (sc->sc_txd[cur].d_len != 0) { 804 ifp->if_flags |= IFF_OACTIVE; 805 break; 806 } 807 IF_DEQUEUE(&ic->ic_pwrsaveq, m0); 808 wh = mtod(m0, struct ieee80211_frame *); 809 llc = (struct llc *) (wh + 1); 810 m_copydata(m0, 4, ETHER_ADDR_LEN * 2, 811 (caddr_t)&frmhdr.wi_ehdr); 812 frmhdr.wi_ehdr.ether_type = llc->llc_snap.ether_type; 813 } else { 814 if (ic->ic_state != IEEE80211_S_RUN) 815 break; 816 IFQ_POLL(&ifp->if_snd, m0); 817 if (m0 == NULL) 818 break; 819 if (sc->sc_txd[cur].d_len != 0) { 820 ifp->if_flags |= IFF_OACTIVE; 821 break; 822 } 823 IFQ_DEQUEUE(&ifp->if_snd, m0); 824 ifp->if_opackets++; 825 m_copydata(m0, 0, ETHER_HDR_LEN, 826 (caddr_t)&frmhdr.wi_ehdr); 827 #if NBPFILTER > 0 828 if (ifp->if_bpf) 829 bpf_mtap(ifp->if_bpf, m0); 830 #endif 831 832 if ((m0 = ieee80211_encap(ifp, m0)) == NULL) { 833 ifp->if_oerrors++; 834 continue; 835 } 836 wh = mtod(m0, struct ieee80211_frame *); 837 if (ic->ic_flags & IEEE80211_F_WEPON) 838 wh->i_fc[1] |= IEEE80211_FC1_WEP; 839 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 840 !IEEE80211_IS_MULTICAST(wh->i_addr1) && 841 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 842 IEEE80211_FC0_TYPE_DATA) { 843 ni = ieee80211_find_node(ic, wh->i_addr1); 844 if (ni == NULL || ni->ni_associd == 0) { 845 m_freem(m0); 846 ifp->if_oerrors++; 847 continue; 848 } 849 if (ni->ni_pwrsave & IEEE80211_PS_SLEEP) { 850 ieee80211_pwrsave(ic, ni, m0); 851 continue; 852 } 853 } 854 } 855 #if NBPFILTER > 0 856 if (ic->ic_rawbpf) 857 bpf_mtap(ic->ic_rawbpf, m0); 858 #endif 859 frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX); 860 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 861 (wh->i_fc[1] & IEEE80211_FC1_WEP)) { 862 if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) { 863 ifp->if_oerrors++; 864 continue; 865 } 866 frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT); 867 } 868 m_copydata(m0, 0, sizeof(struct ieee80211_frame), 869 (caddr_t)&frmhdr.wi_whdr); 870 m_adj(m0, sizeof(struct ieee80211_frame)); 871 frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len); 872 #if NBPFILTER > 0 873 if (sc->sc_drvbpf) { 874 struct mbuf mb; 875 876 M_COPY_PKTHDR(&mb, m0); 877 mb.m_data = (caddr_t)&frmhdr; 878 mb.m_len = sizeof(frmhdr); 879 mb.m_next = m0; 880 mb.m_pkthdr.len += mb.m_len; 881 bpf_mtap(sc->sc_drvbpf, &mb); 882 } 883 #endif 884 if (IFF_DUMPPKTS(ifp)) 885 wi_dump_pkt(&frmhdr, ni, -1); 886 fid = sc->sc_txd[cur].d_fid; 887 off = sizeof(frmhdr); 888 if (wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0 || 889 wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0) { 890 ifp->if_oerrors++; 891 m_freem(m0); 892 continue; 893 } 894 m_freem(m0); 895 sc->sc_txd[cur].d_len = off; 896 if (sc->sc_txcur == cur) { 897 if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) { 898 printf("%s: xmit failed\n", 899 sc->sc_dev.dv_xname); 900 sc->sc_txd[cur].d_len = 0; 901 continue; 902 } 903 sc->sc_tx_timer = 5; 904 ifp->if_timer = 1; 905 } 906 sc->sc_txnext = cur = (cur + 1) % WI_NTXBUF; 907 } 908 } 909 910 911 static int 912 wi_reset(struct wi_softc *sc) 913 { 914 int i, error; 915 916 DPRINTF(("wi_reset\n")); 917 918 if (sc->sc_reset) 919 (*sc->sc_reset)(sc); 920 921 error = 0; 922 for (i = 0; i < 5; i++) { 923 DELAY(20*1000); /* XXX: way too long! */ 924 if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0) 925 break; 926 } 927 if (error) { 928 printf("%s: init failed\n", sc->sc_dev.dv_xname); 929 return error; 930 } 931 CSR_WRITE_2(sc, WI_INT_EN, 0); 932 CSR_WRITE_2(sc, WI_EVENT_ACK, ~0); 933 934 /* Calibrate timer. */ 935 wi_write_val(sc, WI_RID_TICK_TIME, 0); 936 return 0; 937 } 938 939 static void 940 wi_watchdog(struct ifnet *ifp) 941 { 942 struct wi_softc *sc = ifp->if_softc; 943 944 ifp->if_timer = 0; 945 if (!sc->sc_enabled) 946 return; 947 948 if (sc->sc_tx_timer) { 949 if (--sc->sc_tx_timer == 0) { 950 printf("%s: device timeout\n", ifp->if_xname); 951 ifp->if_oerrors++; 952 wi_init(ifp); 953 return; 954 } 955 ifp->if_timer = 1; 956 } 957 958 if (sc->sc_scan_timer) { 959 if (--sc->sc_scan_timer <= WI_SCAN_WAIT - WI_SCAN_INQWAIT && 960 sc->sc_firmware_type == WI_INTERSIL) { 961 DPRINTF(("wi_watchdog: inquire scan\n")); 962 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0); 963 } 964 if (sc->sc_scan_timer) 965 ifp->if_timer = 1; 966 } 967 968 if (sc->sc_syn_timer) { 969 if (--sc->sc_syn_timer == 0) { 970 DPRINTF2(("%s: %d false syns\n", 971 sc->sc_dev.dv_xname, sc->sc_false_syns)); 972 sc->sc_false_syns = 0; 973 ieee80211_new_state(ifp, IEEE80211_S_RUN, -1); 974 sc->sc_syn_timer = 5; 975 } 976 ifp->if_timer = 1; 977 } 978 979 /* TODO: rate control */ 980 ieee80211_watchdog(ifp); 981 } 982 983 static int 984 wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 985 { 986 struct wi_softc *sc = ifp->if_softc; 987 struct ieee80211com *ic = &sc->sc_ic; 988 struct ifreq *ifr = (struct ifreq *)data; 989 int s, error = 0; 990 991 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) 992 return ENXIO; 993 994 s = splnet(); 995 996 switch (cmd) { 997 case SIOCSIFFLAGS: 998 /* 999 * Can't do promisc and hostap at the same time. If all that's 1000 * changing is the promisc flag, try to short-circuit a call to 1001 * wi_init() by just setting PROMISC in the hardware. 1002 */ 1003 if (ifp->if_flags & IFF_UP) { 1004 if (sc->sc_enabled) { 1005 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 1006 (ifp->if_flags & IFF_PROMISC) != 0) 1007 wi_write_val(sc, WI_RID_PROMISC, 1); 1008 else 1009 wi_write_val(sc, WI_RID_PROMISC, 0); 1010 } else 1011 error = wi_init(ifp); 1012 } else if (sc->sc_enabled) 1013 wi_stop(ifp, 1); 1014 break; 1015 case SIOCSIFMEDIA: 1016 case SIOCGIFMEDIA: 1017 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 1018 break; 1019 case SIOCADDMULTI: 1020 case SIOCDELMULTI: 1021 error = (cmd == SIOCADDMULTI) ? 1022 ether_addmulti(ifr, &sc->sc_ic.ic_ec) : 1023 ether_delmulti(ifr, &sc->sc_ic.ic_ec); 1024 if (error == ENETRESET) { 1025 if (sc->sc_enabled) { 1026 /* do not rescan */ 1027 error = wi_write_multi(sc); 1028 } else 1029 error = 0; 1030 } 1031 break; 1032 case SIOCGIFGENERIC: 1033 error = wi_get_cfg(ifp, cmd, data); 1034 break; 1035 case SIOCSIFGENERIC: 1036 error = suser(curproc->p_ucred, &curproc->p_acflag); 1037 if (error) 1038 break; 1039 error = wi_set_cfg(ifp, cmd, data); 1040 if (error == ENETRESET) { 1041 if (sc->sc_enabled) 1042 error = wi_init(ifp); 1043 else 1044 error = 0; 1045 } 1046 break; 1047 case SIOCS80211BSSID: 1048 if (sc->sc_firmware_type == WI_LUCENT) { 1049 error = ENODEV; 1050 break; 1051 } 1052 /* fall through */ 1053 default: 1054 error = ieee80211_ioctl(ifp, cmd, data); 1055 if (error == ENETRESET) { 1056 if (sc->sc_enabled) 1057 error = wi_init(ifp); 1058 else 1059 error = 0; 1060 } 1061 break; 1062 } 1063 splx(s); 1064 return error; 1065 } 1066 1067 static int 1068 wi_media_change(struct ifnet *ifp) 1069 { 1070 struct wi_softc *sc = ifp->if_softc; 1071 struct ieee80211com *ic = &sc->sc_ic; 1072 struct ifmedia_entry *ime; 1073 enum ieee80211_opmode newmode; 1074 int i, rate, error = 0; 1075 1076 ime = sc->sc_media.ifm_cur; 1077 if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) { 1078 i = -1; 1079 } else { 1080 rate = ieee80211_media2rate(ime->ifm_media, IEEE80211_T_DS); 1081 if (rate == 0) 1082 return EINVAL; 1083 for (i = 0; i < IEEE80211_RATE_SIZE; i++) { 1084 if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) == rate) 1085 break; 1086 } 1087 if (i == IEEE80211_RATE_SIZE) 1088 return EINVAL; 1089 } 1090 if (ic->ic_fixed_rate != i) { 1091 ic->ic_fixed_rate = i; 1092 error = ENETRESET; 1093 } 1094 1095 if ((ime->ifm_media & IFM_IEEE80211_ADHOC) && 1096 (ime->ifm_media & IFM_FLAG0)) 1097 newmode = IEEE80211_M_AHDEMO; 1098 else if (ime->ifm_media & IFM_IEEE80211_ADHOC) 1099 newmode = IEEE80211_M_IBSS; 1100 else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) 1101 newmode = IEEE80211_M_HOSTAP; 1102 else if (ime->ifm_media & IFM_IEEE80211_MONITOR) 1103 newmode = IEEE80211_M_MONITOR; 1104 else 1105 newmode = IEEE80211_M_STA; 1106 if (ic->ic_opmode != newmode) { 1107 ic->ic_opmode = newmode; 1108 error = ENETRESET; 1109 } 1110 if (error == ENETRESET) { 1111 if (sc->sc_enabled) 1112 error = wi_init(ifp); 1113 else 1114 error = 0; 1115 } 1116 ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media); 1117 1118 return error; 1119 } 1120 1121 static void 1122 wi_media_status(struct ifnet *ifp, struct ifmediareq *imr) 1123 { 1124 struct wi_softc *sc = ifp->if_softc; 1125 struct ieee80211com *ic = &sc->sc_ic; 1126 u_int16_t val; 1127 int rate, len; 1128 1129 if (sc->sc_enabled == 0) { 1130 imr->ifm_active = IFM_IEEE80211 | IFM_NONE; 1131 imr->ifm_status = 0; 1132 return; 1133 } 1134 1135 imr->ifm_status = IFM_AVALID; 1136 imr->ifm_active = IFM_IEEE80211; 1137 if (ic->ic_state == IEEE80211_S_RUN && 1138 (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0) 1139 imr->ifm_status |= IFM_ACTIVE; 1140 len = sizeof(val); 1141 if (wi_read_rid(sc, WI_RID_CUR_TX_RATE, &val, &len) != 0) 1142 rate = 0; 1143 else { 1144 /* convert to 802.11 rate */ 1145 rate = val * 2; 1146 if (sc->sc_firmware_type == WI_LUCENT) { 1147 if (rate == 10) 1148 rate = 11; /* 5.5Mbps */ 1149 } else { 1150 if (rate == 4*2) 1151 rate = 11; /* 5.5Mbps */ 1152 else if (rate == 8*2) 1153 rate = 22; /* 11Mbps */ 1154 } 1155 } 1156 imr->ifm_active |= ieee80211_rate2media(rate, IEEE80211_T_DS); 1157 switch (ic->ic_opmode) { 1158 case IEEE80211_M_STA: 1159 break; 1160 case IEEE80211_M_IBSS: 1161 imr->ifm_active |= IFM_IEEE80211_ADHOC; 1162 break; 1163 case IEEE80211_M_AHDEMO: 1164 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0; 1165 break; 1166 case IEEE80211_M_HOSTAP: 1167 imr->ifm_active |= IFM_IEEE80211_HOSTAP; 1168 break; 1169 case IEEE80211_M_MONITOR: 1170 imr->ifm_active |= IFM_IEEE80211_MONITOR; 1171 break; 1172 } 1173 } 1174 1175 static void 1176 wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN]) 1177 { 1178 struct ieee80211com *ic = &sc->sc_ic; 1179 struct ieee80211_node *ni = &ic->ic_bss; 1180 struct ifnet *ifp = &ic->ic_if; 1181 1182 if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid)) 1183 return; 1184 1185 DPRINTF(("wi_sync_bssid: bssid %s -> ", ether_sprintf(ni->ni_bssid))); 1186 DPRINTF(("%s ?\n", ether_sprintf(new_bssid))); 1187 1188 /* In promiscuous mode, the BSSID field is not a reliable 1189 * indicator of the firmware's BSSID. Damp spurious 1190 * change-of-BSSID indications. 1191 */ 1192 if ((ifp->if_flags & IFF_PROMISC) != 0 && 1193 sc->sc_false_syns >= WI_MAX_FALSE_SYNS) 1194 return; 1195 1196 ieee80211_new_state(ifp, IEEE80211_S_RUN, -1); 1197 } 1198 1199 static void 1200 wi_rx_intr(struct wi_softc *sc) 1201 { 1202 struct ieee80211com *ic = &sc->sc_ic; 1203 struct ifnet *ifp = &ic->ic_if; 1204 struct wi_frame frmhdr; 1205 struct mbuf *m; 1206 struct ieee80211_frame *wh; 1207 int fid, len, off, rssi; 1208 u_int8_t dir; 1209 u_int16_t status; 1210 u_int32_t rstamp; 1211 1212 fid = CSR_READ_2(sc, WI_RX_FID); 1213 1214 /* First read in the frame header */ 1215 if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) { 1216 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 1217 ifp->if_ierrors++; 1218 DPRINTF(("wi_rx_intr: read fid %x failed\n", fid)); 1219 return; 1220 } 1221 1222 if (IFF_DUMPPKTS(ifp)) 1223 wi_dump_pkt(&frmhdr, NULL, frmhdr.wi_rx_signal); 1224 1225 /* 1226 * Drop undecryptable or packets with receive errors here 1227 */ 1228 status = le16toh(frmhdr.wi_status); 1229 if (status & WI_STAT_ERRSTAT) { 1230 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 1231 ifp->if_ierrors++; 1232 DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status)); 1233 return; 1234 } 1235 rssi = frmhdr.wi_rx_signal; 1236 rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) | 1237 le16toh(frmhdr.wi_rx_tstamp1); 1238 1239 len = le16toh(frmhdr.wi_dat_len); 1240 off = ALIGN(sizeof(struct ieee80211_frame)); 1241 1242 /* Sometimes the PRISM2.x returns bogusly large frames. Except 1243 * in monitor mode, just throw them away. 1244 */ 1245 if (off + len > MCLBYTES) { 1246 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 1247 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 1248 ifp->if_ierrors++; 1249 DPRINTF(("wi_rx_intr: oversized packet\n")); 1250 return; 1251 } else 1252 len = 0; 1253 } 1254 1255 MGETHDR(m, M_DONTWAIT, MT_DATA); 1256 if (m == NULL) { 1257 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 1258 ifp->if_ierrors++; 1259 DPRINTF(("wi_rx_intr: MGET failed\n")); 1260 return; 1261 } 1262 if (off + len > MHLEN) { 1263 MCLGET(m, M_DONTWAIT); 1264 if ((m->m_flags & M_EXT) == 0) { 1265 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 1266 m_freem(m); 1267 ifp->if_ierrors++; 1268 DPRINTF(("wi_rx_intr: MCLGET failed\n")); 1269 return; 1270 } 1271 } 1272 1273 m->m_data += off - sizeof(struct ieee80211_frame); 1274 memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame)); 1275 wi_read_bap(sc, fid, sizeof(frmhdr), 1276 m->m_data + sizeof(struct ieee80211_frame), len); 1277 m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len; 1278 m->m_pkthdr.rcvif = ifp; 1279 1280 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 1281 1282 #if NBPFILTER > 0 1283 if (sc->sc_drvbpf) { 1284 struct mbuf mb; 1285 1286 M_COPY_PKTHDR(&mb, m); 1287 mb.m_data = (caddr_t)&frmhdr; 1288 frmhdr.wi_rx_signal -= sc->sc_dbm_adjust; 1289 frmhdr.wi_rx_silence -= sc->sc_dbm_adjust; 1290 mb.m_len = (char *)&frmhdr.wi_whdr - (char *)&frmhdr; 1291 mb.m_next = m; 1292 mb.m_pkthdr.len += mb.m_len; 1293 bpf_mtap(sc->sc_drvbpf, &mb); 1294 } 1295 #endif 1296 wh = mtod(m, struct ieee80211_frame *); 1297 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1298 /* 1299 * WEP is decrypted by hardware. Clear WEP bit 1300 * header for ieee80211_input(). 1301 */ 1302 wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 1303 } 1304 1305 /* synchronize driver's BSSID with firmware's BSSID */ 1306 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; 1307 if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS) 1308 wi_sync_bssid(sc, wh->i_addr3); 1309 1310 ieee80211_input(ifp, m, rssi, rstamp); 1311 } 1312 1313 static void 1314 wi_tx_ex_intr(struct wi_softc *sc) 1315 { 1316 struct ieee80211com *ic = &sc->sc_ic; 1317 struct ifnet *ifp = &ic->ic_if; 1318 struct wi_frame frmhdr; 1319 int fid; 1320 1321 fid = CSR_READ_2(sc, WI_TX_CMP_FID); 1322 /* Read in the frame header */ 1323 if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) == 0) { 1324 u_int16_t status = le16toh(frmhdr.wi_status); 1325 1326 /* 1327 * Spontaneous station disconnects appear as xmit 1328 * errors. Don't announce them and/or count them 1329 * as an output error. 1330 */ 1331 if ((status & WI_TXSTAT_DISCONNECT) == 0) { 1332 if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) { 1333 curtxeps = 0; 1334 printf("%s: tx failed", sc->sc_dev.dv_xname); 1335 if (status & WI_TXSTAT_RET_ERR) 1336 printf(", retry limit exceeded"); 1337 if (status & WI_TXSTAT_AGED_ERR) 1338 printf(", max transmit lifetime exceeded"); 1339 if (status & WI_TXSTAT_DISCONNECT) 1340 printf(", port disconnected"); 1341 if (status & WI_TXSTAT_FORM_ERR) 1342 printf(", invalid format (data len %u src %s)", 1343 le16toh(frmhdr.wi_dat_len), 1344 ether_sprintf(frmhdr.wi_ehdr.ether_shost)); 1345 if (status & ~0xf) 1346 printf(", status=0x%x", status); 1347 printf("\n"); 1348 } 1349 ifp->if_oerrors++; 1350 } else { 1351 DPRINTF(("port disconnected\n")); 1352 ifp->if_collisions++; /* XXX */ 1353 } 1354 } else 1355 DPRINTF(("wi_tx_ex_intr: read fid %x failed\n", fid)); 1356 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC); 1357 } 1358 1359 static void 1360 wi_tx_intr(struct wi_softc *sc) 1361 { 1362 struct ieee80211com *ic = &sc->sc_ic; 1363 struct ifnet *ifp = &ic->ic_if; 1364 int fid, cur; 1365 1366 fid = CSR_READ_2(sc, WI_ALLOC_FID); 1367 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); 1368 1369 cur = sc->sc_txcur; 1370 if (sc->sc_txd[cur].d_fid != fid) { 1371 printf("%s: bad alloc %x != %x, cur %d nxt %d\n", 1372 sc->sc_dev.dv_xname, fid, sc->sc_txd[cur].d_fid, cur, 1373 sc->sc_txnext); 1374 return; 1375 } 1376 sc->sc_tx_timer = 0; 1377 sc->sc_txd[cur].d_len = 0; 1378 sc->sc_txcur = cur = (cur + 1) % WI_NTXBUF; 1379 if (sc->sc_txd[cur].d_len == 0) 1380 ifp->if_flags &= ~IFF_OACTIVE; 1381 else { 1382 if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid, 1383 0, 0)) { 1384 printf("%s: xmit failed\n", sc->sc_dev.dv_xname); 1385 sc->sc_txd[cur].d_len = 0; 1386 } else { 1387 sc->sc_tx_timer = 5; 1388 ifp->if_timer = 1; 1389 } 1390 } 1391 } 1392 1393 static void 1394 wi_info_intr(struct wi_softc *sc) 1395 { 1396 struct ieee80211com *ic = &sc->sc_ic; 1397 struct ifnet *ifp = &ic->ic_if; 1398 int i, fid, len, off; 1399 u_int16_t ltbuf[2]; 1400 u_int16_t stat; 1401 u_int32_t *ptr; 1402 1403 fid = CSR_READ_2(sc, WI_INFO_FID); 1404 wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf)); 1405 1406 switch (le16toh(ltbuf[1])) { 1407 1408 case WI_INFO_LINK_STAT: 1409 wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat)); 1410 DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat))); 1411 switch (le16toh(stat)) { 1412 case CONNECTED: 1413 sc->sc_flags &= ~WI_FLAGS_OUTRANGE; 1414 if (ic->ic_state == IEEE80211_S_RUN && 1415 ic->ic_opmode != IEEE80211_M_IBSS) 1416 break; 1417 /* FALLTHROUGH */ 1418 case AP_CHANGE: 1419 ieee80211_new_state(ifp, IEEE80211_S_RUN, -1); 1420 break; 1421 case AP_IN_RANGE: 1422 sc->sc_flags &= ~WI_FLAGS_OUTRANGE; 1423 break; 1424 case AP_OUT_OF_RANGE: 1425 if (sc->sc_firmware_type == WI_SYMBOL && 1426 sc->sc_scan_timer > 0) { 1427 if (wi_cmd(sc, WI_CMD_INQUIRE, 1428 WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0) 1429 sc->sc_scan_timer = 0; 1430 break; 1431 } 1432 if (ic->ic_opmode == IEEE80211_M_STA) 1433 sc->sc_flags |= WI_FLAGS_OUTRANGE; 1434 break; 1435 case DISCONNECTED: 1436 case ASSOC_FAILED: 1437 if (ic->ic_opmode == IEEE80211_M_STA) 1438 ieee80211_new_state(ifp, IEEE80211_S_INIT, -1); 1439 break; 1440 } 1441 break; 1442 1443 case WI_INFO_COUNTERS: 1444 /* some card versions have a larger stats structure */ 1445 len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4); 1446 ptr = (u_int32_t *)&sc->sc_stats; 1447 off = sizeof(ltbuf); 1448 for (i = 0; i < len; i++, off += 2, ptr++) { 1449 wi_read_bap(sc, fid, off, &stat, sizeof(stat)); 1450 #ifdef WI_HERMES_STATS_WAR 1451 if (stat & 0xf000) 1452 stat = ~stat; 1453 #endif 1454 *ptr += stat; 1455 } 1456 ifp->if_collisions = sc->sc_stats.wi_tx_single_retries + 1457 sc->sc_stats.wi_tx_multi_retries + 1458 sc->sc_stats.wi_tx_retry_limit; 1459 break; 1460 1461 case WI_INFO_SCAN_RESULTS: 1462 case WI_INFO_HOST_SCAN_RESULTS: 1463 wi_scan_result(sc, fid, le16toh(ltbuf[0])); 1464 break; 1465 1466 default: 1467 DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid, 1468 le16toh(ltbuf[1]), le16toh(ltbuf[0]))); 1469 break; 1470 } 1471 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO); 1472 } 1473 1474 static int 1475 wi_write_multi(struct wi_softc *sc) 1476 { 1477 struct ifnet *ifp = &sc->sc_ic.ic_if; 1478 int n; 1479 struct wi_mcast mlist; 1480 struct ether_multi *enm; 1481 struct ether_multistep estep; 1482 1483 if ((ifp->if_flags & IFF_PROMISC) != 0) { 1484 allmulti: 1485 ifp->if_flags |= IFF_ALLMULTI; 1486 memset(&mlist, 0, sizeof(mlist)); 1487 return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist, 1488 sizeof(mlist)); 1489 } 1490 1491 n = 0; 1492 ETHER_FIRST_MULTI(estep, &sc->sc_ic.ic_ec, enm); 1493 while (enm != NULL) { 1494 /* Punt on ranges or too many multicast addresses. */ 1495 if (!IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi) || 1496 n >= sizeof(mlist) / sizeof(mlist.wi_mcast[0])) 1497 goto allmulti; 1498 1499 IEEE80211_ADDR_COPY(&mlist.wi_mcast[n], enm->enm_addrlo); 1500 n++; 1501 ETHER_NEXT_MULTI(estep, enm); 1502 } 1503 ifp->if_flags &= ~IFF_ALLMULTI; 1504 return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist, 1505 IEEE80211_ADDR_LEN * n); 1506 } 1507 1508 1509 static void 1510 wi_read_nicid(struct wi_softc *sc) 1511 { 1512 struct wi_card_ident *id; 1513 char *p; 1514 int len; 1515 u_int16_t ver[4]; 1516 1517 /* getting chip identity */ 1518 memset(ver, 0, sizeof(ver)); 1519 len = sizeof(ver); 1520 wi_read_rid(sc, WI_RID_CARD_ID, ver, &len); 1521 printf("%s: using ", sc->sc_dev.dv_xname); 1522 DPRINTF2(("wi_read_nicid: CARD_ID: %x %x %x %x\n", le16toh(ver[0]), le16toh(ver[1]), le16toh(ver[2]), le16toh(ver[3]))); 1523 1524 sc->sc_firmware_type = WI_NOTYPE; 1525 for (id = wi_card_ident; id->card_name != NULL; id++) { 1526 if (le16toh(ver[0]) == id->card_id) { 1527 printf("%s", id->card_name); 1528 sc->sc_firmware_type = id->firm_type; 1529 break; 1530 } 1531 } 1532 if (sc->sc_firmware_type == WI_NOTYPE) { 1533 if (le16toh(ver[0]) & 0x8000) { 1534 printf("Unknown PRISM2 chip"); 1535 sc->sc_firmware_type = WI_INTERSIL; 1536 } else { 1537 printf("Unknown Lucent chip"); 1538 sc->sc_firmware_type = WI_LUCENT; 1539 } 1540 } 1541 1542 /* get primary firmware version (Only Prism chips) */ 1543 if (sc->sc_firmware_type != WI_LUCENT) { 1544 memset(ver, 0, sizeof(ver)); 1545 len = sizeof(ver); 1546 wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len); 1547 sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 + 1548 le16toh(ver[3]) * 100 + le16toh(ver[1]); 1549 } 1550 1551 /* get station firmware version */ 1552 memset(ver, 0, sizeof(ver)); 1553 len = sizeof(ver); 1554 wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len); 1555 sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 + 1556 le16toh(ver[3]) * 100 + le16toh(ver[1]); 1557 if (sc->sc_firmware_type == WI_INTERSIL && 1558 (sc->sc_sta_firmware_ver == 10102 || 1559 sc->sc_sta_firmware_ver == 20102)) { 1560 char ident[12]; 1561 memset(ident, 0, sizeof(ident)); 1562 len = sizeof(ident); 1563 /* value should be the format like "V2.00-11" */ 1564 if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 && 1565 *(p = (char *)ident) >= 'A' && 1566 p[2] == '.' && p[5] == '-' && p[8] == '\0') { 1567 sc->sc_firmware_type = WI_SYMBOL; 1568 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 + 1569 (p[3] - '0') * 1000 + (p[4] - '0') * 100 + 1570 (p[6] - '0') * 10 + (p[7] - '0'); 1571 } 1572 } 1573 1574 printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname, 1575 sc->sc_firmware_type == WI_LUCENT ? "Lucent" : 1576 (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil")); 1577 if (sc->sc_firmware_type != WI_LUCENT) /* XXX */ 1578 printf("Primary (%u.%u.%u), ", 1579 sc->sc_pri_firmware_ver / 10000, 1580 (sc->sc_pri_firmware_ver % 10000) / 100, 1581 sc->sc_pri_firmware_ver % 100); 1582 printf("Station (%u.%u.%u)\n", 1583 sc->sc_sta_firmware_ver / 10000, 1584 (sc->sc_sta_firmware_ver % 10000) / 100, 1585 sc->sc_sta_firmware_ver % 100); 1586 } 1587 1588 static int 1589 wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen) 1590 { 1591 struct wi_ssid ssid; 1592 1593 if (buflen > IEEE80211_NWID_LEN) 1594 return ENOBUFS; 1595 memset(&ssid, 0, sizeof(ssid)); 1596 ssid.wi_len = htole16(buflen); 1597 memcpy(ssid.wi_ssid, buf, buflen); 1598 return wi_write_rid(sc, rid, &ssid, sizeof(ssid)); 1599 } 1600 1601 static int 1602 wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data) 1603 { 1604 struct wi_softc *sc = ifp->if_softc; 1605 struct ieee80211com *ic = &sc->sc_ic; 1606 struct ifreq *ifr = (struct ifreq *)data; 1607 struct wi_req wreq; 1608 int len, n, error; 1609 1610 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1611 if (error) 1612 return error; 1613 len = (wreq.wi_len - 1) * 2; 1614 if (len < sizeof(u_int16_t)) 1615 return ENOSPC; 1616 if (len > sizeof(wreq.wi_val)) 1617 len = sizeof(wreq.wi_val); 1618 1619 switch (wreq.wi_type) { 1620 1621 case WI_RID_IFACE_STATS: 1622 memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats)); 1623 if (len < sizeof(sc->sc_stats)) 1624 error = ENOSPC; 1625 else 1626 len = sizeof(sc->sc_stats); 1627 break; 1628 1629 case WI_RID_ENCRYPTION: 1630 case WI_RID_TX_CRYPT_KEY: 1631 case WI_RID_DEFLT_CRYPT_KEYS: 1632 case WI_RID_TX_RATE: 1633 return ieee80211_cfgget(ifp, cmd, data); 1634 1635 case WI_RID_MICROWAVE_OVEN: 1636 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) { 1637 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val, 1638 &len); 1639 break; 1640 } 1641 wreq.wi_val[0] = htole16(sc->sc_microwave_oven); 1642 len = sizeof(u_int16_t); 1643 break; 1644 1645 case WI_RID_DBM_ADJUST: 1646 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) { 1647 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val, 1648 &len); 1649 break; 1650 } 1651 wreq.wi_val[0] = htole16(sc->sc_dbm_adjust); 1652 len = sizeof(u_int16_t); 1653 break; 1654 1655 case WI_RID_ROAMING_MODE: 1656 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) { 1657 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val, 1658 &len); 1659 break; 1660 } 1661 wreq.wi_val[0] = htole16(sc->sc_roaming_mode); 1662 len = sizeof(u_int16_t); 1663 break; 1664 1665 case WI_RID_SYSTEM_SCALE: 1666 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) { 1667 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val, 1668 &len); 1669 break; 1670 } 1671 wreq.wi_val[0] = htole16(sc->sc_system_scale); 1672 len = sizeof(u_int16_t); 1673 break; 1674 1675 case WI_RID_FRAG_THRESH: 1676 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) { 1677 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val, 1678 &len); 1679 break; 1680 } 1681 wreq.wi_val[0] = htole16(sc->sc_frag_thresh); 1682 len = sizeof(u_int16_t); 1683 break; 1684 1685 case WI_RID_READ_APS: 1686 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 1687 return ieee80211_cfgget(ifp, cmd, data); 1688 if (sc->sc_scan_timer > 0) { 1689 error = EINPROGRESS; 1690 break; 1691 } 1692 n = sc->sc_naps; 1693 if (len < sizeof(n)) { 1694 error = ENOSPC; 1695 break; 1696 } 1697 if (len < sizeof(n) + sizeof(struct wi_apinfo) * n) 1698 n = (len - sizeof(n)) / sizeof(struct wi_apinfo); 1699 len = sizeof(n) + sizeof(struct wi_apinfo) * n; 1700 memcpy(wreq.wi_val, &n, sizeof(n)); 1701 memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps, 1702 sizeof(struct wi_apinfo) * n); 1703 break; 1704 1705 default: 1706 if (sc->sc_enabled) { 1707 error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val, 1708 &len); 1709 break; 1710 } 1711 switch (wreq.wi_type) { 1712 case WI_RID_MAX_DATALEN: 1713 wreq.wi_val[0] = htole16(sc->sc_max_datalen); 1714 len = sizeof(u_int16_t); 1715 break; 1716 case WI_RID_FRAG_THRESH: 1717 wreq.wi_val[0] = htole16(sc->sc_frag_thresh); 1718 len = sizeof(u_int16_t); 1719 break; 1720 case WI_RID_RTS_THRESH: 1721 wreq.wi_val[0] = htole16(sc->sc_rts_thresh); 1722 len = sizeof(u_int16_t); 1723 break; 1724 case WI_RID_CNFAUTHMODE: 1725 wreq.wi_val[0] = htole16(sc->sc_cnfauthmode); 1726 len = sizeof(u_int16_t); 1727 break; 1728 case WI_RID_NODENAME: 1729 if (len < sc->sc_nodelen + sizeof(u_int16_t)) { 1730 error = ENOSPC; 1731 break; 1732 } 1733 len = sc->sc_nodelen + sizeof(u_int16_t); 1734 wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2); 1735 memcpy(&wreq.wi_val[1], sc->sc_nodename, 1736 sc->sc_nodelen); 1737 break; 1738 default: 1739 return ieee80211_cfgget(ifp, cmd, data); 1740 } 1741 break; 1742 } 1743 if (error) 1744 return error; 1745 wreq.wi_len = (len + 1) / 2 + 1; 1746 return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2); 1747 } 1748 1749 static int 1750 wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data) 1751 { 1752 struct wi_softc *sc = ifp->if_softc; 1753 struct ieee80211com *ic = &sc->sc_ic; 1754 struct ifreq *ifr = (struct ifreq *)data; 1755 struct wi_req wreq; 1756 struct mbuf *m; 1757 int i, len, error; 1758 1759 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1760 if (error) 1761 return error; 1762 len = (wreq.wi_len - 1) * 2; 1763 switch (wreq.wi_type) { 1764 case WI_RID_DBM_ADJUST: 1765 return ENODEV; 1766 1767 case WI_RID_NODENAME: 1768 if (le16toh(wreq.wi_val[0]) * 2 > len || 1769 le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) { 1770 error = ENOSPC; 1771 break; 1772 } 1773 if (sc->sc_enabled) { 1774 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val, 1775 len); 1776 if (error) 1777 break; 1778 } 1779 sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2; 1780 memcpy(sc->sc_nodename, &wreq.wi_val[1], sc->sc_nodelen); 1781 break; 1782 1783 case WI_RID_MICROWAVE_OVEN: 1784 case WI_RID_ROAMING_MODE: 1785 case WI_RID_SYSTEM_SCALE: 1786 case WI_RID_FRAG_THRESH: 1787 if (wreq.wi_type == WI_RID_MICROWAVE_OVEN && 1788 (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0) 1789 break; 1790 if (wreq.wi_type == WI_RID_ROAMING_MODE && 1791 (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0) 1792 break; 1793 if (wreq.wi_type == WI_RID_SYSTEM_SCALE && 1794 (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0) 1795 break; 1796 if (wreq.wi_type == WI_RID_FRAG_THRESH && 1797 (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0) 1798 break; 1799 /* FALLTHROUGH */ 1800 case WI_RID_RTS_THRESH: 1801 case WI_RID_CNFAUTHMODE: 1802 case WI_RID_MAX_DATALEN: 1803 if (sc->sc_enabled) { 1804 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val, 1805 sizeof(u_int16_t)); 1806 if (error) 1807 break; 1808 } 1809 switch (wreq.wi_type) { 1810 case WI_RID_FRAG_THRESH: 1811 sc->sc_frag_thresh = le16toh(wreq.wi_val[0]); 1812 break; 1813 case WI_RID_RTS_THRESH: 1814 sc->sc_rts_thresh = le16toh(wreq.wi_val[0]); 1815 break; 1816 case WI_RID_MICROWAVE_OVEN: 1817 sc->sc_microwave_oven = le16toh(wreq.wi_val[0]); 1818 break; 1819 case WI_RID_ROAMING_MODE: 1820 sc->sc_roaming_mode = le16toh(wreq.wi_val[0]); 1821 break; 1822 case WI_RID_SYSTEM_SCALE: 1823 sc->sc_system_scale = le16toh(wreq.wi_val[0]); 1824 break; 1825 case WI_RID_CNFAUTHMODE: 1826 sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]); 1827 break; 1828 case WI_RID_MAX_DATALEN: 1829 sc->sc_max_datalen = le16toh(wreq.wi_val[0]); 1830 break; 1831 } 1832 break; 1833 1834 case WI_RID_TX_RATE: 1835 switch (le16toh(wreq.wi_val[0])) { 1836 case 3: 1837 ic->ic_fixed_rate = -1; 1838 break; 1839 default: 1840 for (i = 0; i < IEEE80211_RATE_SIZE; i++) { 1841 if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) 1842 / 2 == le16toh(wreq.wi_val[0])) 1843 break; 1844 } 1845 if (i == IEEE80211_RATE_SIZE) 1846 return EINVAL; 1847 ic->ic_fixed_rate = i; 1848 } 1849 if (sc->sc_enabled) 1850 error = wi_write_txrate(sc); 1851 break; 1852 1853 case WI_RID_SCAN_APS: 1854 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP) 1855 error = wi_scan_ap(sc, 0x3fff, 0x000f); 1856 break; 1857 1858 case WI_RID_MGMT_XMIT: 1859 if (!sc->sc_enabled) { 1860 error = ENETDOWN; 1861 break; 1862 } 1863 if (ic->ic_mgtq.ifq_len > 5) { 1864 error = EAGAIN; 1865 break; 1866 } 1867 /* XXX wi_len looks in u_int8_t, not in u_int16_t */ 1868 m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0, ifp, NULL); 1869 if (m == NULL) { 1870 error = ENOMEM; 1871 break; 1872 } 1873 IF_ENQUEUE(&ic->ic_mgtq, m); 1874 break; 1875 1876 default: 1877 if (sc->sc_enabled) { 1878 error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val, 1879 len); 1880 if (error) 1881 break; 1882 } 1883 error = ieee80211_cfgset(ifp, cmd, data); 1884 break; 1885 } 1886 return error; 1887 } 1888 1889 static int 1890 wi_write_txrate(struct wi_softc *sc) 1891 { 1892 struct ieee80211com *ic = &sc->sc_ic; 1893 int i; 1894 u_int16_t rate; 1895 1896 if (ic->ic_fixed_rate < 0) 1897 rate = 0; /* auto */ 1898 else 1899 rate = (ic->ic_sup_rates[ic->ic_fixed_rate] & 1900 IEEE80211_RATE_VAL) / 2; 1901 1902 /* rate: 0, 1, 2, 5, 11 */ 1903 1904 switch (sc->sc_firmware_type) { 1905 case WI_LUCENT: 1906 if (rate == 0) 1907 rate = 3; /* auto */ 1908 break; 1909 default: 1910 /* Choose a bit according to this table. 1911 * 1912 * bit | data rate 1913 * ----+------------------- 1914 * 0 | 1Mbps 1915 * 1 | 2Mbps 1916 * 2 | 5.5Mbps 1917 * 3 | 11Mbps 1918 */ 1919 for (i = 8; i > 0; i >>= 1) { 1920 if (rate >= i) 1921 break; 1922 } 1923 if (i == 0) 1924 rate = 0xf; /* auto */ 1925 else 1926 rate = i; 1927 break; 1928 } 1929 return wi_write_val(sc, WI_RID_TX_RATE, rate); 1930 } 1931 1932 static int 1933 wi_write_wep(struct wi_softc *sc) 1934 { 1935 struct ieee80211com *ic = &sc->sc_ic; 1936 int error = 0; 1937 int i, keylen; 1938 u_int16_t val; 1939 struct wi_key wkey[IEEE80211_WEP_NKID]; 1940 1941 switch (sc->sc_firmware_type) { 1942 case WI_LUCENT: 1943 val = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0; 1944 error = wi_write_val(sc, WI_RID_ENCRYPTION, val); 1945 if (error) 1946 break; 1947 error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_wep_txkey); 1948 if (error) 1949 break; 1950 memset(wkey, 0, sizeof(wkey)); 1951 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1952 keylen = ic->ic_nw_keys[i].wk_len; 1953 wkey[i].wi_keylen = htole16(keylen); 1954 memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key, 1955 keylen); 1956 } 1957 error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS, 1958 wkey, sizeof(wkey)); 1959 break; 1960 1961 case WI_INTERSIL: 1962 case WI_SYMBOL: 1963 if (ic->ic_flags & IEEE80211_F_WEPON) { 1964 /* 1965 * ONLY HWB3163 EVAL-CARD Firmware version 1966 * less than 0.8 variant2 1967 * 1968 * If promiscuous mode disable, Prism2 chip 1969 * does not work with WEP . 1970 * It is under investigation for details. 1971 * (ichiro@netbsd.org) 1972 */ 1973 if (sc->sc_firmware_type == WI_INTERSIL && 1974 sc->sc_sta_firmware_ver < 802 ) { 1975 /* firm ver < 0.8 variant 2 */ 1976 wi_write_val(sc, WI_RID_PROMISC, 1); 1977 } 1978 wi_write_val(sc, WI_RID_CNFAUTHMODE, 1979 sc->sc_cnfauthmode); 1980 val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED; 1981 /* 1982 * Encryption firmware has a bug for HostAP mode. 1983 */ 1984 if (sc->sc_firmware_type == WI_INTERSIL && 1985 ic->ic_opmode == IEEE80211_M_HOSTAP) 1986 val |= HOST_ENCRYPT; 1987 } else { 1988 wi_write_val(sc, WI_RID_CNFAUTHMODE, 1989 IEEE80211_AUTH_OPEN); 1990 val = HOST_ENCRYPT | HOST_DECRYPT; 1991 } 1992 error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val); 1993 if (error) 1994 break; 1995 error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY, 1996 ic->ic_wep_txkey); 1997 if (error) 1998 break; 1999 /* 2000 * It seems that the firmware accept 104bit key only if 2001 * all the keys have 104bit length. We get the length of 2002 * the transmit key and use it for all other keys. 2003 * Perhaps we should use software WEP for such situation. 2004 */ 2005 keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len; 2006 if (keylen > IEEE80211_WEP_KEYLEN) 2007 keylen = 13; /* 104bit keys */ 2008 else 2009 keylen = IEEE80211_WEP_KEYLEN; 2010 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2011 error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i, 2012 ic->ic_nw_keys[i].wk_key, keylen); 2013 if (error) 2014 break; 2015 } 2016 break; 2017 } 2018 return error; 2019 } 2020 2021 /* Must be called at proper protection level! */ 2022 static int 2023 wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2) 2024 { 2025 int i, status; 2026 2027 /* wait for the busy bit to clear */ 2028 for (i = 500; i > 0; i--) { /* 5s */ 2029 if ((CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY) == 0) 2030 break; 2031 DELAY(10*1000); /* 10 m sec */ 2032 } 2033 if (i == 0) { 2034 printf("%s: wi_cmd: busy bit won't clear.\n", 2035 sc->sc_dev.dv_xname); 2036 return(ETIMEDOUT); 2037 } 2038 CSR_WRITE_2(sc, WI_PARAM0, val0); 2039 CSR_WRITE_2(sc, WI_PARAM1, val1); 2040 CSR_WRITE_2(sc, WI_PARAM2, val2); 2041 CSR_WRITE_2(sc, WI_COMMAND, cmd); 2042 2043 if (cmd == WI_CMD_INI) { 2044 /* XXX: should sleep here. */ 2045 DELAY(100*1000); 2046 } 2047 /* wait for the cmd completed bit */ 2048 for (i = 0; i < WI_TIMEOUT; i++) { 2049 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD) 2050 break; 2051 DELAY(WI_DELAY); 2052 } 2053 2054 status = CSR_READ_2(sc, WI_STATUS); 2055 2056 /* Ack the command */ 2057 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); 2058 2059 if (i == WI_TIMEOUT) { 2060 printf("%s: command timed out, cmd=0x%x, arg=0x%x\n", 2061 sc->sc_dev.dv_xname, cmd, val0); 2062 return ETIMEDOUT; 2063 } 2064 2065 if (status & WI_STAT_CMD_RESULT) { 2066 printf("%s: command failed, cmd=0x%x, arg=0x%x\n", 2067 sc->sc_dev.dv_xname, cmd, val0); 2068 return EIO; 2069 } 2070 return 0; 2071 } 2072 2073 static int 2074 wi_seek_bap(struct wi_softc *sc, int id, int off) 2075 { 2076 int i, status; 2077 2078 CSR_WRITE_2(sc, WI_SEL0, id); 2079 CSR_WRITE_2(sc, WI_OFF0, off); 2080 2081 for (i = 0; ; i++) { 2082 status = CSR_READ_2(sc, WI_OFF0); 2083 if ((status & WI_OFF_BUSY) == 0) 2084 break; 2085 if (i == WI_TIMEOUT) { 2086 printf("%s: timeout in wi_seek to %x/%x\n", 2087 sc->sc_dev.dv_xname, id, off); 2088 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */ 2089 return ETIMEDOUT; 2090 } 2091 DELAY(1); 2092 } 2093 if (status & WI_OFF_ERR) { 2094 printf("%s: failed in wi_seek to %x/%x\n", 2095 sc->sc_dev.dv_xname, id, off); 2096 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */ 2097 return EIO; 2098 } 2099 sc->sc_bap_id = id; 2100 sc->sc_bap_off = off; 2101 return 0; 2102 } 2103 2104 static int 2105 wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen) 2106 { 2107 int error, cnt; 2108 2109 if (buflen == 0) 2110 return 0; 2111 if (id != sc->sc_bap_id || off != sc->sc_bap_off) { 2112 if ((error = wi_seek_bap(sc, id, off)) != 0) 2113 return error; 2114 } 2115 cnt = (buflen + 1) / 2; 2116 CSR_READ_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt); 2117 sc->sc_bap_off += cnt * 2; 2118 return 0; 2119 } 2120 2121 static int 2122 wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen) 2123 { 2124 int error, cnt; 2125 2126 if (buflen == 0) 2127 return 0; 2128 2129 #ifdef WI_HERMES_AUTOINC_WAR 2130 again: 2131 #endif 2132 if (id != sc->sc_bap_id || off != sc->sc_bap_off) { 2133 if ((error = wi_seek_bap(sc, id, off)) != 0) 2134 return error; 2135 } 2136 cnt = (buflen + 1) / 2; 2137 CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt); 2138 sc->sc_bap_off += cnt * 2; 2139 2140 #ifdef WI_HERMES_AUTOINC_WAR 2141 /* 2142 * According to the comments in the HCF Light code, there is a bug 2143 * in the Hermes (or possibly in certain Hermes firmware revisions) 2144 * where the chip's internal autoincrement counter gets thrown off 2145 * during data writes: the autoincrement is missed, causing one 2146 * data word to be overwritten and subsequent words to be written to 2147 * the wrong memory locations. The end result is that we could end 2148 * up transmitting bogus frames without realizing it. The workaround 2149 * for this is to write a couple of extra guard words after the end 2150 * of the transfer, then attempt to read then back. If we fail to 2151 * locate the guard words where we expect them, we preform the 2152 * transfer over again. 2153 */ 2154 if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) { 2155 CSR_WRITE_2(sc, WI_DATA0, 0x1234); 2156 CSR_WRITE_2(sc, WI_DATA0, 0x5678); 2157 wi_seek_bap(sc, id, sc->sc_bap_off); 2158 sc->sc_bap_off = WI_OFF_ERR; /* invalidate */ 2159 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 || 2160 CSR_READ_2(sc, WI_DATA0) != 0x5678) { 2161 printf("%s: detect auto increment bug, try again\n", 2162 sc->sc_dev.dv_xname); 2163 goto again; 2164 } 2165 } 2166 #endif 2167 return 0; 2168 } 2169 2170 static int 2171 wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen) 2172 { 2173 int error, len; 2174 struct mbuf *m; 2175 2176 for (m = m0; m != NULL && totlen > 0; m = m->m_next) { 2177 if (m->m_len == 0) 2178 continue; 2179 2180 len = min(m->m_len, totlen); 2181 2182 if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) { 2183 m_copydata(m, 0, totlen, (caddr_t)&sc->sc_txbuf); 2184 return wi_write_bap(sc, id, off, (caddr_t)&sc->sc_txbuf, 2185 totlen); 2186 } 2187 2188 if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0) 2189 return error; 2190 2191 off += m->m_len; 2192 totlen -= len; 2193 } 2194 return 0; 2195 } 2196 2197 static int 2198 wi_alloc_fid(struct wi_softc *sc, int len, int *idp) 2199 { 2200 int i; 2201 2202 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) { 2203 printf("%s: failed to allocate %d bytes on NIC\n", 2204 sc->sc_dev.dv_xname, len); 2205 return ENOMEM; 2206 } 2207 2208 for (i = 0; i < WI_TIMEOUT; i++) { 2209 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) 2210 break; 2211 if (i == WI_TIMEOUT) { 2212 printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname); 2213 return ETIMEDOUT; 2214 } 2215 DELAY(1); 2216 } 2217 *idp = CSR_READ_2(sc, WI_ALLOC_FID); 2218 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); 2219 return 0; 2220 } 2221 2222 static int 2223 wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp) 2224 { 2225 int error, len; 2226 u_int16_t ltbuf[2]; 2227 2228 /* Tell the NIC to enter record read mode. */ 2229 error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0); 2230 if (error) 2231 return error; 2232 2233 error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf)); 2234 if (error) 2235 return error; 2236 2237 if (le16toh(ltbuf[1]) != rid) { 2238 printf("%s: record read mismatch, rid=%x, got=%x\n", 2239 sc->sc_dev.dv_xname, rid, le16toh(ltbuf[1])); 2240 return EIO; 2241 } 2242 len = (le16toh(ltbuf[0]) - 1) * 2; /* already got rid */ 2243 if (*buflenp < len) { 2244 printf("%s: record buffer is too small, " 2245 "rid=%x, size=%d, len=%d\n", 2246 sc->sc_dev.dv_xname, rid, *buflenp, len); 2247 return ENOSPC; 2248 } 2249 *buflenp = len; 2250 return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len); 2251 } 2252 2253 static int 2254 wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen) 2255 { 2256 int error; 2257 u_int16_t ltbuf[2]; 2258 2259 ltbuf[0] = htole16((buflen + 1) / 2 + 1); /* includes rid */ 2260 ltbuf[1] = htole16(rid); 2261 2262 error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf)); 2263 if (error) 2264 return error; 2265 error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen); 2266 if (error) 2267 return error; 2268 2269 return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0); 2270 } 2271 2272 static int 2273 wi_newstate(void *arg, enum ieee80211_state nstate) 2274 { 2275 struct wi_softc *sc = arg; 2276 struct ieee80211com *ic = &sc->sc_ic; 2277 struct ieee80211_node *ni = &ic->ic_bss; 2278 int i, buflen; 2279 u_int16_t val; 2280 struct wi_ssid ssid; 2281 u_int8_t old_bssid[IEEE80211_ADDR_LEN]; 2282 enum ieee80211_state ostate; 2283 #ifdef WI_DEBUG 2284 static const char *stname[] = 2285 { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" }; 2286 #endif /* WI_DEBUG */ 2287 2288 ostate = ic->ic_state; 2289 DPRINTF(("wi_newstate: %s -> %s\n", stname[ostate], stname[nstate])); 2290 2291 ic->ic_state = nstate; 2292 switch (nstate) { 2293 case IEEE80211_S_INIT: 2294 ic->ic_flags &= ~IEEE80211_F_SIBSS; 2295 sc->sc_flags &= ~WI_FLAGS_OUTRANGE; 2296 return 0; 2297 2298 case IEEE80211_S_RUN: 2299 sc->sc_flags &= ~WI_FLAGS_OUTRANGE; 2300 buflen = IEEE80211_ADDR_LEN; 2301 IEEE80211_ADDR_COPY(old_bssid, ni->ni_bssid); 2302 wi_read_rid(sc, WI_RID_CURRENT_BSSID, ni->ni_bssid, &buflen); 2303 IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid); 2304 buflen = sizeof(val); 2305 wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen); 2306 ni->ni_chan = le16toh(val); 2307 2308 if (IEEE80211_ADDR_EQ(old_bssid, ni->ni_bssid)) 2309 sc->sc_false_syns++; 2310 else 2311 sc->sc_false_syns = 0; 2312 2313 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 2314 ni->ni_esslen = ic->ic_des_esslen; 2315 memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); 2316 ni->ni_nrate = 0; 2317 for (i = 0; i < IEEE80211_RATE_SIZE; i++) { 2318 if (ic->ic_sup_rates[i]) 2319 ni->ni_rates[ni->ni_nrate++] = 2320 ic->ic_sup_rates[i]; 2321 } 2322 ni->ni_intval = ic->ic_lintval; 2323 ni->ni_capinfo = IEEE80211_CAPINFO_ESS; 2324 if (ic->ic_flags & IEEE80211_F_WEPON) 2325 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; 2326 } else { 2327 buflen = sizeof(ssid); 2328 wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen); 2329 ni->ni_esslen = le16toh(ssid.wi_len); 2330 if (ni->ni_esslen > IEEE80211_NWID_LEN) 2331 ni->ni_esslen = IEEE80211_NWID_LEN; /*XXX*/ 2332 memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen); 2333 } 2334 break; 2335 2336 case IEEE80211_S_SCAN: 2337 case IEEE80211_S_AUTH: 2338 case IEEE80211_S_ASSOC: 2339 break; 2340 } 2341 2342 /* skip standard ieee80211 handling */ 2343 return EINPROGRESS; 2344 } 2345 2346 static int 2347 wi_set_tim(struct ieee80211com *ic, int aid, int which) 2348 { 2349 struct wi_softc *sc = ic->ic_softc; 2350 2351 aid &= ~0xc000; 2352 if (which) 2353 aid |= 0x8000; 2354 2355 return wi_write_val(sc, WI_RID_SET_TIM, aid); 2356 } 2357 2358 static int 2359 wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate) 2360 { 2361 int error = 0; 2362 u_int16_t val[2]; 2363 2364 if (!sc->sc_enabled) 2365 return ENXIO; 2366 switch (sc->sc_firmware_type) { 2367 case WI_LUCENT: 2368 (void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0); 2369 break; 2370 case WI_INTERSIL: 2371 val[0] = chanmask; /* channel */ 2372 val[1] = txrate; /* tx rate */ 2373 error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val)); 2374 break; 2375 case WI_SYMBOL: 2376 /* 2377 * XXX only supported on 3.x ? 2378 */ 2379 val[0] = BSCAN_BCAST | BSCAN_ONETIME; 2380 error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ, 2381 val, sizeof(val[0])); 2382 break; 2383 } 2384 if (error == 0) { 2385 sc->sc_scan_timer = WI_SCAN_WAIT; 2386 sc->sc_ic.ic_if.if_timer = 1; 2387 DPRINTF(("wi_scan_ap: start scanning, " 2388 "chanmask 0x%x txrate 0x%x\n", chanmask, txrate)); 2389 } 2390 return error; 2391 } 2392 2393 static void 2394 wi_scan_result(struct wi_softc *sc, int fid, int cnt) 2395 { 2396 #define N(a) (sizeof (a) / sizeof (a[0])) 2397 int i, naps, off, szbuf; 2398 struct wi_scan_header ws_hdr; /* Prism2 header */ 2399 struct wi_scan_data_p2 ws_dat; /* Prism2 scantable*/ 2400 struct wi_apinfo *ap; 2401 2402 off = sizeof(u_int16_t) * 2; 2403 memset(&ws_hdr, 0, sizeof(ws_hdr)); 2404 switch (sc->sc_firmware_type) { 2405 case WI_INTERSIL: 2406 wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr)); 2407 off += sizeof(ws_hdr); 2408 szbuf = sizeof(struct wi_scan_data_p2); 2409 break; 2410 case WI_SYMBOL: 2411 szbuf = sizeof(struct wi_scan_data_p2) + 6; 2412 break; 2413 case WI_LUCENT: 2414 szbuf = sizeof(struct wi_scan_data); 2415 break; 2416 default: 2417 printf("%s: wi_scan_result: unknown firmware type %u\n", 2418 sc->sc_dev.dv_xname, sc->sc_firmware_type); 2419 naps = 0; 2420 goto done; 2421 } 2422 naps = (cnt * 2 + 2 - off) / szbuf; 2423 if (naps > N(sc->sc_aps)) 2424 naps = N(sc->sc_aps); 2425 sc->sc_naps = naps; 2426 /* Read Data */ 2427 ap = sc->sc_aps; 2428 memset(&ws_dat, 0, sizeof(ws_dat)); 2429 for (i = 0; i < naps; i++, ap++) { 2430 wi_read_bap(sc, fid, off, &ws_dat, 2431 (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf)); 2432 DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off, 2433 ether_sprintf(ws_dat.wi_bssid))); 2434 off += szbuf; 2435 ap->scanreason = le16toh(ws_hdr.wi_reason); 2436 memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid)); 2437 ap->channel = le16toh(ws_dat.wi_chid); 2438 ap->signal = le16toh(ws_dat.wi_signal); 2439 ap->noise = le16toh(ws_dat.wi_noise); 2440 ap->quality = ap->signal - ap->noise; 2441 ap->capinfo = le16toh(ws_dat.wi_capinfo); 2442 ap->interval = le16toh(ws_dat.wi_interval); 2443 ap->rate = le16toh(ws_dat.wi_rate); 2444 ap->namelen = le16toh(ws_dat.wi_namelen); 2445 if (ap->namelen > sizeof(ap->name)) 2446 ap->namelen = sizeof(ap->name); 2447 memcpy(ap->name, ws_dat.wi_name, ap->namelen); 2448 } 2449 done: 2450 /* Done scanning */ 2451 sc->sc_scan_timer = 0; 2452 DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps)); 2453 #undef N 2454 } 2455 2456 static void 2457 wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi) 2458 { 2459 ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr), 2460 ni ? ni->ni_rates[ni->ni_txrate] & IEEE80211_RATE_VAL : -1, rssi); 2461 printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n", 2462 le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1), 2463 le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence); 2464 printf(" rx_signal %u rx_rate %u rx_flow %u\n", 2465 wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow); 2466 printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n", 2467 wh->wi_tx_rtry, wh->wi_tx_rate, 2468 le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len)); 2469 printf(" ehdr dst %s src %s type 0x%x\n", 2470 ether_sprintf(wh->wi_ehdr.ether_dhost), 2471 ether_sprintf(wh->wi_ehdr.ether_shost), 2472 wh->wi_ehdr.ether_type); 2473 } 2474