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