1 1.100 andvar /* $NetBSD: if_ray.c,v 1.100 2024/02/11 10:36:40 andvar Exp $ */ 2 1.49 mycroft 3 1.56 perry /* 4 1.1 chopps * Copyright (c) 2000 Christian E. Hopps 5 1.1 chopps * All rights reserved. 6 1.56 perry * 7 1.1 chopps * Redistribution and use in source and binary forms, with or without 8 1.1 chopps * modification, are permitted provided that the following conditions 9 1.1 chopps * are met: 10 1.1 chopps * 1. Redistributions of source code must retain the above copyright 11 1.1 chopps * notice, this list of conditions and the following disclaimer. 12 1.1 chopps * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 chopps * notice, this list of conditions and the following disclaimer in the 14 1.1 chopps * documentation and/or other materials provided with the distribution. 15 1.1 chopps * 3. Neither the name of the author nor the names of any co-contributors 16 1.1 chopps * may be used to endorse or promote products derived from this software 17 1.1 chopps * without specific prior written permission. 18 1.1 chopps * 19 1.1 chopps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 1.1 chopps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 chopps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 chopps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 1.1 chopps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 chopps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 chopps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 chopps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 chopps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 chopps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 chopps * SUCH DAMAGE. 30 1.1 chopps */ 31 1.1 chopps 32 1.1 chopps /* 33 1.1 chopps * Driver for the Raylink (Raytheon) / WebGear IEEE 802.11 (FH) WLANs 34 1.1 chopps * 35 1.1 chopps * 2-way communication with the card is through command structures 36 1.1 chopps * stored in shared ram. To communicate with the card a free 37 1.1 chopps * command structure is filled in and then the card is interrupted. 38 1.1 chopps * The card does the same with a different set of command structures. 39 1.1 chopps * Only one command can be processed at a time. This is indicated 40 1.1 chopps * by the interrupt having not been cleared since it was last set. 41 1.1 chopps * The bit is cleared when the command has been processed (although 42 1.1 chopps * it may not yet be complete). 43 1.1 chopps * 44 1.1 chopps * This driver was only tested with the Aviator 2.4 wireless 45 1.1 chopps * The author didn't have the pro version or raylink to test 46 1.1 chopps * with. 47 1.1 chopps * 48 1.1 chopps * N.B. Its unclear yet whether the Aviator 2.4 cards interoperate 49 1.1 chopps * with other 802.11 FH 2Mbps cards, since this was also untested. 50 1.1 chopps * Given the nature of the buggy build 4 firmware there may be problems. 51 1.24 thorpej * 52 1.24 thorpej * Authentication added by Steve Weiss <srw (at) alum.mit.edu> based on 53 1.30 soren * advice from Corey Thomas (author of the Linux RayLink driver). 54 1.24 thorpej * Authentication is currently limited to adhoc networks, and was 55 1.24 thorpej * added to support a requirement of the newest Windows drivers for 56 1.24 thorpej * the RayLink. Tested with Aviator Pro (firmware 5.63) on Win98. 57 1.1 chopps */ 58 1.29 lukem 59 1.29 lukem #include <sys/cdefs.h> 60 1.100 andvar __KERNEL_RCSID(0, "$NetBSD: if_ray.c,v 1.100 2024/02/11 10:36:40 andvar Exp $"); 61 1.1 chopps 62 1.1 chopps #include "opt_inet.h" 63 1.1 chopps 64 1.1 chopps #include <sys/param.h> 65 1.1 chopps #include <sys/systm.h> 66 1.17 thorpej #include <sys/callout.h> 67 1.1 chopps #include <sys/mbuf.h> 68 1.1 chopps #include <sys/socket.h> 69 1.1 chopps #include <sys/ioctl.h> 70 1.1 chopps #include <sys/errno.h> 71 1.1 chopps #include <sys/device.h> 72 1.1 chopps #include <sys/kernel.h> 73 1.1 chopps #include <sys/proc.h> 74 1.1 chopps 75 1.1 chopps #include <net/if.h> 76 1.1 chopps #include <net/if_dl.h> 77 1.1 chopps #include <net/if_ether.h> 78 1.1 chopps #include <net/if_media.h> 79 1.1 chopps #include <net/if_llc.h> 80 1.38 dyoung #include <net80211/ieee80211.h> 81 1.38 dyoung #include <net80211/ieee80211_ioctl.h> 82 1.1 chopps #include <net/if_media.h> 83 1.89 msaitoh #include <net/bpf.h> 84 1.1 chopps 85 1.1 chopps #ifdef INET 86 1.1 chopps #include <netinet/in.h> 87 1.1 chopps #include <netinet/in_systm.h> 88 1.1 chopps #include <netinet/in_var.h> 89 1.1 chopps #include <netinet/ip.h> 90 1.1 chopps #include <netinet/if_inarp.h> 91 1.1 chopps #endif 92 1.1 chopps 93 1.67 ad #include <sys/cpu.h> 94 1.67 ad #include <sys/bus.h> 95 1.67 ad #include <sys/intr.h> 96 1.1 chopps 97 1.1 chopps #include <dev/pcmcia/pcmciareg.h> 98 1.1 chopps #include <dev/pcmcia/pcmciavar.h> 99 1.1 chopps #include <dev/pcmcia/pcmciadevs.h> 100 1.1 chopps 101 1.1 chopps #include <dev/pcmcia/if_rayreg.h> 102 1.1 chopps 103 1.1 chopps #define RAY_DEBUG 104 1.1 chopps 105 1.1 chopps #ifndef RAY_PID_COUNTRY_CODE_DEFAULT 106 1.1 chopps #define RAY_PID_COUNTRY_CODE_DEFAULT RAY_PID_COUNTRY_CODE_USA 107 1.1 chopps #endif 108 1.1 chopps 109 1.1 chopps /* amount of time to poll for non-return of certain command status */ 110 1.1 chopps #ifndef RAY_CHECK_CCS_TIMEOUT 111 1.1 chopps #define RAY_CHECK_CCS_TIMEOUT (hz / 2) 112 1.1 chopps #endif 113 1.1 chopps 114 1.99 andvar /* amount of time to consider start/join failed */ 115 1.1 chopps #ifndef RAY_START_TIMEOUT 116 1.3 chopps #define RAY_START_TIMEOUT (30 * hz) 117 1.1 chopps #endif 118 1.1 chopps 119 1.1 chopps /* 120 1.1 chopps * if a command cannot execute because device is busy try later 121 1.1 chopps * this is also done after interrupts and other command timeouts 122 1.1 chopps * so we can use a large value safely. 123 1.1 chopps */ 124 1.1 chopps #ifndef RAY_CHECK_SCHED_TIMEOUT 125 1.1 chopps #define RAY_CHECK_SCHED_TIMEOUT (hz) /* XXX 5 */ 126 1.1 chopps #endif 127 1.1 chopps 128 1.1 chopps #ifndef RAY_MODE_DEFAULT 129 1.1 chopps #define RAY_MODE_DEFAULT SC_MODE_ADHOC 130 1.1 chopps #endif 131 1.1 chopps 132 1.1 chopps #ifndef RAY_DEF_NWID 133 1.1 chopps #define RAY_DEF_NWID "NETWORK_NAME" 134 1.1 chopps #endif 135 1.1 chopps 136 1.1 chopps /* 137 1.39 mjl * The number of times the HW is reset in 30s before disabling. 138 1.39 mjl * This is needed because resets take ~2s and currently pcmcia 139 1.39 mjl * spins for the reset. 140 1.1 chopps */ 141 1.1 chopps #ifndef RAY_MAX_RESETS 142 1.1 chopps #define RAY_MAX_RESETS 3 143 1.1 chopps #endif 144 1.1 chopps 145 1.1 chopps /* 146 1.1 chopps * Types 147 1.1 chopps */ 148 1.1 chopps 149 1.1 chopps struct ray_softc { 150 1.80 chs device_t sc_dev; 151 1.1 chopps struct ethercom sc_ec; 152 1.1 chopps struct ifmedia sc_media; 153 1.1 chopps 154 1.1 chopps struct pcmcia_function *sc_pf; 155 1.1 chopps void *sc_ih; 156 1.49 mycroft int sc_attached; 157 1.49 mycroft 158 1.1 chopps int sc_resetloop; 159 1.1 chopps 160 1.17 thorpej struct callout sc_check_ccs_ch; 161 1.17 thorpej struct callout sc_check_scheduled_ch; 162 1.17 thorpej struct callout sc_reset_resetloop_ch; 163 1.17 thorpej struct callout sc_disable_ch; 164 1.17 thorpej struct callout sc_start_join_timo_ch; 165 1.17 thorpej 166 1.1 chopps struct ray_ecf_startup sc_ecf_startup; 167 1.1 chopps struct ray_startup_params_head sc_startup; 168 1.1 chopps union { 169 1.1 chopps struct ray_startup_params_tail_5 u_params_5; 170 1.1 chopps struct ray_startup_params_tail_4 u_params_4; 171 1.1 chopps } sc_u; 172 1.56 perry 173 1.93 msaitoh uint8_t sc_ccsinuse[64]; /* ccs in use -- not for tx */ 174 1.1 chopps u_int sc_txfree; /* a free count for efficiency */ 175 1.1 chopps 176 1.93 msaitoh uint8_t sc_bssid[ETHER_ADDR_LEN]; /* current net values */ 177 1.93 msaitoh uint8_t sc_authid[ETHER_ADDR_LEN]; /* ID of authenticating 178 1.24 thorpej station */ 179 1.21 onoe struct ieee80211_nwid sc_cnwid; /* last nwid */ 180 1.21 onoe struct ieee80211_nwid sc_dnwid; /* desired nwid */ 181 1.93 msaitoh uint8_t sc_omode; /* old operating mode SC_MODE_xx */ 182 1.93 msaitoh uint8_t sc_mode; /* current operating mode SC_MODE_xx */ 183 1.93 msaitoh uint8_t sc_countrycode; /* current country code */ 184 1.93 msaitoh uint8_t sc_dcountrycode; /* desired country code */ 185 1.28 wiz int sc_havenet; /* true if we have acquired a network */ 186 1.1 chopps bus_size_t sc_txpad; /* tib size plus "phy" size */ 187 1.93 msaitoh uint8_t sc_deftxrate; /* default transfer rate */ 188 1.93 msaitoh uint8_t sc_encrypt; 189 1.93 msaitoh uint8_t sc_authstate; /* authentication state */ 190 1.1 chopps 191 1.1 chopps int sc_promisc; /* current set value */ 192 1.1 chopps int sc_running; /* things we are doing */ 193 1.1 chopps int sc_scheduled; /* things we need to do */ 194 1.1 chopps int sc_timoneed; /* set if timeout is sched */ 195 1.1 chopps int sc_timocheck; /* set if timeout is sched */ 196 1.1 chopps bus_size_t sc_startccs; /* ccs of start/join */ 197 1.1 chopps u_int sc_startcmd; /* cmd (start | join) */ 198 1.1 chopps 199 1.1 chopps int sc_checkcounters; 200 1.93 msaitoh uint64_t sc_rxoverflow; 201 1.93 msaitoh uint64_t sc_rxcksum; 202 1.93 msaitoh uint64_t sc_rxhcksum; 203 1.93 msaitoh uint8_t sc_rxnoise; 204 1.1 chopps 205 1.1 chopps /* use to return values to the user */ 206 1.1 chopps struct ray_param_req *sc_repreq; 207 1.1 chopps struct ray_param_req *sc_updreq; 208 1.14 augustss 209 1.49 mycroft bus_space_tag_t sc_memt; 210 1.49 mycroft bus_space_handle_t sc_memh; 211 1.49 mycroft 212 1.14 augustss #ifdef RAY_DO_SIGLEV 213 1.14 augustss struct ray_siglev sc_siglevs[RAY_NSIGLEVRECS]; 214 1.14 augustss #endif 215 1.1 chopps }; 216 1.1 chopps #define sc_ccrt sc_pf->pf_ccrt 217 1.1 chopps #define sc_ccrh sc_pf->pf_ccrh 218 1.32 martin #define sc_ccroff sc_pf->pf_ccr_offset 219 1.1 chopps #define sc_startup_4 sc_u.u_params_4 220 1.1 chopps #define sc_startup_5 sc_u.u_params_5 221 1.1 chopps #define sc_version sc_ecf_startup.e_fw_build_string 222 1.1 chopps #define sc_tibsize sc_ecf_startup.e_tib_size 223 1.1 chopps #define sc_if sc_ec.ec_if 224 1.1 chopps 225 1.1 chopps /* modes of operation */ 226 1.1 chopps #define SC_MODE_ADHOC 0 /* ad-hoc mode */ 227 1.1 chopps #define SC_MODE_INFRA 1 /* infrastructure mode */ 228 1.1 chopps 229 1.1 chopps /* commands -- priority given to LSB */ 230 1.1 chopps #define SCP_FIRST 0x0001 231 1.1 chopps #define SCP_UPDATESUBCMD 0x0001 232 1.1 chopps #define SCP_STARTASSOC 0x0002 233 1.1 chopps #define SCP_REPORTPARAMS 0x0004 234 1.1 chopps #define SCP_IFSTART 0x0008 235 1.1 chopps 236 1.1 chopps /* update sub commands -- issues are serialized priority to LSB */ 237 1.1 chopps #define SCP_UPD_FIRST 0x0100 238 1.1 chopps #define SCP_UPD_STARTUP 0x0100 239 1.1 chopps #define SCP_UPD_STARTJOIN 0x0200 240 1.1 chopps #define SCP_UPD_PROMISC 0x0400 241 1.1 chopps #define SCP_UPD_MCAST 0x0800 242 1.1 chopps #define SCP_UPD_UPDATEPARAMS 0x1000 243 1.1 chopps #define SCP_UPD_SHIFT 8 244 1.1 chopps #define SCP_UPD_MASK 0xff00 245 1.1 chopps 246 1.1 chopps /* these command (a subset of the update set) require timeout checking */ 247 1.1 chopps #define SCP_TIMOCHECK_CMD_MASK \ 248 1.1 chopps (SCP_UPD_UPDATEPARAMS | SCP_UPD_STARTUP | SCP_UPD_MCAST | \ 249 1.1 chopps SCP_UPD_PROMISC) 250 1.1 chopps 251 1.1 chopps 252 1.1 chopps #define IFM_ADHOC \ 253 1.1 chopps IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_FH2, IFM_IEEE80211_ADHOC, 0) 254 1.1 chopps #define IFM_INFRA \ 255 1.1 chopps IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_FH2, 0, 0) 256 1.1 chopps 257 1.1 chopps typedef void (*ray_cmd_func_t)(struct ray_softc *); 258 1.1 chopps 259 1.1 chopps #define SC_BUILD_5 0x5 260 1.1 chopps #define SC_BUILD_4 0x55 261 1.1 chopps 262 1.24 thorpej /* sc_authstate */ 263 1.24 thorpej #define RAY_AUTH_UNAUTH 0 264 1.24 thorpej #define RAY_AUTH_WAITING 1 265 1.24 thorpej #define RAY_AUTH_AUTH 2 266 1.24 thorpej #define RAY_AUTH_NEEDED 3 267 1.24 thorpej 268 1.24 thorpej #define OPEN_AUTH_REQUEST 1 269 1.24 thorpej #define OPEN_AUTH_RESPONSE 2 270 1.24 thorpej #define BROADCAST_DEAUTH 0xc0 271 1.1 chopps 272 1.55 perry static int ray_alloc_ccs(struct ray_softc *, bus_size_t *, u_int, u_int); 273 1.55 perry static bus_size_t ray_fill_in_tx_ccs(struct ray_softc *, size_t, 274 1.55 perry u_int, u_int); 275 1.55 perry static int ray_validate_config(struct pcmcia_config_entry *); 276 1.75 cegger static void ray_attach(device_t, device_t, void *); 277 1.55 perry static ray_cmd_func_t ray_ccs_done(struct ray_softc *, bus_size_t); 278 1.55 perry static void ray_check_ccs(void *); 279 1.55 perry static void ray_check_scheduled(void *); 280 1.55 perry static void ray_cmd_cancel(struct ray_softc *, int); 281 1.55 perry static void ray_cmd_schedule(struct ray_softc *, int); 282 1.55 perry static void ray_cmd_ran(struct ray_softc *, int); 283 1.55 perry static int ray_cmd_is_running(struct ray_softc *, int); 284 1.55 perry static int ray_cmd_is_scheduled(struct ray_softc *, int); 285 1.55 perry static void ray_cmd_done(struct ray_softc *, int); 286 1.75 cegger static int ray_detach(device_t, int); 287 1.75 cegger static int ray_activate(device_t, enum devact); 288 1.55 perry static void ray_disable(struct ray_softc *); 289 1.55 perry static void ray_download_params(struct ray_softc *); 290 1.55 perry static int ray_enable(struct ray_softc *); 291 1.55 perry static u_int ray_find_free_tx_ccs(struct ray_softc *, u_int); 292 1.93 msaitoh static uint8_t ray_free_ccs(struct ray_softc *, bus_size_t); 293 1.55 perry static void ray_free_ccs_chain(struct ray_softc *, u_int); 294 1.55 perry static void ray_if_start(struct ifnet *); 295 1.68 jmcneill static void ray_if_stop(struct ifnet *, int); 296 1.55 perry static int ray_init(struct ray_softc *); 297 1.55 perry static int ray_intr(void *); 298 1.55 perry static void ray_intr_start(struct ray_softc *); 299 1.64 christos static int ray_ioctl(struct ifnet *, u_long, void *); 300 1.55 perry static int ray_issue_cmd(struct ray_softc *, bus_size_t, u_int); 301 1.75 cegger static int ray_match(device_t, cfdata_t, void *); 302 1.55 perry static int ray_media_change(struct ifnet *); 303 1.55 perry static void ray_media_status(struct ifnet *, struct ifmediareq *); 304 1.55 perry static ray_cmd_func_t ray_rccs_intr(struct ray_softc *, bus_size_t); 305 1.93 msaitoh static void ray_read_region(struct ray_softc *, bus_size_t, void *, size_t); 306 1.55 perry static void ray_recv(struct ray_softc *, bus_size_t); 307 1.55 perry static void ray_recv_auth(struct ray_softc *, struct ieee80211_frame *); 308 1.55 perry static void ray_report_params(struct ray_softc *); 309 1.55 perry static void ray_reset(struct ray_softc *); 310 1.55 perry static void ray_reset_resetloop(void *); 311 1.93 msaitoh static int ray_send_auth(struct ray_softc *, uint8_t *, uint8_t); 312 1.55 perry static void ray_set_pending(struct ray_softc *, u_int); 313 1.55 perry static int ray_simple_cmd(struct ray_softc *, u_int, u_int); 314 1.55 perry static void ray_start_assoc(struct ray_softc *); 315 1.55 perry static void ray_start_join_net(struct ray_softc *); 316 1.55 perry static ray_cmd_func_t ray_start_join_net_done(struct ray_softc *, 317 1.55 perry u_int, bus_size_t, u_int); 318 1.55 perry static void ray_start_join_timo(void *); 319 1.55 perry static void ray_stop(struct ray_softc *); 320 1.55 perry static void ray_update_error_counters(struct ray_softc *); 321 1.55 perry static void ray_update_mcast(struct ray_softc *); 322 1.55 perry static ray_cmd_func_t ray_update_params_done(struct ray_softc *, 323 1.55 perry bus_size_t, u_int); 324 1.55 perry static void ray_update_params(struct ray_softc *); 325 1.55 perry static void ray_update_promisc(struct ray_softc *); 326 1.55 perry static void ray_update_subcmd(struct ray_softc *); 327 1.55 perry static int ray_user_report_params(struct ray_softc *, 328 1.55 perry struct ray_param_req *); 329 1.55 perry static int ray_user_update_params(struct ray_softc *, 330 1.55 perry struct ray_param_req *); 331 1.93 msaitoh static void ray_write_region(struct ray_softc *, bus_size_t, void *, size_t); 332 1.1 chopps 333 1.14 augustss #ifdef RAY_DO_SIGLEV 334 1.93 msaitoh static void ray_update_siglev(struct ray_softc *, uint8_t *, uint8_t); 335 1.14 augustss #endif 336 1.1 chopps 337 1.1 chopps #ifdef RAY_DEBUG 338 1.1 chopps static int ray_debug = 0; 339 1.1 chopps static int ray_debug_xmit_sum = 0; 340 1.1 chopps static int ray_debug_dump_desc = 0; 341 1.1 chopps static int ray_debug_dump_rx = 0; 342 1.1 chopps static int ray_debug_dump_tx = 0; 343 1.1 chopps static struct timeval rtv, tv1, tv2, *ttp, *ltp; 344 1.1 chopps #define RAY_DPRINTF(x) do { if (ray_debug) { \ 345 1.57 christos struct timeval *ttmp; \ 346 1.1 chopps microtime(ttp); \ 347 1.1 chopps timersub(ttp, ltp, &rtv); \ 348 1.57 christos ttmp = ttp; ttp = ltp; ltp = ttmp; \ 349 1.18 kleink printf("%ld:%ld %ld:%06ld: ", \ 350 1.18 kleink (long int)ttp->tv_sec, \ 351 1.18 kleink (long int)ttp->tv_usec, \ 352 1.18 kleink (long int)rtv.tv_sec, \ 353 1.18 kleink (long int)rtv.tv_usec); \ 354 1.1 chopps printf x ; \ 355 1.1 chopps } } while (0) 356 1.1 chopps #define RAY_DPRINTF_XMIT(x) do { if (ray_debug_xmit_sum) { \ 357 1.57 christos struct timeval *ttmp; \ 358 1.1 chopps microtime(ttp); \ 359 1.1 chopps timersub(ttp, ltp, &rtv); \ 360 1.57 christos ttmp = ttp; ttp = ltp; ltp = ttmp; \ 361 1.18 kleink printf("%ld:%ld %ld:%06ld: ", \ 362 1.18 kleink (long int)ttp->tv_sec, \ 363 1.18 kleink (long int)ttp->tv_usec, \ 364 1.18 kleink (long int)rtv.tv_sec, \ 365 1.18 kleink (long int)rtv.tv_usec); \ 366 1.1 chopps printf x ; \ 367 1.1 chopps } } while (0) 368 1.1 chopps 369 1.55 perry static void ray_dump_mbuf(struct ray_softc *, struct mbuf *); 370 1.1 chopps 371 1.1 chopps #else /* !RAY_DEBUG */ 372 1.1 chopps 373 1.1 chopps #define RAY_DPRINTF(x) 374 1.1 chopps #define RAY_DPRINTF_XMIT(x) 375 1.1 chopps 376 1.1 chopps #endif /* !RAY_DEBUG */ 377 1.1 chopps 378 1.1 chopps /* 379 1.1 chopps * macros for writing to various regions in the mapped memory space 380 1.1 chopps */ 381 1.1 chopps 382 1.1 chopps /* use already mapped ccrt */ 383 1.1 chopps #define REG_WRITE(sc, off, val) \ 384 1.32 martin bus_space_write_1((sc)->sc_ccrt, (sc)->sc_ccrh, ((sc)->sc_ccroff + (off)), (val)) 385 1.1 chopps 386 1.1 chopps #define REG_READ(sc, off) \ 387 1.32 martin bus_space_read_1((sc)->sc_ccrt, (sc)->sc_ccrh, ((sc)->sc_ccroff + (off))) 388 1.1 chopps 389 1.1 chopps #define SRAM_READ_1(sc, off) \ 390 1.93 msaitoh ((uint8_t)bus_space_read_1((sc)->sc_memt, (sc)->sc_memh, (off))) 391 1.1 chopps 392 1.1 chopps #define SRAM_READ_FIELD_1(sc, off, s, f) \ 393 1.1 chopps SRAM_READ_1(sc, (off) + offsetof(struct s, f)) 394 1.1 chopps 395 1.1 chopps #define SRAM_READ_FIELD_2(sc, off, s, f) \ 396 1.93 msaitoh ((((uint16_t)SRAM_READ_1(sc, (off) + offsetof(struct s, f)) << 8) \ 397 1.1 chopps |(SRAM_READ_1(sc, (off) + 1 + offsetof(struct s, f))))) 398 1.1 chopps 399 1.1 chopps #define SRAM_READ_FIELD_N(sc, off, s, f, p, n) \ 400 1.1 chopps ray_read_region(sc, (off) + offsetof(struct s, f), (p), (n)) 401 1.1 chopps 402 1.1 chopps #define SRAM_WRITE_1(sc, off, val) \ 403 1.1 chopps bus_space_write_1((sc)->sc_memt, (sc)->sc_memh, (off), (val)) 404 1.1 chopps 405 1.1 chopps #define SRAM_WRITE_FIELD_1(sc, off, s, f, v) \ 406 1.1 chopps SRAM_WRITE_1(sc, (off) + offsetof(struct s, f), (v)) 407 1.1 chopps 408 1.1 chopps #define SRAM_WRITE_FIELD_2(sc, off, s, f, v) do { \ 409 1.1 chopps SRAM_WRITE_1(sc, (off) + offsetof(struct s, f), (((v) >> 8 ) & 0xff)); \ 410 1.1 chopps SRAM_WRITE_1(sc, (off) + 1 + offsetof(struct s, f), ((v) & 0xff)); \ 411 1.1 chopps } while (0) 412 1.1 chopps 413 1.1 chopps #define SRAM_WRITE_FIELD_N(sc, off, s, f, p, n) \ 414 1.1 chopps ray_write_region(sc, (off) + offsetof(struct s, f), (p), (n)) 415 1.1 chopps 416 1.1 chopps /* 417 1.1 chopps * Macros of general usefulness 418 1.1 chopps */ 419 1.1 chopps 420 1.1 chopps #define M_PULLUP(m, s) do { \ 421 1.1 chopps if ((m)->m_len < (s)) \ 422 1.1 chopps (m) = m_pullup((m), (s)); \ 423 1.1 chopps } while (0) 424 1.1 chopps 425 1.1 chopps #define RAY_ECF_READY(sc) (!(REG_READ(sc, RAY_ECFIR) & RAY_ECSIR_IRQ)) 426 1.1 chopps #define RAY_ECF_START_CMD(sc) REG_WRITE(sc, RAY_ECFIR, RAY_ECSIR_IRQ) 427 1.1 chopps #define RAY_GET_INDEX(ccs) (((ccs) - RAY_CCS_BASE) / RAY_CCS_SIZE) 428 1.1 chopps #define RAY_GET_CCS(i) (RAY_CCS_BASE + (i) * RAY_CCS_SIZE) 429 1.1 chopps 430 1.1 chopps /* 431 1.1 chopps * Globals 432 1.1 chopps */ 433 1.1 chopps 434 1.93 msaitoh static uint8_t llc_snapid[6] = { LLC_SNAP_LSAP, LLC_SNAP_LSAP, LLC_UI, }; 435 1.1 chopps 436 1.1 chopps /* based on bit index in SCP_xx */ 437 1.1 chopps static ray_cmd_func_t ray_cmdtab[] = { 438 1.1 chopps ray_update_subcmd, /* SCP_UPDATESUBCMD */ 439 1.1 chopps ray_start_assoc, /* SCP_STARTASSOC */ 440 1.1 chopps ray_report_params, /* SCP_REPORTPARAMS */ 441 1.1 chopps ray_intr_start /* SCP_IFSTART */ 442 1.1 chopps }; 443 1.1 chopps static int ray_ncmdtab = sizeof(ray_cmdtab) / sizeof(*ray_cmdtab); 444 1.1 chopps 445 1.1 chopps static ray_cmd_func_t ray_subcmdtab[] = { 446 1.1 chopps ray_download_params, /* SCP_UPD_STARTUP */ 447 1.1 chopps ray_start_join_net, /* SCP_UPD_STARTJOIN */ 448 1.1 chopps ray_update_promisc, /* SCP_UPD_PROMISC */ 449 1.1 chopps ray_update_mcast, /* SCP_UPD_MCAST */ 450 1.1 chopps ray_update_params /* SCP_UPD_UPDATEPARAMS */ 451 1.1 chopps }; 452 1.1 chopps static int ray_nsubcmdtab = sizeof(ray_subcmdtab) / sizeof(*ray_subcmdtab); 453 1.1 chopps 454 1.1 chopps /* autoconf information */ 455 1.80 chs CFATTACH_DECL_NEW(ray, sizeof(struct ray_softc), 456 1.36 thorpej ray_match, ray_attach, ray_detach, ray_activate); 457 1.1 chopps 458 1.1 chopps /* 459 1.1 chopps * Config Routines 460 1.1 chopps */ 461 1.1 chopps 462 1.1 chopps static int 463 1.75 cegger ray_match(device_t parent, cfdata_t match, 464 1.62 christos void *aux) 465 1.1 chopps { 466 1.1 chopps struct pcmcia_attach_args *pa = aux; 467 1.1 chopps 468 1.1 chopps #ifdef RAY_DEBUG 469 1.1 chopps if (!ltp) { 470 1.1 chopps /* initialize timestamp XXX */ 471 1.1 chopps ttp = &tv1; 472 1.1 chopps ltp = &tv2; 473 1.1 chopps microtime(ltp); 474 1.1 chopps } 475 1.1 chopps #endif 476 1.1 chopps return (pa->manufacturer == PCMCIA_VENDOR_RAYTHEON 477 1.1 chopps && pa->product == PCMCIA_PRODUCT_RAYTHEON_WLAN); 478 1.1 chopps } 479 1.1 chopps 480 1.49 mycroft static int 481 1.72 dsl ray_validate_config(struct pcmcia_config_entry *cfe) 482 1.49 mycroft { 483 1.49 mycroft if (cfe->iftype != PCMCIA_IFTYPE_IO || 484 1.49 mycroft cfe->num_memspace != 1 || 485 1.49 mycroft cfe->num_iospace != 0 || 486 1.49 mycroft cfe->memspace[0].length != RAY_SRAM_MEM_SIZE) 487 1.49 mycroft return (EINVAL); 488 1.49 mycroft return (0); 489 1.49 mycroft } 490 1.1 chopps 491 1.1 chopps static void 492 1.75 cegger ray_attach(device_t parent, device_t self, void *aux) 493 1.1 chopps { 494 1.80 chs struct ray_softc *sc = device_private(self); 495 1.48 mycroft struct pcmcia_attach_args *pa = aux; 496 1.48 mycroft struct ifnet *ifp = &sc->sc_if; 497 1.48 mycroft struct pcmcia_config_entry *cfe; 498 1.1 chopps struct ray_ecf_startup *ep; 499 1.49 mycroft int error; 500 1.1 chopps 501 1.80 chs sc->sc_dev = self; 502 1.48 mycroft sc->sc_pf = pa->pf; 503 1.48 mycroft 504 1.49 mycroft /*XXXmem8|common*/ 505 1.49 mycroft error = pcmcia_function_configure(pa->pf, ray_validate_config); 506 1.49 mycroft if (error) { 507 1.84 msaitoh aprint_error_dev(self, "configure failed, error=%d\n", error); 508 1.49 mycroft return; 509 1.1 chopps } 510 1.1 chopps 511 1.49 mycroft cfe = pa->pf->cfe; 512 1.49 mycroft sc->sc_memt = cfe->memspace[0].handle.memt; 513 1.49 mycroft sc->sc_memh = cfe->memspace[0].handle.memh; 514 1.48 mycroft 515 1.65 ad callout_init(&sc->sc_reset_resetloop_ch, 0); 516 1.65 ad callout_init(&sc->sc_disable_ch, 0); 517 1.65 ad callout_init(&sc->sc_start_join_timo_ch, 0); 518 1.48 mycroft 519 1.49 mycroft error = ray_enable(sc); 520 1.52 mycroft if (error) 521 1.49 mycroft goto fail; 522 1.1 chopps 523 1.1 chopps /* get startup results */ 524 1.1 chopps ep = &sc->sc_ecf_startup; 525 1.1 chopps ray_read_region(sc, RAY_ECF_TO_HOST_BASE, ep, 526 1.1 chopps sizeof(sc->sc_ecf_startup)); 527 1.1 chopps 528 1.1 chopps /* check to see that card initialized properly */ 529 1.1 chopps if (ep->e_status != RAY_ECFS_CARD_OK) { 530 1.70 cegger aprint_error_dev(self, "card failed self test: status %d\n", 531 1.70 cegger sc->sc_ecf_startup.e_status); 532 1.49 mycroft goto fail2; 533 1.1 chopps } 534 1.1 chopps 535 1.1 chopps /* check firmware version */ 536 1.1 chopps if (sc->sc_version != SC_BUILD_4 && sc->sc_version != SC_BUILD_5) { 537 1.70 cegger aprint_error_dev(self, "unsupported firmware version %d\n", 538 1.70 cegger ep->e_fw_build_string); 539 1.49 mycroft goto fail2; 540 1.1 chopps } 541 1.1 chopps 542 1.11 chopps /* clear any interrupt if present */ 543 1.11 chopps REG_WRITE(sc, RAY_HCSIR, 0); 544 1.11 chopps 545 1.1 chopps /* 546 1.1 chopps * set the parameters that will survive stop/init 547 1.1 chopps */ 548 1.21 onoe memset(&sc->sc_dnwid, 0, sizeof(sc->sc_dnwid)); 549 1.21 onoe sc->sc_dnwid.i_len = strlen(RAY_DEF_NWID); 550 1.86 maya memcpy(sc->sc_dnwid.i_nwid, RAY_DEF_NWID, sc->sc_dnwid.i_len); 551 1.21 onoe memcpy(&sc->sc_cnwid, &sc->sc_dnwid, sizeof(sc->sc_cnwid)); 552 1.1 chopps sc->sc_omode = sc->sc_mode = RAY_MODE_DEFAULT; 553 1.20 jhawk sc->sc_countrycode = sc->sc_dcountrycode = 554 1.20 jhawk RAY_PID_COUNTRY_CODE_DEFAULT; 555 1.1 chopps 556 1.1 chopps /* 557 1.1 chopps * attach the interface 558 1.1 chopps */ 559 1.2 augustss /* The version isn't the most accurate way, but it's easy. */ 560 1.70 cegger aprint_normal_dev(self, "firmware version %d\n", 561 1.20 jhawk sc->sc_version); 562 1.11 chopps if (sc->sc_version != SC_BUILD_4) 563 1.84 msaitoh aprint_normal_dev(self, 564 1.84 msaitoh "supported rates %0x:%0x:%0x:%0x:%0x:%0x:%0x:%0x\n", 565 1.70 cegger ep->e_rates[0], ep->e_rates[1], 566 1.11 chopps ep->e_rates[2], ep->e_rates[3], ep->e_rates[4], 567 1.11 chopps ep->e_rates[5], ep->e_rates[6], ep->e_rates[7]); 568 1.70 cegger aprint_normal_dev(self, "802.11 address %s\n", 569 1.1 chopps ether_sprintf(ep->e_station_addr)); 570 1.1 chopps 571 1.70 cegger memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); 572 1.1 chopps ifp->if_softc = sc; 573 1.1 chopps ifp->if_start = ray_if_start; 574 1.68 jmcneill ifp->if_stop = ray_if_stop; 575 1.1 chopps ifp->if_ioctl = ray_ioctl; 576 1.1 chopps ifp->if_mtu = ETHERMTU; 577 1.93 msaitoh ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 578 1.27 thorpej IFQ_SET_READY(&ifp->if_snd); 579 1.27 thorpej 580 1.1 chopps if_attach(ifp); 581 1.1 chopps ether_ifattach(ifp, ep->e_station_addr); 582 1.1 chopps /* need enough space for ieee80211_header + (snap or e2) */ 583 1.1 chopps ifp->if_hdrlen = 584 1.1 chopps sizeof(struct ieee80211_frame) + sizeof(struct ether_header); 585 1.1 chopps 586 1.1 chopps ifmedia_init(&sc->sc_media, 0, ray_media_change, ray_media_status); 587 1.3 chopps ifmedia_add(&sc->sc_media, IFM_ADHOC, 0, 0); 588 1.3 chopps ifmedia_add(&sc->sc_media, IFM_INFRA, 0, 0); 589 1.1 chopps if (sc->sc_mode == SC_MODE_ADHOC) 590 1.1 chopps ifmedia_set(&sc->sc_media, IFM_ADHOC); 591 1.1 chopps else 592 1.1 chopps ifmedia_set(&sc->sc_media, IFM_INFRA); 593 1.1 chopps 594 1.76 tsutsui if (pmf_device_register(self, NULL, NULL)) 595 1.76 tsutsui pmf_class_network_register(self, ifp); 596 1.76 tsutsui else 597 1.68 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 598 1.1 chopps 599 1.20 jhawk /* The attach is successful. */ 600 1.49 mycroft sc->sc_attached = 1; 601 1.48 mycroft ray_disable(sc); 602 1.1 chopps return; 603 1.1 chopps 604 1.49 mycroft fail2: 605 1.48 mycroft ray_disable(sc); 606 1.49 mycroft fail: 607 1.49 mycroft pcmcia_function_unconfigure(pa->pf); 608 1.1 chopps } 609 1.1 chopps 610 1.1 chopps static int 611 1.77 dyoung ray_activate(device_t self, enum devact act) 612 1.7 augustss { 613 1.77 dyoung struct ray_softc *sc = device_private(self); 614 1.7 augustss struct ifnet *ifp = &sc->sc_if; 615 1.7 augustss 616 1.77 dyoung RAY_DPRINTF(("%s: activate\n", device_xname(self))); 617 1.7 augustss 618 1.7 augustss switch (act) { 619 1.7 augustss case DVACT_DEACTIVATE: 620 1.7 augustss if_deactivate(ifp); 621 1.77 dyoung return 0; 622 1.77 dyoung default: 623 1.77 dyoung return EOPNOTSUPP; 624 1.7 augustss } 625 1.7 augustss } 626 1.7 augustss 627 1.7 augustss static int 628 1.75 cegger ray_detach(device_t self, int flags) 629 1.1 chopps { 630 1.1 chopps struct ray_softc *sc; 631 1.7 augustss struct ifnet *ifp; 632 1.1 chopps 633 1.68 jmcneill sc = device_private(self); 634 1.7 augustss ifp = &sc->sc_if; 635 1.80 chs RAY_DPRINTF(("%s: detach\n", device_xname(sc->sc_dev))); 636 1.1 chopps 637 1.49 mycroft if (!sc->sc_attached) 638 1.91 msaitoh return (0); 639 1.48 mycroft 640 1.68 jmcneill pmf_device_deregister(self); 641 1.48 mycroft 642 1.51 mycroft if (sc->sc_if.if_flags & IFF_UP) 643 1.51 mycroft ray_disable(sc); 644 1.1 chopps 645 1.7 augustss ether_ifdetach(ifp); 646 1.7 augustss if_detach(ifp); 647 1.98 thorpej ifmedia_fini(&sc->sc_media); 648 1.48 mycroft 649 1.49 mycroft pcmcia_function_unconfigure(sc->sc_pf); 650 1.7 augustss 651 1.9 chopps return (0); 652 1.1 chopps } 653 1.1 chopps 654 1.1 chopps /* 655 1.1 chopps * start the card running 656 1.1 chopps */ 657 1.1 chopps static int 658 1.72 dsl ray_enable(struct ray_softc *sc) 659 1.1 chopps { 660 1.1 chopps int error; 661 1.1 chopps 662 1.80 chs RAY_DPRINTF(("%s: enable\n", device_xname(sc->sc_dev))); 663 1.1 chopps 664 1.84 msaitoh sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, ray_intr, sc); 665 1.52 mycroft if (!sc->sc_ih) 666 1.47 mycroft return (EIO); 667 1.47 mycroft 668 1.47 mycroft error = ray_init(sc); 669 1.49 mycroft if (error) { 670 1.47 mycroft pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 671 1.49 mycroft sc->sc_ih = 0; 672 1.49 mycroft } 673 1.47 mycroft 674 1.1 chopps return (error); 675 1.1 chopps } 676 1.1 chopps 677 1.1 chopps /* 678 1.1 chopps * stop the card running 679 1.1 chopps */ 680 1.1 chopps static void 681 1.72 dsl ray_disable(struct ray_softc *sc) 682 1.1 chopps { 683 1.80 chs RAY_DPRINTF(("%s: disable\n", device_xname(sc->sc_dev))); 684 1.1 chopps 685 1.51 mycroft ray_stop(sc); 686 1.1 chopps 687 1.1 chopps sc->sc_resetloop = 0; 688 1.1 chopps sc->sc_rxoverflow = 0; 689 1.1 chopps sc->sc_rxcksum = 0; 690 1.1 chopps sc->sc_rxhcksum = 0; 691 1.1 chopps sc->sc_rxnoise = 0; 692 1.1 chopps 693 1.49 mycroft if (sc->sc_ih) { 694 1.1 chopps pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 695 1.49 mycroft sc->sc_ih = 0; 696 1.49 mycroft } 697 1.1 chopps } 698 1.1 chopps 699 1.1 chopps /* 700 1.1 chopps * start the card running 701 1.1 chopps */ 702 1.1 chopps static int 703 1.72 dsl ray_init(struct ray_softc *sc) 704 1.1 chopps { 705 1.1 chopps struct ray_ecf_startup *ep; 706 1.1 chopps bus_size_t ccs; 707 1.1 chopps int i; 708 1.1 chopps 709 1.80 chs RAY_DPRINTF(("%s: init\n", device_xname(sc->sc_dev))); 710 1.1 chopps 711 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING)) 712 1.1 chopps ray_stop(sc); 713 1.1 chopps 714 1.1 chopps if (pcmcia_function_enable(sc->sc_pf)) 715 1.1 chopps return (EIO); 716 1.1 chopps 717 1.80 chs RAY_DPRINTF(("%s: init post-enable\n", device_xname(sc->sc_dev))); 718 1.11 chopps 719 1.1 chopps /* reset some values */ 720 1.1 chopps memset(sc->sc_ccsinuse, 0, sizeof(sc->sc_ccsinuse)); 721 1.1 chopps sc->sc_havenet = 0; 722 1.1 chopps memset(sc->sc_bssid, 0, sizeof(sc->sc_bssid)); 723 1.1 chopps sc->sc_deftxrate = 0; 724 1.1 chopps sc->sc_encrypt = 0; 725 1.1 chopps sc->sc_txpad = 0; 726 1.1 chopps sc->sc_promisc = 0; 727 1.1 chopps sc->sc_scheduled = 0; 728 1.1 chopps sc->sc_running = 0; 729 1.1 chopps sc->sc_txfree = RAY_CCS_NTX; 730 1.1 chopps sc->sc_checkcounters = 0; 731 1.24 thorpej sc->sc_authstate = RAY_AUTH_UNAUTH; 732 1.1 chopps 733 1.1 chopps /* get startup results */ 734 1.1 chopps ep = &sc->sc_ecf_startup; 735 1.1 chopps ray_read_region(sc, RAY_ECF_TO_HOST_BASE, ep, 736 1.1 chopps sizeof(sc->sc_ecf_startup)); 737 1.1 chopps 738 1.1 chopps /* check to see that card initialized properly */ 739 1.1 chopps if (ep->e_status != RAY_ECFS_CARD_OK) { 740 1.1 chopps pcmcia_function_disable(sc->sc_pf); 741 1.1 chopps printf("%s: card failed self test: status %d\n", 742 1.80 chs device_xname(sc->sc_dev), sc->sc_ecf_startup.e_status); 743 1.1 chopps return (EIO); 744 1.1 chopps } 745 1.1 chopps 746 1.1 chopps /* fixup tib size to be correct */ 747 1.1 chopps if (sc->sc_version == SC_BUILD_4 && sc->sc_tibsize == 0x55) 748 1.1 chopps sc->sc_tibsize = 32; 749 1.1 chopps sc->sc_txpad = sc->sc_tibsize; 750 1.1 chopps 751 1.1 chopps /* set all ccs to be free */ 752 1.1 chopps ccs = RAY_GET_CCS(0); 753 1.1 chopps for (i = 0; i < RAY_CCS_LAST; ccs += RAY_CCS_SIZE, i++) 754 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, 755 1.1 chopps RAY_CCS_STATUS_FREE); 756 1.1 chopps 757 1.1 chopps /* clear the interrupt if present */ 758 1.1 chopps REG_WRITE(sc, RAY_HCSIR, 0); 759 1.1 chopps 760 1.65 ad callout_init(&sc->sc_check_ccs_ch, 0); 761 1.65 ad callout_init(&sc->sc_check_scheduled_ch, 0); 762 1.48 mycroft 763 1.1 chopps /* we are now up and running -- and are busy until download is cplt */ 764 1.1 chopps sc->sc_if.if_flags |= IFF_RUNNING | IFF_OACTIVE; 765 1.1 chopps 766 1.1 chopps /* set this now so it gets set in the download */ 767 1.22 thorpej if (sc->sc_if.if_flags & IFF_ALLMULTI) 768 1.22 thorpej sc->sc_if.if_flags |= IFF_PROMISC; 769 1.22 thorpej else if (sc->sc_if.if_pcount == 0) 770 1.22 thorpej sc->sc_if.if_flags &= ~IFF_PROMISC; 771 1.22 thorpej sc->sc_promisc = !!(sc->sc_if.if_flags & IFF_PROMISC); 772 1.1 chopps 773 1.1 chopps /* call after we mark ourselves running */ 774 1.1 chopps ray_download_params(sc); 775 1.1 chopps 776 1.1 chopps return (0); 777 1.1 chopps } 778 1.1 chopps 779 1.1 chopps /* 780 1.1 chopps * stop the card running 781 1.1 chopps */ 782 1.1 chopps static void 783 1.72 dsl ray_stop(struct ray_softc *sc) 784 1.1 chopps { 785 1.80 chs RAY_DPRINTF(("%s: stop\n", device_xname(sc->sc_dev))); 786 1.1 chopps 787 1.17 thorpej callout_stop(&sc->sc_check_ccs_ch); 788 1.1 chopps sc->sc_timocheck = 0; 789 1.1 chopps 790 1.17 thorpej callout_stop(&sc->sc_check_scheduled_ch); 791 1.1 chopps sc->sc_timoneed = 0; 792 1.1 chopps 793 1.1 chopps if (sc->sc_repreq) { 794 1.1 chopps sc->sc_repreq->r_failcause = RAY_FAILCAUSE_EDEVSTOP; 795 1.1 chopps wakeup(ray_report_params); 796 1.1 chopps } 797 1.1 chopps if (sc->sc_updreq) { 798 1.60 christos sc->sc_updreq->r_failcause = RAY_FAILCAUSE_EDEVSTOP; 799 1.1 chopps wakeup(ray_update_params); 800 1.1 chopps } 801 1.1 chopps 802 1.1 chopps sc->sc_if.if_flags &= ~IFF_RUNNING; 803 1.1 chopps pcmcia_function_disable(sc->sc_pf); 804 1.1 chopps } 805 1.1 chopps 806 1.1 chopps /* 807 1.1 chopps * reset the card 808 1.1 chopps */ 809 1.1 chopps static void 810 1.72 dsl ray_reset(struct ray_softc *sc) 811 1.1 chopps { 812 1.1 chopps if (++sc->sc_resetloop >= RAY_MAX_RESETS) { 813 1.1 chopps if (sc->sc_resetloop == RAY_MAX_RESETS) { 814 1.84 msaitoh aprint_error_dev(sc->sc_dev, 815 1.84 msaitoh "unable to correct, disabling\n"); 816 1.17 thorpej callout_stop(&sc->sc_reset_resetloop_ch); 817 1.17 thorpej callout_reset(&sc->sc_disable_ch, 1, 818 1.17 thorpej (void (*)(void *))ray_disable, sc); 819 1.1 chopps } 820 1.1 chopps } else { 821 1.84 msaitoh aprint_error_dev(sc->sc_dev, 822 1.84 msaitoh "unexpected failure resetting hw [%d more]\n", 823 1.70 cegger RAY_MAX_RESETS - sc->sc_resetloop); 824 1.17 thorpej callout_stop(&sc->sc_reset_resetloop_ch); 825 1.1 chopps ray_init(sc); 826 1.17 thorpej callout_reset(&sc->sc_reset_resetloop_ch, 30 * hz, 827 1.17 thorpej ray_reset_resetloop, sc); 828 1.1 chopps } 829 1.1 chopps } 830 1.1 chopps 831 1.1 chopps /* 832 1.1 chopps * return resetloop to zero (enough time has expired to allow user to 833 1.1 chopps * disable a whacked interface) the main reason for all this nonesense 834 1.1 chopps * is that resets take ~2 seconds and currently the pcmcia code spins 835 1.1 chopps * on these resets 836 1.1 chopps */ 837 1.1 chopps static void 838 1.72 dsl ray_reset_resetloop(void *arg) 839 1.1 chopps { 840 1.1 chopps struct ray_softc *sc; 841 1.1 chopps 842 1.1 chopps sc = arg; 843 1.1 chopps sc->sc_resetloop = 0; 844 1.1 chopps } 845 1.1 chopps 846 1.1 chopps static int 847 1.71 dyoung ray_ioctl(struct ifnet *ifp, u_long cmd, void *data) 848 1.1 chopps { 849 1.21 onoe struct ieee80211_nwid nwid; 850 1.1 chopps struct ray_param_req pr; 851 1.1 chopps struct ray_softc *sc; 852 1.1 chopps struct ifreq *ifr; 853 1.1 chopps struct ifaddr *ifa; 854 1.21 onoe int error, error2, s, i; 855 1.1 chopps 856 1.1 chopps sc = ifp->if_softc; 857 1.1 chopps error = 0; 858 1.1 chopps 859 1.1 chopps ifr = (struct ifreq *)data; 860 1.1 chopps 861 1.1 chopps s = splnet(); 862 1.1 chopps 863 1.1 chopps RAY_DPRINTF(("%s: ioctl: cmd 0x%lx data 0x%lx\n", ifp->if_xname, 864 1.1 chopps cmd, (long)data)); 865 1.1 chopps switch (cmd) { 866 1.71 dyoung case SIOCINITIFADDR: 867 1.71 dyoung RAY_DPRINTF(("%s: ioctl: cmd SIOCINITIFADDR\n", ifp->if_xname)); 868 1.1 chopps if ((ifp->if_flags & IFF_RUNNING) == 0) 869 1.1 chopps if ((error = ray_enable(sc))) 870 1.1 chopps break; 871 1.1 chopps ifp->if_flags |= IFF_UP; 872 1.1 chopps ifa = (struct ifaddr *)data; 873 1.1 chopps switch (ifa->ifa_addr->sa_family) { 874 1.1 chopps #ifdef INET 875 1.1 chopps case AF_INET: 876 1.1 chopps arp_ifinit(&sc->sc_if, ifa); 877 1.1 chopps break; 878 1.1 chopps #endif 879 1.1 chopps default: 880 1.1 chopps break; 881 1.1 chopps } 882 1.1 chopps break; 883 1.1 chopps case SIOCSIFFLAGS: 884 1.1 chopps RAY_DPRINTF(("%s: ioctl: cmd SIOCSIFFLAGS\n", ifp->if_xname)); 885 1.71 dyoung if ((error = ifioctl_common(ifp, cmd, data)) != 0) 886 1.71 dyoung break; 887 1.1 chopps if (ifp->if_flags & IFF_UP) { 888 1.1 chopps if ((ifp->if_flags & IFF_RUNNING) == 0) { 889 1.1 chopps if ((error = ray_enable(sc))) 890 1.1 chopps break; 891 1.56 perry } else 892 1.1 chopps ray_update_promisc(sc); 893 1.1 chopps } else if (ifp->if_flags & IFF_RUNNING) 894 1.1 chopps ray_disable(sc); 895 1.1 chopps break; 896 1.1 chopps case SIOCADDMULTI: 897 1.1 chopps RAY_DPRINTF(("%s: ioctl: cmd SIOCADDMULTI\n", ifp->if_xname)); 898 1.92 mrg /* FALLTHROUGH */ 899 1.1 chopps case SIOCDELMULTI: 900 1.1 chopps if (cmd == SIOCDELMULTI) 901 1.1 chopps RAY_DPRINTF(("%s: ioctl: cmd SIOCDELMULTI\n", 902 1.1 chopps ifp->if_xname)); 903 1.66 dyoung if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 904 1.54 thorpej if (ifp->if_flags & IFF_RUNNING) 905 1.54 thorpej ray_update_mcast(sc); 906 1.1 chopps error = 0; 907 1.1 chopps } 908 1.15 mycroft break; 909 1.1 chopps case SIOCSIFMEDIA: 910 1.1 chopps RAY_DPRINTF(("%s: ioctl: cmd SIOCSIFMEDIA\n", ifp->if_xname)); 911 1.92 mrg /* FALLTHROUGH */ 912 1.1 chopps case SIOCGIFMEDIA: 913 1.1 chopps if (cmd == SIOCGIFMEDIA) 914 1.1 chopps RAY_DPRINTF(("%s: ioctl: cmd SIOCGIFMEDIA\n", 915 1.1 chopps ifp->if_xname)); 916 1.1 chopps error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 917 1.1 chopps break; 918 1.1 chopps case SIOCSRAYPARAM: 919 1.1 chopps RAY_DPRINTF(("%s: ioctl: cmd SIOCSRAYPARAM\n", ifp->if_xname)); 920 1.1 chopps if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr)))) 921 1.1 chopps break; 922 1.1 chopps /* disallow certain command that have another interface */ 923 1.1 chopps switch (pr.r_paramid) { 924 1.1 chopps case RAY_PID_NET_TYPE: /* through media opt */ 925 1.1 chopps case RAY_PID_AP_STATUS: /* unsupported */ 926 1.1 chopps case RAY_PID_SSID: /* use SIOC80211[GS]NWID */ 927 1.1 chopps case RAY_PID_MAC_ADDR: /* XXX need interface? */ 928 1.1 chopps case RAY_PID_PROMISC: /* bpf */ 929 1.1 chopps error = EINVAL; 930 1.1 chopps break; 931 1.1 chopps } 932 1.1 chopps error = ray_user_update_params(sc, &pr); 933 1.1 chopps error2 = copyout(&pr, ifr->ifr_data, sizeof(pr)); 934 1.1 chopps error = error2 ? error2 : error; 935 1.1 chopps break; 936 1.1 chopps case SIOCGRAYPARAM: 937 1.1 chopps RAY_DPRINTF(("%s: ioctl: cmd SIOCGRAYPARAM\n", ifp->if_xname)); 938 1.1 chopps if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr)))) 939 1.1 chopps break; 940 1.1 chopps error = ray_user_report_params(sc, &pr); 941 1.1 chopps error2 = copyout(&pr, ifr->ifr_data, sizeof(pr)); 942 1.1 chopps error = error2 ? error2 : error; 943 1.1 chopps break; 944 1.1 chopps case SIOCS80211NWID: 945 1.21 onoe RAY_DPRINTF(("%s: ioctl: cmd SIOCS80211NWID\n", ifp->if_xname)); 946 1.1 chopps /* 947 1.1 chopps * if later people overwrite thats ok -- the latest version 948 1.1 chopps * will always get start/joined even if it was set by 949 1.1 chopps * a previous command 950 1.1 chopps */ 951 1.21 onoe if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid)))) 952 1.1 chopps break; 953 1.21 onoe if (nwid.i_len > IEEE80211_NWID_LEN) { 954 1.21 onoe error = EINVAL; 955 1.21 onoe break; 956 1.21 onoe } 957 1.21 onoe /* clear trailing garbages */ 958 1.21 onoe for (i = nwid.i_len; i < IEEE80211_NWID_LEN; i++) 959 1.21 onoe nwid.i_nwid[i] = 0; 960 1.21 onoe if (!memcmp(&sc->sc_dnwid, &nwid, sizeof(nwid))) 961 1.1 chopps break; 962 1.21 onoe memcpy(&sc->sc_dnwid, &nwid, sizeof(nwid)); 963 1.1 chopps if (ifp->if_flags & IFF_RUNNING) 964 1.1 chopps ray_start_join_net(sc); 965 1.1 chopps break; 966 1.1 chopps case SIOCG80211NWID: 967 1.21 onoe RAY_DPRINTF(("%s: ioctl: cmd SIOCG80211NWID\n", ifp->if_xname)); 968 1.21 onoe error = copyout(&sc->sc_cnwid, ifr->ifr_data, 969 1.21 onoe sizeof(sc->sc_cnwid)); 970 1.1 chopps break; 971 1.14 augustss #ifdef RAY_DO_SIGLEV 972 1.14 augustss case SIOCGRAYSIGLEV: 973 1.56 perry error = copyout(sc->sc_siglevs, ifr->ifr_data, 974 1.14 augustss sizeof sc->sc_siglevs); 975 1.14 augustss break; 976 1.14 augustss #endif 977 1.1 chopps default: 978 1.1 chopps RAY_DPRINTF(("%s: ioctl: unknown\n", ifp->if_xname)); 979 1.71 dyoung error = ether_ioctl(ifp, cmd, data); 980 1.1 chopps break; 981 1.1 chopps } 982 1.1 chopps 983 1.3 chopps RAY_DPRINTF(("%s: ioctl: returns %d\n", ifp->if_xname, error)); 984 1.3 chopps 985 1.1 chopps splx(s); 986 1.1 chopps 987 1.1 chopps return (error); 988 1.1 chopps } 989 1.1 chopps 990 1.1 chopps /* 991 1.1 chopps * ifnet interface to start transmission on the interface 992 1.1 chopps */ 993 1.1 chopps static void 994 1.72 dsl ray_if_start(struct ifnet *ifp) 995 1.1 chopps { 996 1.1 chopps struct ray_softc *sc; 997 1.1 chopps 998 1.1 chopps sc = ifp->if_softc; 999 1.1 chopps ray_intr_start(sc); 1000 1.1 chopps } 1001 1.1 chopps 1002 1.68 jmcneill static void 1003 1.68 jmcneill ray_if_stop(struct ifnet *ifp, int disable) 1004 1.68 jmcneill { 1005 1.68 jmcneill struct ray_softc *sc = ifp->if_softc; 1006 1.68 jmcneill 1007 1.68 jmcneill ray_stop(sc); 1008 1.68 jmcneill } 1009 1.68 jmcneill 1010 1.1 chopps static int 1011 1.72 dsl ray_media_change(struct ifnet *ifp) 1012 1.1 chopps { 1013 1.3 chopps struct ray_softc *sc; 1014 1.3 chopps 1015 1.3 chopps sc = ifp->if_softc; 1016 1.3 chopps RAY_DPRINTF(("%s: media change cur %d\n", ifp->if_xname, 1017 1.3 chopps sc->sc_media.ifm_cur->ifm_media)); 1018 1.3 chopps if (sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) 1019 1.3 chopps sc->sc_mode = SC_MODE_ADHOC; 1020 1.3 chopps else 1021 1.3 chopps sc->sc_mode = SC_MODE_INFRA; 1022 1.3 chopps if (sc->sc_mode != sc->sc_omode) 1023 1.3 chopps ray_start_join_net(sc); 1024 1.1 chopps return (0); 1025 1.1 chopps } 1026 1.1 chopps 1027 1.1 chopps static void 1028 1.72 dsl ray_media_status(struct ifnet *ifp, struct ifmediareq *imr) 1029 1.1 chopps { 1030 1.1 chopps struct ray_softc *sc; 1031 1.1 chopps 1032 1.1 chopps sc = ifp->if_softc; 1033 1.1 chopps 1034 1.3 chopps RAY_DPRINTF(("%s: media status\n", ifp->if_xname)); 1035 1.3 chopps 1036 1.1 chopps imr->ifm_status = IFM_AVALID; 1037 1.1 chopps if (sc->sc_havenet) 1038 1.1 chopps imr->ifm_status |= IFM_ACTIVE; 1039 1.1 chopps 1040 1.1 chopps if (sc->sc_mode == SC_MODE_ADHOC) 1041 1.1 chopps imr->ifm_active = IFM_ADHOC; 1042 1.1 chopps else 1043 1.1 chopps imr->ifm_active = IFM_INFRA; 1044 1.1 chopps } 1045 1.1 chopps 1046 1.1 chopps /* 1047 1.1 chopps * called to start from ray_intr. We don't check for pending 1048 1.1 chopps * interrupt as a result 1049 1.1 chopps */ 1050 1.1 chopps static void 1051 1.72 dsl ray_intr_start(struct ray_softc *sc) 1052 1.1 chopps { 1053 1.1 chopps struct ieee80211_frame *iframe; 1054 1.1 chopps struct ether_header *eh; 1055 1.43 mycroft size_t len, pktlen, tmplen; 1056 1.1 chopps bus_size_t bufp, ebufp; 1057 1.1 chopps struct mbuf *m0, *m; 1058 1.1 chopps struct ifnet *ifp; 1059 1.9 chopps u_int firsti, hinti, previ, i, pcount; 1060 1.93 msaitoh uint16_t et; 1061 1.93 msaitoh uint8_t *d; 1062 1.1 chopps 1063 1.1 chopps ifp = &sc->sc_if; 1064 1.1 chopps 1065 1.27 thorpej RAY_DPRINTF(("%s: start free %d\n", 1066 1.27 thorpej ifp->if_xname, sc->sc_txfree)); 1067 1.1 chopps 1068 1.1 chopps ray_cmd_cancel(sc, SCP_IFSTART); 1069 1.1 chopps 1070 1.1 chopps if ((ifp->if_flags & IFF_RUNNING) == 0 || !sc->sc_havenet) 1071 1.1 chopps return; 1072 1.1 chopps 1073 1.27 thorpej if (IFQ_IS_EMPTY(&ifp->if_snd)) 1074 1.1 chopps return; 1075 1.1 chopps 1076 1.1 chopps firsti = i = previ = RAY_CCS_LINK_NULL; 1077 1.1 chopps hinti = RAY_CCS_TX_FIRST; 1078 1.1 chopps 1079 1.1 chopps if (!RAY_ECF_READY(sc)) { 1080 1.1 chopps ray_cmd_schedule(sc, SCP_IFSTART); 1081 1.1 chopps return; 1082 1.1 chopps } 1083 1.1 chopps 1084 1.24 thorpej /* Check to see if we need to authenticate before sending packets. */ 1085 1.24 thorpej if (sc->sc_authstate == RAY_AUTH_NEEDED) { 1086 1.24 thorpej RAY_DPRINTF(("%s: Sending auth request.\n", ifp->if_xname)); 1087 1.24 thorpej sc->sc_authstate = RAY_AUTH_WAITING; 1088 1.24 thorpej ray_send_auth(sc, sc->sc_authid, OPEN_AUTH_REQUEST); 1089 1.24 thorpej return; 1090 1.24 thorpej } 1091 1.24 thorpej 1092 1.9 chopps pcount = 0; 1093 1.1 chopps for (;;) { 1094 1.1 chopps /* if we have no descriptors be done */ 1095 1.1 chopps if (i == RAY_CCS_LINK_NULL) { 1096 1.1 chopps i = ray_find_free_tx_ccs(sc, hinti); 1097 1.1 chopps if (i == RAY_CCS_LINK_NULL) { 1098 1.24 thorpej RAY_DPRINTF(("%s: no descriptors.\n", 1099 1.24 thorpej ifp->if_xname)); 1100 1.1 chopps ifp->if_flags |= IFF_OACTIVE; 1101 1.1 chopps break; 1102 1.1 chopps } 1103 1.1 chopps } 1104 1.1 chopps 1105 1.27 thorpej IFQ_DEQUEUE(&ifp->if_snd, m0); 1106 1.24 thorpej if (!m0) { 1107 1.24 thorpej RAY_DPRINTF(("%s: dry queue.\n", ifp->if_xname)); 1108 1.1 chopps break; 1109 1.24 thorpej } 1110 1.1 chopps RAY_DPRINTF(("%s: gotmbuf 0x%lx\n", ifp->if_xname, (long)m0)); 1111 1.1 chopps pktlen = m0->m_pkthdr.len; 1112 1.1 chopps if (pktlen > ETHER_MAX_LEN - ETHER_CRC_LEN) { 1113 1.1 chopps RAY_DPRINTF(( 1114 1.13 thorpej "%s: mbuf too long %ld\n", ifp->if_xname, 1115 1.13 thorpej (u_long)pktlen)); 1116 1.97 thorpej if_statinc(ifp, if_oerrors); 1117 1.1 chopps m_freem(m0); 1118 1.1 chopps continue; 1119 1.1 chopps } 1120 1.1 chopps RAY_DPRINTF(("%s: mbuf.m_pkthdr.len %d\n", ifp->if_xname, 1121 1.1 chopps (int)pktlen)); 1122 1.1 chopps 1123 1.1 chopps /* we need the ether_header now for pktlen adjustments */ 1124 1.1 chopps M_PULLUP(m0, sizeof(struct ether_header)); 1125 1.1 chopps if (!m0) { 1126 1.1 chopps RAY_DPRINTF(( "%s: couldn\'t pullup ether header\n", 1127 1.1 chopps ifp->if_xname)); 1128 1.97 thorpej if_statinc(ifp, if_oerrors); 1129 1.1 chopps continue; 1130 1.1 chopps } 1131 1.1 chopps RAY_DPRINTF(("%s: got pulled up mbuf 0x%lx\n", ifp->if_xname, 1132 1.1 chopps (long)m0)); 1133 1.1 chopps 1134 1.1 chopps /* first peek at the type of packet and figure out what to do */ 1135 1.1 chopps eh = mtod(m0, struct ether_header *); 1136 1.1 chopps et = ntohs(eh->ether_type); 1137 1.1 chopps if (ifp->if_flags & IFF_LINK0) { 1138 1.1 chopps /* don't support llc for windows compat operation */ 1139 1.1 chopps if (et <= ETHERMTU) { 1140 1.1 chopps m_freem(m0); 1141 1.97 thorpej if_statinc(ifp, if_oerrors); 1142 1.1 chopps continue; 1143 1.1 chopps } 1144 1.1 chopps tmplen = sizeof(struct ieee80211_frame); 1145 1.1 chopps } else if (et > ETHERMTU) { 1146 1.1 chopps /* adjust for LLC/SNAP header */ 1147 1.84 msaitoh tmplen = sizeof(struct ieee80211_frame) 1148 1.84 msaitoh - ETHER_ADDR_LEN; 1149 1.40 christos } else { 1150 1.40 christos tmplen = 0; 1151 1.1 chopps } 1152 1.1 chopps /* now get our space for the 802.11 frame */ 1153 1.1 chopps M_PREPEND(m0, tmplen, M_DONTWAIT); 1154 1.1 chopps if (m0) 1155 1.1 chopps M_PULLUP(m0, sizeof(struct ether_header) + tmplen); 1156 1.1 chopps if (!m0) { 1157 1.1 chopps RAY_DPRINTF(("%s: couldn\'t prepend header\n", 1158 1.1 chopps ifp->if_xname)); 1159 1.97 thorpej if_statinc(ifp, if_oerrors); 1160 1.1 chopps continue; 1161 1.1 chopps } 1162 1.1 chopps /* copy the frame into the mbuf for tapping */ 1163 1.1 chopps iframe = mtod(m0, struct ieee80211_frame *); 1164 1.93 msaitoh eh = (struct ether_header *)((uint8_t *)iframe + tmplen); 1165 1.1 chopps iframe->i_fc[0] = 1166 1.1 chopps (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA); 1167 1.3 chopps if (sc->sc_mode == SC_MODE_ADHOC) { 1168 1.16 onoe iframe->i_fc[1] = IEEE80211_FC1_DIR_NODS; 1169 1.3 chopps memcpy(iframe->i_addr1, eh->ether_dhost,ETHER_ADDR_LEN); 1170 1.3 chopps memcpy(iframe->i_addr2, eh->ether_shost,ETHER_ADDR_LEN); 1171 1.3 chopps memcpy(iframe->i_addr3, sc->sc_bssid, ETHER_ADDR_LEN); 1172 1.3 chopps } else { 1173 1.16 onoe iframe->i_fc[1] = IEEE80211_FC1_DIR_TODS; 1174 1.93 msaitoh memcpy(iframe->i_addr1, sc->sc_bssid, ETHER_ADDR_LEN); 1175 1.3 chopps memcpy(iframe->i_addr2, eh->ether_shost,ETHER_ADDR_LEN); 1176 1.3 chopps memmove(iframe->i_addr3,eh->ether_dhost,ETHER_ADDR_LEN); 1177 1.3 chopps } 1178 1.1 chopps iframe->i_dur[0] = iframe->i_dur[1] = 0; 1179 1.1 chopps iframe->i_seq[0] = iframe->i_seq[1] = 0; 1180 1.1 chopps 1181 1.1 chopps /* if not using crummy E2 in 802.11 make it LLC/SNAP */ 1182 1.1 chopps if ((ifp->if_flags & IFF_LINK0) == 0 && et > ETHERMTU) 1183 1.1 chopps memcpy(iframe + 1, llc_snapid, sizeof(llc_snapid)); 1184 1.1 chopps 1185 1.1 chopps RAY_DPRINTF(("%s: i %d previ %d\n", ifp->if_xname, i, previ)); 1186 1.1 chopps 1187 1.1 chopps if (firsti == RAY_CCS_LINK_NULL) 1188 1.1 chopps firsti = i; 1189 1.1 chopps 1190 1.1 chopps pktlen = m0->m_pkthdr.len; 1191 1.1 chopps bufp = ray_fill_in_tx_ccs(sc, pktlen, i, previ); 1192 1.1 chopps previ = hinti = i; 1193 1.1 chopps i = RAY_CCS_LINK_NULL; 1194 1.1 chopps 1195 1.1 chopps RAY_DPRINTF(("%s: bufp 0x%lx new pktlen %d\n", 1196 1.1 chopps ifp->if_xname, (long)bufp, (int)pktlen)); 1197 1.56 perry 1198 1.1 chopps /* copy out mbuf */ 1199 1.1 chopps for (m = m0; m; m = m->m_next) { 1200 1.1 chopps if ((len = m->m_len) == 0) 1201 1.1 chopps continue; 1202 1.1 chopps RAY_DPRINTF(( 1203 1.1 chopps "%s: copying mbuf 0x%lx bufp 0x%lx len %d\n", 1204 1.1 chopps ifp->if_xname, (long)m, (long)bufp, (int)len)); 1205 1.93 msaitoh d = mtod(m, uint8_t *); 1206 1.1 chopps ebufp = bufp + len; 1207 1.1 chopps if (ebufp <= RAY_TX_END) 1208 1.1 chopps ray_write_region(sc, bufp, d, len); 1209 1.1 chopps else { 1210 1.1 chopps panic("ray_intr_start"); /* XXX */ 1211 1.1 chopps /* wrapping */ 1212 1.56 perry tmplen = ebufp - bufp; 1213 1.1 chopps len -= tmplen; 1214 1.1 chopps ray_write_region(sc, bufp, d, tmplen); 1215 1.1 chopps d += tmplen; 1216 1.1 chopps bufp = RAY_TX_BASE; 1217 1.1 chopps ray_write_region(sc, bufp, d, len); 1218 1.1 chopps } 1219 1.1 chopps bufp += len; 1220 1.1 chopps } 1221 1.1 chopps if (ifp->if_bpf) { 1222 1.1 chopps if (ifp->if_flags & IFF_LINK0) { 1223 1.1 chopps m0->m_data += sizeof(struct ieee80211_frame); 1224 1.1 chopps m0->m_len -= sizeof(struct ieee80211_frame); 1225 1.1 chopps m0->m_pkthdr.len -= sizeof(struct ieee80211_frame); 1226 1.1 chopps } 1227 1.90 msaitoh bpf_mtap(ifp, m0, BPF_D_OUT); 1228 1.1 chopps if (ifp->if_flags & IFF_LINK0) { 1229 1.1 chopps m0->m_data -= sizeof(struct ieee80211_frame); 1230 1.1 chopps m0->m_len += sizeof(struct ieee80211_frame); 1231 1.1 chopps m0->m_pkthdr.len += sizeof(struct ieee80211_frame); 1232 1.1 chopps } 1233 1.1 chopps } 1234 1.1 chopps 1235 1.1 chopps #ifdef RAY_DEBUG 1236 1.1 chopps if (ray_debug && ray_debug_dump_tx) 1237 1.1 chopps ray_dump_mbuf(sc, m0); 1238 1.1 chopps #endif 1239 1.9 chopps pcount++; 1240 1.1 chopps m_freem(m0); 1241 1.43 mycroft 1242 1.84 msaitoh RAY_DPRINTF_XMIT(("%s: sent packet: len %ld\n", 1243 1.84 msaitoh device_xname(sc->sc_dev), (u_long)pktlen)); 1244 1.1 chopps } 1245 1.1 chopps 1246 1.1 chopps if (firsti == RAY_CCS_LINK_NULL) 1247 1.1 chopps return; 1248 1.1 chopps i = 0; 1249 1.1 chopps if (!RAY_ECF_READY(sc)) { 1250 1.1 chopps /* 1251 1.1 chopps * if this can really happen perhaps we need to save 1252 1.1 chopps * the chain and use it later. I think this might 1253 1.1 chopps * be a confused state though because we check above 1254 1.1 chopps * and don't issue any commands between. 1255 1.1 chopps */ 1256 1.84 msaitoh printf("%s: dropping tx packets device busy\n", 1257 1.84 msaitoh device_xname(sc->sc_dev)); 1258 1.1 chopps ray_free_ccs_chain(sc, firsti); 1259 1.97 thorpej if_statadd(ifp, if_oerrors, pcount); 1260 1.1 chopps return; 1261 1.1 chopps } 1262 1.1 chopps 1263 1.1 chopps /* send it off */ 1264 1.84 msaitoh RAY_DPRINTF(("%s: ray_start issuing %d \n", device_xname(sc->sc_dev), 1265 1.84 msaitoh firsti)); 1266 1.1 chopps SRAM_WRITE_1(sc, RAY_SCB_CCSI, firsti); 1267 1.1 chopps RAY_ECF_START_CMD(sc); 1268 1.9 chopps 1269 1.97 thorpej if_statadd(ifp, if_opackets, pcount); 1270 1.1 chopps } 1271 1.1 chopps 1272 1.1 chopps /* 1273 1.100 andvar * receive a packet from the card 1274 1.1 chopps */ 1275 1.1 chopps static void 1276 1.72 dsl ray_recv(struct ray_softc *sc, bus_size_t ccs) 1277 1.1 chopps { 1278 1.1 chopps struct ieee80211_frame *frame; 1279 1.1 chopps struct ether_header *eh; 1280 1.1 chopps struct mbuf *m; 1281 1.41 christos size_t pktlen, fudge, len, lenread = 0; 1282 1.1 chopps bus_size_t bufp, ebufp, tmp; 1283 1.1 chopps struct ifnet *ifp; 1284 1.93 msaitoh uint8_t *src, *d; 1285 1.41 christos u_int frag = 0, ni, i, issnap, first; 1286 1.93 msaitoh uint8_t fc0; 1287 1.14 augustss #ifdef RAY_DO_SIGLEV 1288 1.93 msaitoh uint8_t siglev; 1289 1.14 augustss #endif 1290 1.1 chopps 1291 1.1 chopps #ifdef RAY_DEBUG 1292 1.1 chopps /* have a look if you want to see how the card rx works :) */ 1293 1.1 chopps if (ray_debug && ray_debug_dump_desc) 1294 1.88 christos hexdump(printf, __func__, (char *)sc->sc_memh + RAY_RCS_BASE, 1295 1.88 christos 0x400); 1296 1.1 chopps #endif 1297 1.1 chopps 1298 1.1 chopps m = 0; 1299 1.1 chopps ifp = &sc->sc_if; 1300 1.1 chopps 1301 1.19 thorpej /* 1302 1.19 thorpej * If we're expecting the E2-in-802.11 encapsulation that the 1303 1.19 thorpej * WebGear Windows driver produces, fudge the packet forward 1304 1.19 thorpej * in the mbuf by 2 bytes so that the payload after the 1305 1.19 thorpej * Ethernet header will be aligned. If we end up getting a 1306 1.19 thorpej * packet that's not of this type, we'll just drop it anyway. 1307 1.19 thorpej */ 1308 1.19 thorpej if (ifp->if_flags & IFF_LINK0) 1309 1.19 thorpej fudge = 2; 1310 1.19 thorpej else 1311 1.19 thorpej fudge = 0; 1312 1.19 thorpej 1313 1.1 chopps /* it looks like at least with build 4 there is no CRC in length */ 1314 1.1 chopps first = RAY_GET_INDEX(ccs); 1315 1.1 chopps pktlen = SRAM_READ_FIELD_2(sc, ccs, ray_cmd_rx, c_pktlen); 1316 1.14 augustss #ifdef RAY_DO_SIGLEV 1317 1.14 augustss siglev = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_rx, c_siglev); 1318 1.14 augustss #endif 1319 1.1 chopps 1320 1.80 chs RAY_DPRINTF(("%s: recv pktlen %ld frag %d\n", device_xname(sc->sc_dev), 1321 1.41 christos (u_long)pktlen, frag)); 1322 1.84 msaitoh RAY_DPRINTF_XMIT(("%s: received packet: len %ld\n", 1323 1.84 msaitoh device_xname(sc->sc_dev), (u_long)pktlen)); 1324 1.24 thorpej if (pktlen > MCLBYTES || pktlen < sizeof(*frame)) { 1325 1.1 chopps RAY_DPRINTF(("%s: PKTLEN TOO BIG OR TOO SMALL\n", 1326 1.80 chs device_xname(sc->sc_dev))); 1327 1.97 thorpej if_statinc(ifp, if_ierrors); 1328 1.1 chopps goto done; 1329 1.1 chopps } 1330 1.1 chopps MGETHDR(m, M_DONTWAIT, MT_DATA); 1331 1.1 chopps if (!m) { 1332 1.80 chs RAY_DPRINTF(("%s: MGETHDR FAILED\n", device_xname(sc->sc_dev))); 1333 1.97 thorpej if_statinc(ifp, if_ierrors); 1334 1.1 chopps goto done; 1335 1.1 chopps } 1336 1.19 thorpej if ((pktlen + fudge) > MHLEN) { 1337 1.1 chopps /* XXX should allow chaining? */ 1338 1.1 chopps MCLGET(m, M_DONTWAIT); 1339 1.1 chopps if ((m->m_flags & M_EXT) == 0) { 1340 1.84 msaitoh RAY_DPRINTF(("%s: MCLGET FAILED\n", 1341 1.84 msaitoh device_xname(sc->sc_dev))); 1342 1.97 thorpej if_statinc(ifp, if_ierrors); 1343 1.1 chopps m_freem(m); 1344 1.1 chopps m = 0; 1345 1.1 chopps goto done; 1346 1.1 chopps } 1347 1.1 chopps } 1348 1.83 ozaki m_set_rcvif(m, ifp); 1349 1.1 chopps m->m_pkthdr.len = pktlen; 1350 1.1 chopps m->m_len = pktlen; 1351 1.19 thorpej m->m_data += fudge; 1352 1.93 msaitoh d = mtod(m, uint8_t *); 1353 1.1 chopps 1354 1.84 msaitoh RAY_DPRINTF(("%s: recv ccs index %d\n", device_xname(sc->sc_dev), 1355 1.84 msaitoh first)); 1356 1.1 chopps i = ni = first; 1357 1.1 chopps while ((i = ni) && i != RAY_CCS_LINK_NULL) { 1358 1.1 chopps ccs = RAY_GET_CCS(i); 1359 1.1 chopps bufp = SRAM_READ_FIELD_2(sc, ccs, ray_cmd_rx, c_bufp); 1360 1.1 chopps len = SRAM_READ_FIELD_2(sc, ccs, ray_cmd_rx, c_len); 1361 1.1 chopps /* remove the CRC */ 1362 1.1 chopps #if 0 1363 1.1 chopps /* at least with build 4 no crc seems to be here */ 1364 1.1 chopps if (frag++ == 0) 1365 1.1 chopps len -= 4; 1366 1.1 chopps #endif 1367 1.1 chopps ni = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_rx, c_nextfrag); 1368 1.69 dholland RAY_DPRINTF(( 1369 1.69 dholland "%s: recv frag index %d len %ld bufp 0x%llx ni %d\n", 1370 1.84 msaitoh device_xname(sc->sc_dev), i, (u_long)len, 1371 1.84 msaitoh (unsigned long long)bufp, ni)); 1372 1.1 chopps if (len + lenread > pktlen) { 1373 1.13 thorpej RAY_DPRINTF(("%s: BAD LEN current 0x%lx pktlen 0x%lx\n", 1374 1.80 chs device_xname(sc->sc_dev), (u_long)(len + lenread), 1375 1.13 thorpej (u_long)pktlen)); 1376 1.97 thorpej if_statinc(ifp, if_ierrors); 1377 1.1 chopps m_freem(m); 1378 1.1 chopps m = 0; 1379 1.1 chopps goto done; 1380 1.1 chopps } 1381 1.1 chopps if (i < RAY_RCCS_FIRST) { 1382 1.1 chopps printf("ray_recv: bad ccs index 0x%x\n", i); 1383 1.1 chopps m_freem(m); 1384 1.1 chopps m = 0; 1385 1.1 chopps goto done; 1386 1.1 chopps } 1387 1.1 chopps 1388 1.1 chopps ebufp = bufp + len; 1389 1.1 chopps if (ebufp <= RAY_RX_END) 1390 1.1 chopps ray_read_region(sc, bufp, d, len); 1391 1.1 chopps else { 1392 1.1 chopps /* wrapping */ 1393 1.1 chopps ray_read_region(sc, bufp, d, (tmp = RAY_RX_END - bufp)); 1394 1.84 msaitoh ray_read_region(sc, RAY_RX_BASE, d + tmp, 1395 1.84 msaitoh ebufp - RAY_RX_END); 1396 1.1 chopps } 1397 1.1 chopps d += len; 1398 1.1 chopps lenread += len; 1399 1.1 chopps } 1400 1.1 chopps done: 1401 1.56 perry 1402 1.84 msaitoh RAY_DPRINTF(("%s: recv frag count %d\n", device_xname(sc->sc_dev), 1403 1.84 msaitoh frag)); 1404 1.1 chopps 1405 1.1 chopps /* free the rcss */ 1406 1.1 chopps ni = first; 1407 1.1 chopps while ((i = ni) && (i != RAY_CCS_LINK_NULL)) { 1408 1.1 chopps ccs = RAY_GET_CCS(i); 1409 1.1 chopps ni = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_rx, c_nextfrag); 1410 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, 1411 1.1 chopps RAY_CCS_STATUS_FREE); 1412 1.1 chopps } 1413 1.1 chopps 1414 1.1 chopps if (!m) 1415 1.1 chopps return; 1416 1.1 chopps 1417 1.13 thorpej RAY_DPRINTF(("%s: recv got packet pktlen %ld actual %ld\n", 1418 1.80 chs device_xname(sc->sc_dev), (u_long)pktlen, (u_long)lenread)); 1419 1.1 chopps #ifdef RAY_DEBUG 1420 1.1 chopps if (ray_debug && ray_debug_dump_rx) 1421 1.1 chopps ray_dump_mbuf(sc, m); 1422 1.1 chopps #endif 1423 1.1 chopps /* receivce the packet */ 1424 1.1 chopps frame = mtod(m, struct ieee80211_frame *); 1425 1.1 chopps fc0 = frame->i_fc[0] 1426 1.93 msaitoh & (IEEE80211_FC0_VERSION_MASK | IEEE80211_FC0_TYPE_MASK); 1427 1.1 chopps if ((fc0 & IEEE80211_FC0_VERSION_MASK) != IEEE80211_FC0_VERSION_0) { 1428 1.1 chopps RAY_DPRINTF(("%s: pkt not version 0 fc 0x%x\n", 1429 1.80 chs device_xname(sc->sc_dev), fc0)); 1430 1.1 chopps m_freem(m); 1431 1.1 chopps return; 1432 1.1 chopps } 1433 1.24 thorpej if ((fc0 & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT) { 1434 1.24 thorpej switch (frame->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) { 1435 1.24 thorpej case IEEE80211_FC0_SUBTYPE_BEACON: 1436 1.24 thorpej /* Ignore beacon silently. */ 1437 1.24 thorpej break; 1438 1.24 thorpej case IEEE80211_FC0_SUBTYPE_AUTH: 1439 1.24 thorpej ray_recv_auth(sc, frame); 1440 1.24 thorpej break; 1441 1.24 thorpej case IEEE80211_FC0_SUBTYPE_DEAUTH: 1442 1.24 thorpej sc->sc_authstate = RAY_AUTH_UNAUTH; 1443 1.24 thorpej break; 1444 1.24 thorpej default: 1445 1.24 thorpej RAY_DPRINTF(("%s: mgt packet not supported\n", 1446 1.80 chs device_xname(sc->sc_dev))); 1447 1.24 thorpej #ifdef RAY_DEBUG 1448 1.88 christos hexdump(printf, __func__, frame, pktlen); 1449 1.24 thorpej #endif 1450 1.24 thorpej RAY_DPRINTF(("\n")); 1451 1.24 thorpej break; 1452 1.24 thorpej } 1453 1.24 thorpej m_freem(m); 1454 1.25 thorpej return; 1455 1.24 thorpej } else if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) { 1456 1.1 chopps RAY_DPRINTF(("%s: pkt not type data fc0 0x%x\n", 1457 1.80 chs device_xname(sc->sc_dev), fc0)); 1458 1.1 chopps m_freem(m); 1459 1.1 chopps return; 1460 1.1 chopps } 1461 1.1 chopps 1462 1.24 thorpej if (pktlen < sizeof(*frame) + sizeof(struct llc)) { 1463 1.26 mycroft RAY_DPRINTF(("%s: pkt too small for llc (%ld)\n", 1464 1.80 chs device_xname(sc->sc_dev), (u_long)pktlen)); 1465 1.24 thorpej m_freem(m); 1466 1.24 thorpej return; 1467 1.24 thorpej } 1468 1.24 thorpej 1469 1.1 chopps if (!memcmp(frame + 1, llc_snapid, sizeof(llc_snapid))) 1470 1.1 chopps issnap = 1; 1471 1.1 chopps else { 1472 1.1 chopps /* 1473 1.56 perry * if user has link0 flag set we allow the weird 1474 1.1 chopps * Ethernet2 in 802.11 encapsulation produced by 1475 1.1 chopps * the windows driver for the WebGear card 1476 1.1 chopps */ 1477 1.80 chs RAY_DPRINTF(("%s: pkt not snap 0\n", device_xname(sc->sc_dev))); 1478 1.1 chopps if ((ifp->if_flags & IFF_LINK0) == 0) { 1479 1.1 chopps m_freem(m); 1480 1.1 chopps return; 1481 1.1 chopps } 1482 1.1 chopps issnap = 0; 1483 1.1 chopps } 1484 1.16 onoe switch (frame->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 1485 1.16 onoe case IEEE80211_FC1_DIR_NODS: 1486 1.1 chopps src = frame->i_addr2; 1487 1.1 chopps break; 1488 1.16 onoe case IEEE80211_FC1_DIR_FROMDS: 1489 1.1 chopps src = frame->i_addr3; 1490 1.1 chopps break; 1491 1.16 onoe case IEEE80211_FC1_DIR_TODS: 1492 1.80 chs RAY_DPRINTF(("%s: pkt ap2ap\n", device_xname(sc->sc_dev))); 1493 1.1 chopps m_freem(m); 1494 1.1 chopps return; 1495 1.1 chopps default: 1496 1.84 msaitoh RAY_DPRINTF(("%s: pkt type unknown\n", 1497 1.84 msaitoh device_xname(sc->sc_dev))); 1498 1.1 chopps m_freem(m); 1499 1.1 chopps return; 1500 1.1 chopps } 1501 1.14 augustss 1502 1.14 augustss #ifdef RAY_DO_SIGLEV 1503 1.14 augustss ray_update_siglev(sc, src, siglev); 1504 1.14 augustss #endif 1505 1.14 augustss 1506 1.1 chopps /* 1507 1.1 chopps * This is a mess.. we should support other LLC frame types 1508 1.1 chopps */ 1509 1.1 chopps if (issnap) { 1510 1.1 chopps /* create an ether_header over top of the 802.11+SNAP header */ 1511 1.64 christos eh = (struct ether_header *)((char *)(frame + 1) - 6); 1512 1.1 chopps memcpy(eh->ether_shost, src, ETHER_ADDR_LEN); 1513 1.1 chopps memcpy(eh->ether_dhost, frame->i_addr1, ETHER_ADDR_LEN); 1514 1.1 chopps } else { 1515 1.1 chopps /* this is the weird e2 in 802.11 encapsulation */ 1516 1.1 chopps eh = (struct ether_header *)(frame + 1); 1517 1.1 chopps } 1518 1.64 christos m_adj(m, (char *)eh - (char *)frame); 1519 1.90 msaitoh bpf_mtap(ifp, m, BPF_D_IN); 1520 1.1 chopps /* XXX doesn't appear to be included m->m_flags |= M_HASFCS; */ 1521 1.82 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 1522 1.1 chopps } 1523 1.1 chopps 1524 1.24 thorpej /* 1525 1.24 thorpej * receive an auth packet 1526 1.24 thorpej */ 1527 1.24 thorpej static void 1528 1.72 dsl ray_recv_auth(struct ray_softc *sc, struct ieee80211_frame *frame) 1529 1.24 thorpej { 1530 1.93 msaitoh uint8_t *var = (uint8_t *)(frame + 1); 1531 1.24 thorpej 1532 1.24 thorpej if (sc->sc_mode == SC_MODE_ADHOC) { 1533 1.84 msaitoh RAY_DPRINTF(("%s: recv auth packet:\n", 1534 1.84 msaitoh device_xname(sc->sc_dev))); 1535 1.24 thorpej #ifdef RAY_DEBUG 1536 1.88 christos hexdump(printf, __func__, frame, sizeof(*frame) + 6); 1537 1.24 thorpej #endif 1538 1.24 thorpej RAY_DPRINTF(("\n")); 1539 1.24 thorpej 1540 1.24 thorpej if (var[2] == OPEN_AUTH_REQUEST) { 1541 1.24 thorpej RAY_DPRINTF(("%s: Sending authentication response.\n", 1542 1.80 chs device_xname(sc->sc_dev))); 1543 1.24 thorpej if (ray_send_auth(sc, frame->i_addr2, 1544 1.24 thorpej OPEN_AUTH_RESPONSE) == 0) { 1545 1.24 thorpej sc->sc_authstate = RAY_AUTH_NEEDED; 1546 1.24 thorpej memcpy(sc->sc_authid, frame->i_addr2, 1547 1.24 thorpej ETHER_ADDR_LEN); 1548 1.24 thorpej } 1549 1.24 thorpej } else if (var[2] == OPEN_AUTH_RESPONSE) { 1550 1.24 thorpej RAY_DPRINTF(("%s: Authenticated!\n", 1551 1.80 chs device_xname(sc->sc_dev))); 1552 1.24 thorpej sc->sc_authstate = RAY_AUTH_AUTH; 1553 1.24 thorpej } 1554 1.24 thorpej } 1555 1.24 thorpej } 1556 1.24 thorpej 1557 1.24 thorpej /* 1558 1.24 thorpej * send an auth packet 1559 1.24 thorpej */ 1560 1.24 thorpej static int 1561 1.93 msaitoh ray_send_auth(struct ray_softc *sc, uint8_t *dest, uint8_t auth_type) 1562 1.24 thorpej { 1563 1.93 msaitoh uint8_t packet[sizeof(struct ieee80211_frame) + ETHER_ADDR_LEN], *var; 1564 1.24 thorpej struct ieee80211_frame *frame; 1565 1.24 thorpej bus_size_t bufp; 1566 1.24 thorpej int ccsindex; 1567 1.24 thorpej 1568 1.24 thorpej ccsindex = ray_find_free_tx_ccs(sc, RAY_CCS_TX_FIRST); 1569 1.24 thorpej if (ccsindex == RAY_CCS_LINK_NULL) { 1570 1.24 thorpej RAY_DPRINTF(("%s: send auth failed -- no free tx slots\n", 1571 1.80 chs device_xname(sc->sc_dev))); 1572 1.24 thorpej return (ENOMEM); 1573 1.24 thorpej } 1574 1.24 thorpej 1575 1.24 thorpej bufp = ray_fill_in_tx_ccs(sc, sizeof(packet), ccsindex, 1576 1.24 thorpej RAY_CCS_LINK_NULL); 1577 1.24 thorpej frame = (struct ieee80211_frame *) packet; 1578 1.24 thorpej frame->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_SUBTYPE_AUTH; 1579 1.24 thorpej frame->i_fc[1] = 0; 1580 1.24 thorpej memcpy(frame->i_addr1, dest, ETHER_ADDR_LEN); 1581 1.24 thorpej memcpy(frame->i_addr2, sc->sc_ecf_startup.e_station_addr, 1582 1.24 thorpej ETHER_ADDR_LEN); 1583 1.24 thorpej memcpy(frame->i_addr3, sc->sc_bssid, ETHER_ADDR_LEN); 1584 1.24 thorpej 1585 1.93 msaitoh var = (uint8_t *)(frame + 1); 1586 1.24 thorpej memset(var, 0, ETHER_ADDR_LEN); 1587 1.24 thorpej var[2] = auth_type; 1588 1.24 thorpej 1589 1.24 thorpej ray_write_region(sc, bufp, packet, sizeof(packet)); 1590 1.24 thorpej 1591 1.24 thorpej SRAM_WRITE_1(sc, RAY_SCB_CCSI, ccsindex); 1592 1.24 thorpej RAY_ECF_START_CMD(sc); 1593 1.24 thorpej 1594 1.24 thorpej RAY_DPRINTF_XMIT(("%s: sent auth packet: len %lu\n", 1595 1.80 chs device_xname(sc->sc_dev), (u_long) sizeof(packet))); 1596 1.24 thorpej 1597 1.24 thorpej return (0); 1598 1.24 thorpej } 1599 1.1 chopps 1600 1.1 chopps /* 1601 1.1 chopps * scan for free buffers 1602 1.1 chopps * 1603 1.1 chopps * Note: do _not_ try to optimize this away, there is some kind of 1604 1.1 chopps * horrible interaction with receiving tx interrupts and they 1605 1.1 chopps * have to be done as fast as possible, which means zero processing. 1606 1.1 chopps * this took ~ever to figure out, don't make someone do it again! 1607 1.1 chopps */ 1608 1.1 chopps static u_int 1609 1.72 dsl ray_find_free_tx_ccs(struct ray_softc *sc, u_int hint) 1610 1.1 chopps { 1611 1.1 chopps u_int i, stat; 1612 1.1 chopps 1613 1.1 chopps for (i = hint; i <= RAY_CCS_TX_LAST; i++) { 1614 1.1 chopps stat = SRAM_READ_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_status); 1615 1.1 chopps if (stat == RAY_CCS_STATUS_FREE) 1616 1.1 chopps return (i); 1617 1.1 chopps } 1618 1.1 chopps 1619 1.1 chopps if (hint == RAY_CCS_TX_FIRST) 1620 1.1 chopps return (RAY_CCS_LINK_NULL); 1621 1.1 chopps 1622 1.1 chopps for (i = RAY_CCS_TX_FIRST; i < hint; i++) { 1623 1.1 chopps stat = SRAM_READ_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_status); 1624 1.1 chopps if (stat == RAY_CCS_STATUS_FREE) 1625 1.1 chopps return (i); 1626 1.1 chopps } 1627 1.1 chopps return (RAY_CCS_LINK_NULL); 1628 1.1 chopps } 1629 1.1 chopps 1630 1.1 chopps /* 1631 1.1 chopps * allocate, initialize and link in a tx ccs for the given 1632 1.1 chopps * page and the current chain values 1633 1.1 chopps */ 1634 1.1 chopps static bus_size_t 1635 1.73 dsl ray_fill_in_tx_ccs(struct ray_softc *sc, size_t pktlen, u_int i, u_int pi) 1636 1.1 chopps { 1637 1.1 chopps bus_size_t ccs, bufp; 1638 1.1 chopps 1639 1.1 chopps /* pktlen += RAY_TX_PHY_SIZE; */ 1640 1.1 chopps bufp = RAY_TX_BASE + i * RAY_TX_BUF_SIZE; 1641 1.1 chopps bufp += sc->sc_txpad; 1642 1.1 chopps ccs = RAY_GET_CCS(i); 1643 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_status, RAY_CCS_STATUS_BUSY); 1644 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_cmd, RAY_CMD_TX_REQ); 1645 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_link, RAY_CCS_LINK_NULL); 1646 1.1 chopps SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_bufp, bufp); 1647 1.1 chopps SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_len, pktlen); 1648 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_tx_rate, sc->sc_deftxrate); 1649 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_apm_mode, 0); 1650 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_antenna, 0); 1651 1.1 chopps 1652 1.1 chopps /* link us in */ 1653 1.1 chopps if (pi != RAY_CCS_LINK_NULL) 1654 1.1 chopps SRAM_WRITE_FIELD_1(sc, RAY_GET_CCS(pi), ray_cmd_tx, c_link, i); 1655 1.1 chopps 1656 1.58 christos RAY_DPRINTF(("%s: ray_alloc_tx_ccs bufp 0x%llx idx %u pidx %u\n", 1657 1.80 chs device_xname(sc->sc_dev), (unsigned long long)bufp, i, pi)); 1658 1.1 chopps 1659 1.1 chopps return (bufp + RAY_TX_PHY_SIZE); 1660 1.1 chopps } 1661 1.1 chopps 1662 1.1 chopps /* 1663 1.1 chopps * an update params command has completed lookup which command and 1664 1.1 chopps * the status 1665 1.1 chopps */ 1666 1.1 chopps static ray_cmd_func_t 1667 1.72 dsl ray_update_params_done(struct ray_softc *sc, bus_size_t ccs, u_int stat) 1668 1.1 chopps { 1669 1.1 chopps ray_cmd_func_t rcmd; 1670 1.1 chopps 1671 1.1 chopps rcmd = 0; 1672 1.1 chopps 1673 1.1 chopps RAY_DPRINTF(("%s: ray_update_params_done stat %d\n", 1674 1.80 chs device_xname(sc->sc_dev), stat)); 1675 1.1 chopps 1676 1.1 chopps /* this will get more complex as we add commands */ 1677 1.1 chopps if (stat == RAY_CCS_STATUS_FAIL) { 1678 1.84 msaitoh printf("%s: failed to update a promisc\n", 1679 1.84 msaitoh device_xname(sc->sc_dev)); 1680 1.1 chopps /* XXX should probably reset */ 1681 1.1 chopps /* rcmd = ray_reset; */ 1682 1.1 chopps } 1683 1.1 chopps 1684 1.1 chopps if (sc->sc_running & SCP_UPD_PROMISC) { 1685 1.1 chopps ray_cmd_done(sc, SCP_UPD_PROMISC); 1686 1.1 chopps sc->sc_promisc = SRAM_READ_1(sc, RAY_HOST_TO_ECF_BASE); 1687 1.84 msaitoh RAY_DPRINTF(("%s: new promisc value %d\n", 1688 1.84 msaitoh device_xname(sc->sc_dev), sc->sc_promisc)); 1689 1.1 chopps } else if (sc->sc_updreq) { 1690 1.1 chopps ray_cmd_done(sc, SCP_UPD_UPDATEPARAMS); 1691 1.1 chopps /* get the update parameter */ 1692 1.1 chopps sc->sc_updreq->r_failcause = 1693 1.1 chopps SRAM_READ_FIELD_1(sc, ccs, ray_cmd_update, c_failcause); 1694 1.1 chopps sc->sc_updreq = 0; 1695 1.1 chopps wakeup(ray_update_params); 1696 1.1 chopps 1697 1.1 chopps rcmd = ray_start_join_net; 1698 1.1 chopps } 1699 1.1 chopps return (rcmd); 1700 1.1 chopps } 1701 1.1 chopps 1702 1.1 chopps /* 1703 1.1 chopps * check too see if we have any pending commands. 1704 1.1 chopps */ 1705 1.1 chopps static void 1706 1.72 dsl ray_check_scheduled(void *arg) 1707 1.1 chopps { 1708 1.1 chopps struct ray_softc *sc; 1709 1.1 chopps int s, i, mask; 1710 1.1 chopps 1711 1.1 chopps s = splnet(); 1712 1.1 chopps 1713 1.1 chopps sc = arg; 1714 1.1 chopps RAY_DPRINTF(( 1715 1.1 chopps "%s: ray_check_scheduled enter schd 0x%x running 0x%x ready %d\n", 1716 1.84 msaitoh device_xname(sc->sc_dev), sc->sc_scheduled, sc->sc_running, 1717 1.84 msaitoh RAY_ECF_READY(sc))); 1718 1.1 chopps 1719 1.1 chopps if (sc->sc_timoneed) { 1720 1.17 thorpej callout_stop(&sc->sc_check_scheduled_ch); 1721 1.1 chopps sc->sc_timoneed = 0; 1722 1.1 chopps } 1723 1.1 chopps 1724 1.1 chopps /* if update subcmd is running -- clear it in scheduled */ 1725 1.1 chopps if (sc->sc_running & SCP_UPDATESUBCMD) 1726 1.1 chopps sc->sc_scheduled &= ~SCP_UPDATESUBCMD; 1727 1.1 chopps 1728 1.1 chopps mask = SCP_FIRST; 1729 1.1 chopps for (i = 0; i < ray_ncmdtab; mask <<= 1, i++) { 1730 1.1 chopps if ((sc->sc_scheduled & ~SCP_UPD_MASK) == 0) 1731 1.1 chopps break; 1732 1.1 chopps if (!RAY_ECF_READY(sc)) 1733 1.1 chopps break; 1734 1.1 chopps if (sc->sc_scheduled & mask) 1735 1.1 chopps (*ray_cmdtab[i])(sc); 1736 1.1 chopps } 1737 1.1 chopps 1738 1.1 chopps RAY_DPRINTF(( 1739 1.1 chopps "%s: ray_check_scheduled exit sched 0x%x running 0x%x ready %d\n", 1740 1.84 msaitoh device_xname(sc->sc_dev), sc->sc_scheduled, sc->sc_running, 1741 1.84 msaitoh RAY_ECF_READY(sc))); 1742 1.1 chopps 1743 1.1 chopps if (sc->sc_scheduled & ~SCP_UPD_MASK) 1744 1.1 chopps ray_set_pending(sc, sc->sc_scheduled); 1745 1.1 chopps 1746 1.1 chopps splx(s); 1747 1.1 chopps } 1748 1.1 chopps 1749 1.1 chopps /* 1750 1.1 chopps * check for unreported returns 1751 1.1 chopps * 1752 1.1 chopps * this routine is coded to only expect one outstanding request for the 1753 1.1 chopps * timed out requests at a time, but thats all that can be outstanding 1754 1.1 chopps * per hardware limitations 1755 1.1 chopps */ 1756 1.1 chopps static void 1757 1.72 dsl ray_check_ccs(void *arg) 1758 1.1 chopps { 1759 1.1 chopps ray_cmd_func_t fp; 1760 1.1 chopps struct ray_softc *sc; 1761 1.42 chs u_int i, cmd, stat = 0; 1762 1.42 chs bus_size_t ccs = 0; 1763 1.1 chopps int s; 1764 1.1 chopps 1765 1.1 chopps s = splnet(); 1766 1.1 chopps sc = arg; 1767 1.1 chopps 1768 1.80 chs RAY_DPRINTF(("%s: ray_check_ccs\n", device_xname(sc->sc_dev))); 1769 1.1 chopps 1770 1.1 chopps sc->sc_timocheck = 0; 1771 1.1 chopps for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) { 1772 1.1 chopps if (!sc->sc_ccsinuse[i]) 1773 1.1 chopps continue; 1774 1.1 chopps ccs = RAY_GET_CCS(i); 1775 1.1 chopps cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd); 1776 1.1 chopps switch (cmd) { 1777 1.1 chopps case RAY_CMD_START_PARAMS: 1778 1.1 chopps case RAY_CMD_UPDATE_MCAST: 1779 1.1 chopps case RAY_CMD_UPDATE_PARAMS: 1780 1.1 chopps stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status); 1781 1.58 christos RAY_DPRINTF(("%s: check ccs idx %u ccs 0x%llx " 1782 1.80 chs "cmd 0x%x stat %u\n", device_xname(sc->sc_dev), i, 1783 1.58 christos (unsigned long long)ccs, cmd, stat)); 1784 1.1 chopps goto breakout; 1785 1.1 chopps } 1786 1.1 chopps } 1787 1.1 chopps breakout: 1788 1.1 chopps /* see if we got one of the commands we are looking for */ 1789 1.1 chopps if (i > RAY_CCS_CMD_LAST) 1790 1.39 mjl ; /* nothing */ 1791 1.1 chopps else if (stat == RAY_CCS_STATUS_FREE) { 1792 1.1 chopps stat = RAY_CCS_STATUS_COMPLETE; 1793 1.1 chopps if ((fp = ray_ccs_done(sc, ccs))) 1794 1.1 chopps (*fp)(sc); 1795 1.1 chopps } else if (stat != RAY_CCS_STATUS_BUSY) { 1796 1.1 chopps if (sc->sc_ccsinuse[i] == 1) { 1797 1.1 chopps /* give a chance for the interrupt to occur */ 1798 1.1 chopps sc->sc_ccsinuse[i] = 2; 1799 1.1 chopps if (!sc->sc_timocheck) { 1800 1.17 thorpej callout_reset(&sc->sc_check_ccs_ch, 1, 1801 1.17 thorpej ray_check_ccs, sc); 1802 1.1 chopps sc->sc_timocheck = 1; 1803 1.1 chopps } 1804 1.1 chopps } else if ((fp = ray_ccs_done(sc, ccs))) 1805 1.1 chopps (*fp)(sc); 1806 1.1 chopps } else { 1807 1.17 thorpej callout_reset(&sc->sc_check_ccs_ch, RAY_CHECK_CCS_TIMEOUT, 1808 1.17 thorpej ray_check_ccs, sc); 1809 1.1 chopps sc->sc_timocheck = 1; 1810 1.1 chopps } 1811 1.1 chopps splx(s); 1812 1.1 chopps } 1813 1.1 chopps 1814 1.1 chopps /* 1815 1.1 chopps * read the counters, the card implements the following protocol 1816 1.1 chopps * to keep the values from being changed while read: It checks 1817 1.1 chopps * the `own' bit and if zero writes the current internal counter 1818 1.1 chopps * value, it then sets the `own' bit to 1. If the `own' bit was 1 it 1819 1.39 mjl * increments its internal counter. The user thus reads the counter 1820 1.1 chopps * if the `own' bit is one and then sets the own bit to 0. 1821 1.1 chopps */ 1822 1.1 chopps static void 1823 1.72 dsl ray_update_error_counters(struct ray_softc *sc) 1824 1.1 chopps { 1825 1.1 chopps bus_size_t csc; 1826 1.1 chopps 1827 1.1 chopps /* try and update the error counters */ 1828 1.1 chopps csc = RAY_STATUS_BASE; 1829 1.1 chopps if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_mrxo_own)) { 1830 1.1 chopps sc->sc_rxoverflow += 1831 1.1 chopps SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_mrx_overflow); 1832 1.1 chopps SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_mrxo_own, 0); 1833 1.1 chopps } 1834 1.1 chopps if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_mrxc_own)) { 1835 1.1 chopps sc->sc_rxcksum += 1836 1.1 chopps SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_mrx_overflow); 1837 1.1 chopps SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_mrxc_own, 0); 1838 1.1 chopps } 1839 1.1 chopps if (SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_rxhc_own)) { 1840 1.1 chopps sc->sc_rxhcksum += 1841 1.1 chopps SRAM_READ_FIELD_2(sc, csc, ray_csc, csc_rx_hcksum); 1842 1.1 chopps SRAM_WRITE_FIELD_1(sc, csc, ray_csc, csc_rxhc_own, 0); 1843 1.1 chopps } 1844 1.1 chopps sc->sc_rxnoise = SRAM_READ_FIELD_1(sc, csc, ray_csc, csc_rx_noise); 1845 1.1 chopps } 1846 1.1 chopps 1847 1.1 chopps /* 1848 1.1 chopps * one of the commands we issued has completed, process. 1849 1.1 chopps */ 1850 1.1 chopps static ray_cmd_func_t 1851 1.72 dsl ray_ccs_done(struct ray_softc *sc, bus_size_t ccs) 1852 1.1 chopps { 1853 1.1 chopps ray_cmd_func_t rcmd; 1854 1.1 chopps u_int cmd, stat; 1855 1.1 chopps 1856 1.1 chopps cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd); 1857 1.1 chopps stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status); 1858 1.1 chopps 1859 1.58 christos RAY_DPRINTF(("%s: ray_ccs_done idx %llu cmd 0x%x stat %u\n", 1860 1.84 msaitoh device_xname(sc->sc_dev), (unsigned long long)RAY_GET_INDEX(ccs), 1861 1.84 msaitoh cmd, stat)); 1862 1.1 chopps 1863 1.1 chopps rcmd = 0; 1864 1.1 chopps switch (cmd) { 1865 1.1 chopps /* 1866 1.1 chopps * solicited commands 1867 1.1 chopps */ 1868 1.1 chopps case RAY_CMD_START_PARAMS: 1869 1.1 chopps /* start network */ 1870 1.1 chopps ray_cmd_done(sc, SCP_UPD_STARTUP); 1871 1.1 chopps 1872 1.1 chopps /* ok to start queueing packets */ 1873 1.1 chopps sc->sc_if.if_flags &= ~IFF_OACTIVE; 1874 1.1 chopps 1875 1.1 chopps sc->sc_omode = sc->sc_mode; 1876 1.21 onoe memcpy(&sc->sc_cnwid, &sc->sc_dnwid, sizeof(sc->sc_cnwid)); 1877 1.1 chopps 1878 1.1 chopps rcmd = ray_start_join_net; 1879 1.1 chopps break; 1880 1.1 chopps case RAY_CMD_UPDATE_PARAMS: 1881 1.1 chopps rcmd = ray_update_params_done(sc, ccs, stat); 1882 1.1 chopps break; 1883 1.1 chopps case RAY_CMD_REPORT_PARAMS: 1884 1.1 chopps /* get the reported parameters */ 1885 1.1 chopps ray_cmd_done(sc, SCP_REPORTPARAMS); 1886 1.1 chopps if (!sc->sc_repreq) 1887 1.1 chopps break; 1888 1.1 chopps sc->sc_repreq->r_failcause = 1889 1.1 chopps SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_failcause); 1890 1.1 chopps sc->sc_repreq->r_len = 1891 1.1 chopps SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_len); 1892 1.1 chopps ray_read_region(sc, RAY_ECF_TO_HOST_BASE, sc->sc_repreq->r_data, 1893 1.1 chopps sc->sc_repreq->r_len); 1894 1.1 chopps sc->sc_repreq = 0; 1895 1.1 chopps wakeup(ray_report_params); 1896 1.1 chopps break; 1897 1.1 chopps case RAY_CMD_UPDATE_MCAST: 1898 1.1 chopps ray_cmd_done(sc, SCP_UPD_MCAST); 1899 1.1 chopps if (stat == RAY_CCS_STATUS_FAIL) 1900 1.1 chopps rcmd = ray_reset; 1901 1.1 chopps break; 1902 1.1 chopps case RAY_CMD_START_NET: 1903 1.1 chopps case RAY_CMD_JOIN_NET: 1904 1.1 chopps rcmd = ray_start_join_net_done(sc, cmd, ccs, stat); 1905 1.1 chopps break; 1906 1.1 chopps case RAY_CMD_TX_REQ: 1907 1.1 chopps if (sc->sc_if.if_flags & IFF_OACTIVE) { 1908 1.1 chopps sc->sc_if.if_flags &= ~IFF_OACTIVE; 1909 1.1 chopps /* this may also be a problem */ 1910 1.1 chopps rcmd = ray_intr_start; 1911 1.1 chopps } 1912 1.1 chopps /* free it -- no tracking */ 1913 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, 1914 1.1 chopps RAY_CCS_STATUS_FREE); 1915 1.1 chopps goto done; 1916 1.1 chopps case RAY_CMD_START_ASSOC: 1917 1.1 chopps ray_cmd_done(sc, SCP_STARTASSOC); 1918 1.1 chopps if (stat == RAY_CCS_STATUS_FAIL) 1919 1.1 chopps rcmd = ray_start_join_net; /* XXX check */ 1920 1.4 chopps else { 1921 1.4 chopps sc->sc_havenet = 1; 1922 1.1 chopps rcmd = ray_intr_start; 1923 1.4 chopps } 1924 1.1 chopps break; 1925 1.1 chopps case RAY_CMD_UPDATE_APM: 1926 1.1 chopps case RAY_CMD_TEST_MEM: 1927 1.1 chopps case RAY_CMD_SHUTDOWN: 1928 1.1 chopps case RAY_CMD_DUMP_MEM: 1929 1.1 chopps case RAY_CMD_START_TIMER: 1930 1.1 chopps break; 1931 1.1 chopps default: 1932 1.1 chopps printf("%s: intr: unknown command 0x%x\n", 1933 1.1 chopps sc->sc_if.if_xname, cmd); 1934 1.1 chopps break; 1935 1.1 chopps } 1936 1.1 chopps ray_free_ccs(sc, ccs); 1937 1.1 chopps done: 1938 1.1 chopps /* 1939 1.1 chopps * see if needed things can be done now that a command 1940 1.1 chopps * has completed 1941 1.1 chopps */ 1942 1.1 chopps ray_check_scheduled(sc); 1943 1.1 chopps 1944 1.1 chopps return (rcmd); 1945 1.1 chopps } 1946 1.1 chopps 1947 1.1 chopps /* 1948 1.39 mjl * an unsolicited interrupt, i.e., the ECF is sending us a command 1949 1.1 chopps */ 1950 1.1 chopps static ray_cmd_func_t 1951 1.72 dsl ray_rccs_intr(struct ray_softc *sc, bus_size_t ccs) 1952 1.1 chopps { 1953 1.1 chopps ray_cmd_func_t rcmd; 1954 1.1 chopps u_int cmd, stat; 1955 1.1 chopps 1956 1.1 chopps cmd = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd); 1957 1.1 chopps stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status); 1958 1.1 chopps 1959 1.58 christos RAY_DPRINTF(("%s: ray_rccs_intr idx %llu cmd 0x%x stat %u\n", 1960 1.84 msaitoh device_xname(sc->sc_dev), (unsigned long long)RAY_GET_INDEX(ccs), 1961 1.84 msaitoh cmd, stat)); 1962 1.1 chopps 1963 1.1 chopps rcmd = 0; 1964 1.1 chopps switch (cmd) { 1965 1.1 chopps /* 1966 1.39 mjl * unsolicited commands 1967 1.1 chopps */ 1968 1.1 chopps case RAY_ECMD_RX_DONE: 1969 1.1 chopps ray_recv(sc, ccs); 1970 1.1 chopps goto done; 1971 1.1 chopps case RAY_ECMD_REJOIN_DONE: 1972 1.4 chopps if (sc->sc_mode == SC_MODE_ADHOC) 1973 1.4 chopps break; 1974 1.4 chopps /* get the current ssid */ 1975 1.4 chopps SRAM_READ_FIELD_N(sc, ccs, ray_cmd_net, c_bss_id, 1976 1.4 chopps sc->sc_bssid, sizeof(sc->sc_bssid)); 1977 1.1 chopps rcmd = ray_start_assoc; 1978 1.1 chopps break; 1979 1.1 chopps case RAY_ECMD_ROAM_START: 1980 1.4 chopps /* no longer have network */ 1981 1.4 chopps sc->sc_havenet = 0; 1982 1.1 chopps break; 1983 1.1 chopps case RAY_ECMD_JAPAN_CALL_SIGNAL: 1984 1.1 chopps break; 1985 1.1 chopps default: 1986 1.1 chopps ray_update_error_counters(sc); 1987 1.1 chopps 1988 1.1 chopps /* this is a bogus return from build 4 don't free 0x55 */ 1989 1.1 chopps if (sc->sc_version == SC_BUILD_4 && cmd == 0x55 1990 1.1 chopps && RAY_GET_INDEX(ccs) == 0x55) { 1991 1.1 chopps goto done; 1992 1.1 chopps } 1993 1.1 chopps printf("%s: intr: unknown command 0x%x\n", 1994 1.1 chopps sc->sc_if.if_xname, cmd); 1995 1.1 chopps break; 1996 1.1 chopps } 1997 1.1 chopps /* free the ccs */ 1998 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_FREE); 1999 1.1 chopps done: 2000 1.1 chopps return (rcmd); 2001 1.1 chopps } 2002 1.1 chopps 2003 1.1 chopps /* 2004 1.1 chopps * process an interrupt 2005 1.1 chopps */ 2006 1.1 chopps static int 2007 1.72 dsl ray_intr(void *arg) 2008 1.1 chopps { 2009 1.1 chopps struct ray_softc *sc; 2010 1.1 chopps ray_cmd_func_t rcmd; 2011 1.1 chopps u_int i, count; 2012 1.1 chopps 2013 1.1 chopps sc = arg; 2014 1.1 chopps 2015 1.80 chs RAY_DPRINTF(("%s: ray_intr\n", device_xname(sc->sc_dev))); 2016 1.1 chopps 2017 1.1 chopps if ((++sc->sc_checkcounters % 32) == 0) 2018 1.1 chopps ray_update_error_counters(sc); 2019 1.1 chopps 2020 1.1 chopps count = 0; 2021 1.1 chopps rcmd = 0; 2022 1.1 chopps if (!REG_READ(sc, RAY_HCSIR)) 2023 1.1 chopps count = 0; 2024 1.1 chopps else { 2025 1.1 chopps count = 1; 2026 1.1 chopps i = SRAM_READ_1(sc, RAY_SCB_RCCSI); 2027 1.1 chopps if (i <= RAY_CCS_LAST) 2028 1.1 chopps rcmd = ray_ccs_done(sc, RAY_GET_CCS(i)); 2029 1.1 chopps else if (i <= RAY_RCCS_LAST) 2030 1.1 chopps rcmd = ray_rccs_intr(sc, RAY_GET_CCS(i)); 2031 1.1 chopps else 2032 1.84 msaitoh printf("%s: intr: bad cmd index %d\n", 2033 1.84 msaitoh device_xname(sc->sc_dev), i); 2034 1.1 chopps } 2035 1.1 chopps 2036 1.1 chopps if (rcmd) 2037 1.1 chopps (*rcmd)(sc); 2038 1.1 chopps 2039 1.1 chopps if (count) 2040 1.1 chopps REG_WRITE(sc, RAY_HCSIR, 0); 2041 1.1 chopps 2042 1.84 msaitoh RAY_DPRINTF(("%s: interrupt handled %d\n", device_xname(sc->sc_dev), 2043 1.84 msaitoh count)); 2044 1.1 chopps 2045 1.1 chopps return (count ? 1 : 0); 2046 1.1 chopps } 2047 1.1 chopps 2048 1.1 chopps 2049 1.1 chopps /* 2050 1.1 chopps * Generic CCS handling 2051 1.1 chopps */ 2052 1.1 chopps 2053 1.1 chopps /* 2054 1.1 chopps * free the chain of descriptors -- used for freeing allocated tx chains 2055 1.1 chopps */ 2056 1.1 chopps static void 2057 1.72 dsl ray_free_ccs_chain(struct ray_softc *sc, u_int ni) 2058 1.1 chopps { 2059 1.1 chopps u_int i; 2060 1.1 chopps 2061 1.1 chopps while ((i = ni) != RAY_CCS_LINK_NULL) { 2062 1.1 chopps ni = SRAM_READ_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_link); 2063 1.1 chopps SRAM_WRITE_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_status, 2064 1.1 chopps RAY_CCS_STATUS_FREE); 2065 1.1 chopps } 2066 1.1 chopps } 2067 1.1 chopps 2068 1.1 chopps /* 2069 1.1 chopps * free up a cmd and return the old status 2070 1.1 chopps * this routine is only used for commands 2071 1.1 chopps */ 2072 1.93 msaitoh static uint8_t 2073 1.72 dsl ray_free_ccs(struct ray_softc *sc, bus_size_t ccs) 2074 1.1 chopps { 2075 1.93 msaitoh uint8_t stat; 2076 1.1 chopps 2077 1.80 chs RAY_DPRINTF(("%s: free_ccs idx %llu\n", device_xname(sc->sc_dev), 2078 1.58 christos (unsigned long long)RAY_GET_INDEX(ccs))); 2079 1.1 chopps 2080 1.1 chopps stat = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status); 2081 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_FREE); 2082 1.1 chopps if (ccs <= RAY_GET_CCS(RAY_CCS_LAST)) 2083 1.1 chopps sc->sc_ccsinuse[RAY_GET_INDEX(ccs)] = 0; 2084 1.1 chopps 2085 1.1 chopps return (stat); 2086 1.1 chopps } 2087 1.1 chopps 2088 1.1 chopps /* 2089 1.56 perry * returns 1 and in `ccb' the bus offset of the free ccb 2090 1.1 chopps * or 0 if none are free 2091 1.1 chopps * 2092 1.1 chopps * If `track' is not zero, handles tracking this command 2093 1.1 chopps * possibly indicating a callback is needed and setting a timeout 2094 1.1 chopps * also if ECF isn't ready we terminate earlier to avoid overhead. 2095 1.1 chopps * 2096 1.1 chopps * this routine is only used for commands 2097 1.1 chopps */ 2098 1.1 chopps static int 2099 1.73 dsl ray_alloc_ccs(struct ray_softc *sc, bus_size_t *ccsp, u_int cmd, u_int track) 2100 1.1 chopps { 2101 1.1 chopps bus_size_t ccs; 2102 1.1 chopps u_int i; 2103 1.1 chopps 2104 1.80 chs RAY_DPRINTF(("%s: alloc_ccs cmd %d\n", device_xname(sc->sc_dev), cmd)); 2105 1.1 chopps 2106 1.1 chopps /* for tracked commands, if not ready just set pending */ 2107 1.1 chopps if (track && !RAY_ECF_READY(sc)) { 2108 1.1 chopps ray_cmd_schedule(sc, track); 2109 1.1 chopps return (0); 2110 1.1 chopps } 2111 1.1 chopps 2112 1.1 chopps /* first scan our inuse array */ 2113 1.1 chopps for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) { 2114 1.1 chopps /* XXX wonder if we have to probe here to make the card go */ 2115 1.1 chopps (void)SRAM_READ_FIELD_1(sc, RAY_GET_CCS(i), ray_cmd, c_status); 2116 1.1 chopps if (!sc->sc_ccsinuse[i]) 2117 1.1 chopps break; 2118 1.1 chopps } 2119 1.1 chopps if (i > RAY_CCS_CMD_LAST) { 2120 1.1 chopps if (track) 2121 1.1 chopps ray_cmd_schedule(sc, track); 2122 1.1 chopps return (0); 2123 1.1 chopps } 2124 1.1 chopps sc->sc_ccsinuse[i] = 1; 2125 1.1 chopps ccs = RAY_GET_CCS(i); 2126 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_BUSY); 2127 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_cmd, cmd); 2128 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_link, RAY_CCS_LINK_NULL); 2129 1.1 chopps 2130 1.1 chopps *ccsp = ccs; 2131 1.1 chopps return (1); 2132 1.1 chopps } 2133 1.1 chopps 2134 1.1 chopps 2135 1.1 chopps /* 2136 1.1 chopps * this function sets the pending bit for the command given in 'need' 2137 1.1 chopps * and schedules a timeout if none is scheduled already. Any command 2138 1.1 chopps * that uses the `host to ecf' region must be serialized. 2139 1.1 chopps */ 2140 1.1 chopps static void 2141 1.72 dsl ray_set_pending(struct ray_softc *sc, u_int cmdf) 2142 1.1 chopps { 2143 1.84 msaitoh RAY_DPRINTF(("%s: ray_set_pending 0x%x\n", device_xname(sc->sc_dev), 2144 1.84 msaitoh cmdf)); 2145 1.1 chopps 2146 1.1 chopps sc->sc_scheduled |= cmdf; 2147 1.1 chopps if (!sc->sc_timoneed) { 2148 1.84 msaitoh RAY_DPRINTF(("%s: ray_set_pending new timo\n", 2149 1.84 msaitoh device_xname(sc->sc_dev))); 2150 1.17 thorpej callout_reset(&sc->sc_check_scheduled_ch, 2151 1.17 thorpej RAY_CHECK_SCHED_TIMEOUT, ray_check_scheduled, sc); 2152 1.1 chopps sc->sc_timoneed = 1; 2153 1.1 chopps } 2154 1.1 chopps } 2155 1.1 chopps 2156 1.1 chopps /* 2157 1.1 chopps * schedule the `cmdf' for completion later 2158 1.1 chopps */ 2159 1.1 chopps static void 2160 1.72 dsl ray_cmd_schedule(struct ray_softc *sc, int cmdf) 2161 1.1 chopps { 2162 1.1 chopps int track; 2163 1.1 chopps 2164 1.84 msaitoh RAY_DPRINTF(("%s: ray_cmd_schedule 0x%x\n", device_xname(sc->sc_dev), 2165 1.84 msaitoh cmdf)); 2166 1.1 chopps 2167 1.1 chopps track = cmdf; 2168 1.1 chopps if ((cmdf & SCP_UPD_MASK) == 0) 2169 1.1 chopps ray_set_pending(sc, track); 2170 1.1 chopps else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) { 2171 1.39 mjl /* don't do timeout mechanism if subcmd already going */ 2172 1.1 chopps sc->sc_scheduled |= cmdf; 2173 1.1 chopps } else 2174 1.1 chopps ray_set_pending(sc, cmdf | SCP_UPDATESUBCMD); 2175 1.1 chopps } 2176 1.1 chopps 2177 1.1 chopps /* 2178 1.1 chopps * check to see if `cmdf' has been scheduled 2179 1.1 chopps */ 2180 1.1 chopps static int 2181 1.72 dsl ray_cmd_is_scheduled(struct ray_softc *sc, int cmdf) 2182 1.1 chopps { 2183 1.84 msaitoh RAY_DPRINTF(("%s: ray_cmd_is_scheduled 0x%x\n", 2184 1.84 msaitoh device_xname(sc->sc_dev), cmdf)); 2185 1.1 chopps 2186 1.1 chopps return ((sc->sc_scheduled & cmdf) ? 1 : 0); 2187 1.1 chopps } 2188 1.1 chopps 2189 1.1 chopps /* 2190 1.1 chopps * cancel a scheduled command (not a running one though!) 2191 1.1 chopps */ 2192 1.1 chopps static void 2193 1.72 dsl ray_cmd_cancel(struct ray_softc *sc, int cmdf) 2194 1.1 chopps { 2195 1.84 msaitoh RAY_DPRINTF(("%s: ray_cmd_cancel 0x%x\n", device_xname(sc->sc_dev), 2196 1.84 msaitoh cmdf)); 2197 1.1 chopps 2198 1.1 chopps sc->sc_scheduled &= ~cmdf; 2199 1.1 chopps if ((cmdf & SCP_UPD_MASK) && (sc->sc_scheduled & SCP_UPD_MASK) == 0) 2200 1.1 chopps sc->sc_scheduled &= ~SCP_UPDATESUBCMD; 2201 1.1 chopps 2202 1.1 chopps /* if nothing else needed cancel the timer */ 2203 1.1 chopps if (sc->sc_scheduled == 0 && sc->sc_timoneed) { 2204 1.17 thorpej callout_stop(&sc->sc_check_scheduled_ch); 2205 1.1 chopps sc->sc_timoneed = 0; 2206 1.1 chopps } 2207 1.1 chopps } 2208 1.1 chopps 2209 1.1 chopps /* 2210 1.1 chopps * called to indicate the 'cmdf' has been issued 2211 1.1 chopps */ 2212 1.1 chopps static void 2213 1.72 dsl ray_cmd_ran(struct ray_softc *sc, int cmdf) 2214 1.1 chopps { 2215 1.84 msaitoh RAY_DPRINTF(("%s: ray_cmd_ran 0x%x\n", device_xname(sc->sc_dev), 2216 1.84 msaitoh cmdf)); 2217 1.1 chopps 2218 1.1 chopps if (cmdf & SCP_UPD_MASK) 2219 1.1 chopps sc->sc_running |= cmdf | SCP_UPDATESUBCMD; 2220 1.1 chopps else 2221 1.1 chopps sc->sc_running |= cmdf; 2222 1.1 chopps 2223 1.1 chopps if ((cmdf & SCP_TIMOCHECK_CMD_MASK) && !sc->sc_timocheck) { 2224 1.17 thorpej callout_reset(&sc->sc_check_ccs_ch, RAY_CHECK_CCS_TIMEOUT, 2225 1.17 thorpej ray_check_ccs, sc); 2226 1.1 chopps sc->sc_timocheck = 1; 2227 1.1 chopps } 2228 1.1 chopps } 2229 1.1 chopps 2230 1.1 chopps /* 2231 1.1 chopps * check to see if `cmdf' has been issued 2232 1.1 chopps */ 2233 1.1 chopps static int 2234 1.72 dsl ray_cmd_is_running(struct ray_softc *sc, int cmdf) 2235 1.1 chopps { 2236 1.84 msaitoh RAY_DPRINTF(("%s: ray_cmd_is_running 0x%x\n", device_xname(sc->sc_dev), 2237 1.84 msaitoh cmdf)); 2238 1.1 chopps 2239 1.1 chopps return ((sc->sc_running & cmdf) ? 1 : 0); 2240 1.1 chopps } 2241 1.1 chopps 2242 1.1 chopps /* 2243 1.1 chopps * the given `cmdf' that was issued has completed 2244 1.1 chopps */ 2245 1.1 chopps static void 2246 1.72 dsl ray_cmd_done(struct ray_softc *sc, int cmdf) 2247 1.1 chopps { 2248 1.84 msaitoh RAY_DPRINTF(("%s: ray_cmd_done 0x%x\n", device_xname(sc->sc_dev), 2249 1.84 msaitoh cmdf)); 2250 1.1 chopps 2251 1.1 chopps sc->sc_running &= ~cmdf; 2252 1.1 chopps if (cmdf & SCP_UPD_MASK) { 2253 1.1 chopps sc->sc_running &= ~SCP_UPDATESUBCMD; 2254 1.1 chopps if (sc->sc_scheduled & SCP_UPD_MASK) 2255 1.1 chopps ray_cmd_schedule(sc, sc->sc_scheduled & SCP_UPD_MASK); 2256 1.1 chopps } 2257 1.1 chopps if ((sc->sc_running & SCP_TIMOCHECK_CMD_MASK) == 0 && sc->sc_timocheck){ 2258 1.17 thorpej callout_stop(&sc->sc_check_ccs_ch); 2259 1.1 chopps sc->sc_timocheck = 0; 2260 1.1 chopps } 2261 1.1 chopps } 2262 1.1 chopps 2263 1.1 chopps /* 2264 1.1 chopps * issue the command 2265 1.1 chopps * only used for commands not tx 2266 1.1 chopps */ 2267 1.1 chopps static int 2268 1.72 dsl ray_issue_cmd(struct ray_softc *sc, bus_size_t ccs, u_int track) 2269 1.1 chopps { 2270 1.1 chopps u_int i; 2271 1.1 chopps 2272 1.84 msaitoh RAY_DPRINTF(("%s: ray_cmd_issue 0x%x\n", device_xname(sc->sc_dev), 2273 1.84 msaitoh track)); 2274 1.1 chopps 2275 1.1 chopps /* 2276 1.56 perry * XXX other drivers did this, but I think 2277 1.1 chopps * what we really want to do is just make sure we don't 2278 1.1 chopps * get here or that spinning is ok 2279 1.1 chopps */ 2280 1.1 chopps i = 0; 2281 1.1 chopps while (!RAY_ECF_READY(sc)) 2282 1.1 chopps if (++i > 50) { 2283 1.1 chopps ray_free_ccs(sc, ccs); 2284 1.1 chopps if (track) 2285 1.1 chopps ray_cmd_schedule(sc, track); 2286 1.1 chopps return (0); 2287 1.1 chopps } 2288 1.1 chopps 2289 1.1 chopps SRAM_WRITE_1(sc, RAY_SCB_CCSI, RAY_GET_INDEX(ccs)); 2290 1.1 chopps RAY_ECF_START_CMD(sc); 2291 1.1 chopps ray_cmd_ran(sc, track); 2292 1.1 chopps 2293 1.1 chopps return (1); 2294 1.1 chopps } 2295 1.1 chopps 2296 1.1 chopps /* 2297 1.1 chopps * send a simple command if we can 2298 1.1 chopps */ 2299 1.1 chopps static int 2300 1.73 dsl ray_simple_cmd(struct ray_softc *sc, u_int cmd, u_int track) 2301 1.1 chopps { 2302 1.1 chopps bus_size_t ccs; 2303 1.1 chopps 2304 1.1 chopps return (ray_alloc_ccs(sc, &ccs, cmd, track) && 2305 1.1 chopps ray_issue_cmd(sc, ccs, track)); 2306 1.1 chopps } 2307 1.56 perry 2308 1.1 chopps /* 2309 1.1 chopps * Functions based on CCS commands 2310 1.1 chopps */ 2311 1.1 chopps 2312 1.1 chopps /* 2313 1.1 chopps * run a update subcommand 2314 1.1 chopps */ 2315 1.1 chopps static void 2316 1.72 dsl ray_update_subcmd(struct ray_softc *sc) 2317 1.1 chopps { 2318 1.1 chopps int submask, i; 2319 1.1 chopps 2320 1.80 chs RAY_DPRINTF(("%s: ray_update_subcmd\n", device_xname(sc->sc_dev))); 2321 1.1 chopps 2322 1.1 chopps ray_cmd_cancel(sc, SCP_UPDATESUBCMD); 2323 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 2324 1.1 chopps return; 2325 1.1 chopps submask = SCP_UPD_FIRST; 2326 1.1 chopps for (i = 0; i < ray_nsubcmdtab; submask <<= 1, i++) { 2327 1.1 chopps if ((sc->sc_scheduled & SCP_UPD_MASK) == 0) 2328 1.1 chopps break; 2329 1.1 chopps /* when done the next command will be scheduled */ 2330 1.1 chopps if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) 2331 1.1 chopps break; 2332 1.1 chopps if (!RAY_ECF_READY(sc)) 2333 1.1 chopps break; 2334 1.1 chopps /* 2335 1.39 mjl * give priority to LSB -- e.g., if previous loop rescheduled 2336 1.1 chopps * doing this command after calling the function won't catch 2337 1.1 chopps * if a later command sets an earlier bit 2338 1.1 chopps */ 2339 1.1 chopps if (sc->sc_scheduled & ((submask - 1) & SCP_UPD_MASK)) 2340 1.1 chopps break; 2341 1.1 chopps if (sc->sc_scheduled & submask) 2342 1.1 chopps (*ray_subcmdtab[i])(sc); 2343 1.1 chopps } 2344 1.1 chopps } 2345 1.1 chopps 2346 1.1 chopps /* 2347 1.1 chopps * report a parameter 2348 1.1 chopps */ 2349 1.1 chopps static void 2350 1.72 dsl ray_report_params(struct ray_softc *sc) 2351 1.1 chopps { 2352 1.1 chopps bus_size_t ccs; 2353 1.1 chopps 2354 1.1 chopps ray_cmd_cancel(sc, SCP_REPORTPARAMS); 2355 1.1 chopps 2356 1.1 chopps if (!sc->sc_repreq) 2357 1.1 chopps return; 2358 1.1 chopps 2359 1.1 chopps /* do the issue check before equality check */ 2360 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 2361 1.1 chopps return; 2362 1.1 chopps else if (ray_cmd_is_running(sc, SCP_REPORTPARAMS)) { 2363 1.1 chopps ray_cmd_schedule(sc, SCP_REPORTPARAMS); 2364 1.1 chopps return; 2365 1.1 chopps } else if (!ray_alloc_ccs(sc, &ccs, RAY_CMD_REPORT_PARAMS, 2366 1.1 chopps SCP_REPORTPARAMS)) 2367 1.1 chopps return; 2368 1.1 chopps 2369 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_paramid, 2370 1.1 chopps sc->sc_repreq->r_paramid); 2371 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_nparam, 1); 2372 1.1 chopps (void)ray_issue_cmd(sc, ccs, SCP_REPORTPARAMS); 2373 1.1 chopps } 2374 1.1 chopps 2375 1.1 chopps /* 2376 1.1 chopps * start an association 2377 1.1 chopps */ 2378 1.1 chopps static void 2379 1.72 dsl ray_start_assoc(struct ray_softc *sc) 2380 1.1 chopps { 2381 1.1 chopps ray_cmd_cancel(sc, SCP_STARTASSOC); 2382 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 2383 1.1 chopps return; 2384 1.1 chopps else if (ray_cmd_is_running(sc, SCP_STARTASSOC)) 2385 1.1 chopps return; 2386 1.1 chopps (void)ray_simple_cmd(sc, RAY_CMD_START_ASSOC, SCP_STARTASSOC); 2387 1.1 chopps } 2388 1.1 chopps 2389 1.1 chopps /* 2390 1.1 chopps * Subcommand functions that use the SCP_UPDATESUBCMD command 2391 1.1 chopps * (and are serialized with respect to other update sub commands 2392 1.1 chopps */ 2393 1.1 chopps 2394 1.1 chopps /* 2395 1.1 chopps * download the startup parameters to the card 2396 1.1 chopps * -- no outstanding commands expected 2397 1.1 chopps */ 2398 1.1 chopps static void 2399 1.72 dsl ray_download_params(struct ray_softc *sc) 2400 1.1 chopps { 2401 1.1 chopps struct ray_startup_params_head *sp; 2402 1.1 chopps struct ray_startup_params_tail_5 *sp5; 2403 1.1 chopps struct ray_startup_params_tail_4 *sp4; 2404 1.1 chopps bus_size_t off; 2405 1.1 chopps 2406 1.80 chs RAY_DPRINTF(("%s: init_startup_params\n", device_xname(sc->sc_dev))); 2407 1.1 chopps 2408 1.1 chopps ray_cmd_cancel(sc, SCP_UPD_STARTUP); 2409 1.1 chopps 2410 1.1 chopps #define PUT2(p, v) \ 2411 1.1 chopps do { (p)[0] = ((v >> 8) & 0xff); (p)[1] = (v & 0xff); } while(0) 2412 1.1 chopps 2413 1.1 chopps sp = &sc->sc_startup; 2414 1.1 chopps sp4 = &sc->sc_startup_4; 2415 1.1 chopps sp5 = &sc->sc_startup_5; 2416 1.1 chopps memset(sp, 0, sizeof(*sp)); 2417 1.1 chopps if (sc->sc_version == SC_BUILD_4) 2418 1.1 chopps memset(sp4, 0, sizeof(*sp4)); 2419 1.1 chopps else 2420 1.1 chopps memset(sp5, 0, sizeof(*sp5)); 2421 1.21 onoe /* XXX: Raylink firmware doesn't have length field for ssid */ 2422 1.21 onoe memcpy(sp->sp_ssid, sc->sc_dnwid.i_nwid, sizeof(sp->sp_ssid)); 2423 1.1 chopps sp->sp_scan_mode = 0x1; 2424 1.1 chopps memcpy(sp->sp_mac_addr, sc->sc_ecf_startup.e_station_addr, 2425 1.1 chopps ETHER_ADDR_LEN); 2426 1.1 chopps PUT2(sp->sp_frag_thresh, 0x7fff); /* disabled */ 2427 1.1 chopps if (sc->sc_version == SC_BUILD_4) { 2428 1.1 chopps #if 1 2429 1.1 chopps /* linux/fbsd */ 2430 1.1 chopps PUT2(sp->sp_dwell_time, 0x200); 2431 1.56 perry PUT2(sp->sp_beacon_period, 1); 2432 1.1 chopps #else 2433 1.1 chopps /* divined */ 2434 1.1 chopps PUT2(sp->sp_dwell_time, 0x400); 2435 1.56 perry PUT2(sp->sp_beacon_period, 0); 2436 1.1 chopps #endif 2437 1.1 chopps } else { 2438 1.1 chopps PUT2(sp->sp_dwell_time, 128); 2439 1.56 perry PUT2(sp->sp_beacon_period, 256); 2440 1.1 chopps } 2441 1.1 chopps sp->sp_dtim_interval = 1; 2442 1.1 chopps #if 0 2443 1.1 chopps /* these are the documented defaults for build 5/6 */ 2444 1.1 chopps sp->sp_max_retry = 0x1f; 2445 1.1 chopps sp->sp_ack_timo = 0x86; 2446 1.1 chopps sp->sp_sifs = 0x1c; 2447 1.1 chopps #elif 1 2448 1.1 chopps /* these were scrounged from the linux driver */ 2449 1.56 perry sp->sp_max_retry = 0x07; 2450 1.1 chopps 2451 1.1 chopps sp->sp_ack_timo = 0xa3; 2452 1.1 chopps sp->sp_sifs = 0x1d; 2453 1.1 chopps #else 2454 1.1 chopps /* these were divined */ 2455 1.56 perry sp->sp_max_retry = 0x03; 2456 1.1 chopps 2457 1.1 chopps sp->sp_ack_timo = 0xa3; 2458 1.1 chopps sp->sp_sifs = 0x1d; 2459 1.1 chopps #endif 2460 1.1 chopps #if 0 2461 1.1 chopps /* these are the documented defaults for build 5/6 */ 2462 1.1 chopps sp->sp_difs = 0x82; 2463 1.1 chopps sp->sp_pifs = 0; 2464 1.1 chopps #else 2465 1.1 chopps /* linux/fbsd */ 2466 1.1 chopps sp->sp_difs = 0x82; 2467 1.1 chopps 2468 1.1 chopps if (sc->sc_version == SC_BUILD_4) 2469 1.1 chopps sp->sp_pifs = 0xce; 2470 1.1 chopps else 2471 1.1 chopps sp->sp_pifs = 0x4e; 2472 1.1 chopps #endif 2473 1.1 chopps 2474 1.1 chopps PUT2(sp->sp_rts_thresh, 0x7fff); /* disabled */ 2475 1.1 chopps if (sc->sc_version == SC_BUILD_4) { 2476 1.1 chopps PUT2(sp->sp_scan_dwell, 0xfb1e); 2477 1.1 chopps PUT2(sp->sp_scan_max_dwell, 0xc75c); 2478 1.1 chopps } else { 2479 1.1 chopps PUT2(sp->sp_scan_dwell, 0x4e2); 2480 1.1 chopps PUT2(sp->sp_scan_max_dwell, 0x38a4); 2481 1.1 chopps } 2482 1.1 chopps sp->sp_assoc_timo = 0x5; 2483 1.1 chopps if (sc->sc_version == SC_BUILD_4) { 2484 1.1 chopps #if 0 2485 1.1 chopps /* linux/fbsd */ 2486 1.1 chopps sp->sp_adhoc_scan_cycle = 0x4; 2487 1.1 chopps sp->sp_infra_scan_cycle = 0x2; 2488 1.1 chopps sp->sp_infra_super_scan_cycle = 0x4; 2489 1.1 chopps #else 2490 1.1 chopps /* divined */ 2491 1.1 chopps sp->sp_adhoc_scan_cycle = 0x8; 2492 1.1 chopps sp->sp_infra_scan_cycle = 0x1; 2493 1.1 chopps sp->sp_infra_super_scan_cycle = 0x18; 2494 1.1 chopps #endif 2495 1.1 chopps } else { 2496 1.1 chopps sp->sp_adhoc_scan_cycle = 0x8; 2497 1.1 chopps sp->sp_infra_scan_cycle = 0x2; 2498 1.1 chopps sp->sp_infra_super_scan_cycle = 0x8; 2499 1.1 chopps } 2500 1.1 chopps sp->sp_promisc = sc->sc_promisc; 2501 1.1 chopps PUT2(sp->sp_uniq_word, 0x0cbd); 2502 1.1 chopps if (sc->sc_version == SC_BUILD_4) { 2503 1.39 mjl /* XXX what is this value anyway..? the std says 50us */ 2504 1.1 chopps /* XXX sp->sp_slot_time = 0x4e; */ 2505 1.1 chopps sp->sp_slot_time = 0x4e; 2506 1.1 chopps #if 1 2507 1.1 chopps /*linux/fbsd*/ 2508 1.1 chopps sp->sp_roam_low_snr_thresh = 0xff; 2509 1.1 chopps #else 2510 1.1 chopps /*divined*/ 2511 1.1 chopps sp->sp_roam_low_snr_thresh = 0x30; 2512 1.1 chopps #endif 2513 1.1 chopps } else { 2514 1.1 chopps sp->sp_slot_time = 0x32; 2515 1.1 chopps sp->sp_roam_low_snr_thresh = 0xff; /* disabled */ 2516 1.1 chopps } 2517 1.1 chopps #if 1 2518 1.1 chopps sp->sp_low_snr_count = 0xff; /* disabled */ 2519 1.1 chopps #else 2520 1.1 chopps /* divined -- check */ 2521 1.1 chopps sp->sp_low_snr_count = 0x07; /* disabled */ 2522 1.1 chopps #endif 2523 1.1 chopps #if 0 2524 1.1 chopps sp->sp_infra_missed_beacon_count = 0x2; 2525 1.1 chopps #elif 1 2526 1.1 chopps /* linux/fbsd */ 2527 1.1 chopps sp->sp_infra_missed_beacon_count = 0x5; 2528 1.1 chopps #else 2529 1.1 chopps /* divined -- check, looks fishy */ 2530 1.1 chopps sp->sp_infra_missed_beacon_count = 0x7; 2531 1.1 chopps #endif 2532 1.1 chopps sp->sp_adhoc_missed_beacon_count = 0xff; 2533 1.1 chopps sp->sp_country_code = sc->sc_dcountrycode; 2534 1.1 chopps sp->sp_hop_seq = 0x0b; 2535 1.1 chopps if (sc->sc_version == SC_BUILD_4) { 2536 1.1 chopps sp->sp_hop_seq_len = 0x4e; 2537 1.1 chopps sp4->sp_cw_max = 0x3f; /* single byte on build 4 */ 2538 1.1 chopps sp4->sp_cw_min = 0x0f; /* single byte on build 4 */ 2539 1.1 chopps sp4->sp_noise_filter_gain = 0x4; 2540 1.1 chopps sp4->sp_noise_limit_offset = 0x8; 2541 1.1 chopps sp4->sp_rssi_thresh_offset = 0x28; 2542 1.1 chopps sp4->sp_busy_thresh_offset = 0x28; 2543 1.1 chopps sp4->sp_sync_thresh = 0x07; 2544 1.1 chopps sp4->sp_test_mode = 0x0; 2545 1.1 chopps sp4->sp_test_min_chan = 0x2; 2546 1.1 chopps sp4->sp_test_max_chan = 0x2; 2547 1.1 chopps } else { 2548 1.1 chopps sp->sp_hop_seq_len = 0x4f; 2549 1.1 chopps PUT2(sp5->sp_cw_max, 0x3f); 2550 1.1 chopps PUT2(sp5->sp_cw_min, 0x0f); 2551 1.1 chopps sp5->sp_noise_filter_gain = 0x4; 2552 1.1 chopps sp5->sp_noise_limit_offset = 0x8; 2553 1.1 chopps sp5->sp_rssi_thresh_offset = 0x28; 2554 1.1 chopps sp5->sp_busy_thresh_offset = 0x28; 2555 1.1 chopps sp5->sp_sync_thresh = 0x07; 2556 1.1 chopps sp5->sp_test_mode = 0x0; 2557 1.1 chopps sp5->sp_test_min_chan = 0x2; 2558 1.1 chopps sp5->sp_test_max_chan = 0x2; 2559 1.1 chopps #if 0 2560 1.1 chopps sp5->sp_allow_probe_resp = 0x1; 2561 1.1 chopps #else 2562 1.1 chopps sp5->sp_allow_probe_resp = 0x0; 2563 1.1 chopps #endif 2564 1.1 chopps sp5->sp_privacy_must_start = 0x0; 2565 1.1 chopps sp5->sp_privacy_can_join = 0x0; 2566 1.1 chopps sp5->sp_basic_rate_set[0] = 0x2; 2567 1.1 chopps /* 2 = 1Mbps, 3 = old 2Mbps 4 = 2Mbps */ 2568 1.1 chopps } 2569 1.1 chopps 2570 1.1 chopps /* we shouldn't be called with some command pending */ 2571 1.1 chopps if (!RAY_ECF_READY(sc)) 2572 1.1 chopps panic("ray_download_params busy"); 2573 1.1 chopps 2574 1.1 chopps /* write the compatible part */ 2575 1.1 chopps off = RAY_HOST_TO_ECF_BASE; 2576 1.1 chopps ray_write_region(sc, off, sp, sizeof(sc->sc_startup)); 2577 1.1 chopps off += sizeof(sc->sc_startup); 2578 1.1 chopps if (sc->sc_version == SC_BUILD_4) 2579 1.1 chopps ray_write_region(sc, off, sp4, sizeof(*sp4)); 2580 1.1 chopps else 2581 1.1 chopps ray_write_region(sc, off, sp5, sizeof(*sp5)); 2582 1.1 chopps if (!ray_simple_cmd(sc, RAY_CMD_START_PARAMS, SCP_UPD_STARTUP)) 2583 1.1 chopps panic("ray_download_params issue"); 2584 1.1 chopps } 2585 1.1 chopps 2586 1.1 chopps /* 2587 1.1 chopps * start or join a network 2588 1.1 chopps */ 2589 1.1 chopps static void 2590 1.72 dsl ray_start_join_net(struct ray_softc *sc) 2591 1.1 chopps { 2592 1.1 chopps struct ray_net_params np; 2593 1.1 chopps bus_size_t ccs; 2594 1.1 chopps int cmd; 2595 1.1 chopps 2596 1.1 chopps ray_cmd_cancel(sc, SCP_UPD_STARTJOIN); 2597 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 2598 1.1 chopps return; 2599 1.1 chopps 2600 1.1 chopps /* XXX check we may not want to re-issue */ 2601 1.1 chopps if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) { 2602 1.1 chopps ray_cmd_schedule(sc, SCP_UPD_STARTJOIN); 2603 1.1 chopps return; 2604 1.1 chopps } 2605 1.1 chopps 2606 1.1 chopps if (sc->sc_mode == SC_MODE_ADHOC) 2607 1.1 chopps cmd = RAY_CMD_START_NET; 2608 1.1 chopps else 2609 1.1 chopps cmd = RAY_CMD_JOIN_NET; 2610 1.1 chopps 2611 1.1 chopps if (!ray_alloc_ccs(sc, &ccs, cmd, SCP_UPD_STARTJOIN)) 2612 1.1 chopps return; 2613 1.1 chopps sc->sc_startccs = ccs; 2614 1.1 chopps sc->sc_startcmd = cmd; 2615 1.21 onoe if (!memcmp(&sc->sc_cnwid, &sc->sc_dnwid, sizeof(sc->sc_cnwid)) 2616 1.1 chopps && sc->sc_omode == sc->sc_mode) 2617 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 0); 2618 1.1 chopps else { 2619 1.4 chopps sc->sc_havenet = 0; 2620 1.1 chopps memset(&np, 0, sizeof(np)); 2621 1.1 chopps np.p_net_type = sc->sc_mode; 2622 1.21 onoe memcpy(np.p_ssid, sc->sc_dnwid.i_nwid, sizeof(np.p_ssid)); 2623 1.1 chopps ray_write_region(sc, RAY_HOST_TO_ECF_BASE, &np, sizeof(np)); 2624 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 1); 2625 1.1 chopps } 2626 1.1 chopps if (ray_issue_cmd(sc, ccs, SCP_UPD_STARTJOIN)) 2627 1.17 thorpej callout_reset(&sc->sc_start_join_timo_ch, RAY_START_TIMEOUT, 2628 1.17 thorpej ray_start_join_timo, sc); 2629 1.1 chopps } 2630 1.1 chopps 2631 1.1 chopps static void 2632 1.72 dsl ray_start_join_timo(void *arg) 2633 1.1 chopps { 2634 1.1 chopps struct ray_softc *sc; 2635 1.1 chopps u_int stat; 2636 1.1 chopps 2637 1.1 chopps sc = arg; 2638 1.1 chopps stat = SRAM_READ_FIELD_1(sc, sc->sc_startccs, ray_cmd, c_status); 2639 1.1 chopps ray_start_join_net_done(sc, sc->sc_startcmd, sc->sc_startccs, stat); 2640 1.1 chopps } 2641 1.1 chopps 2642 1.1 chopps /* 2643 1.1 chopps * The start/join has completed. Note: we timeout the start 2644 1.1 chopps * command because it seems to fail to work at least on the 2645 1.1 chopps * build 4 firmware without reporting an error. This actually 2646 1.1 chopps * may be a result of not putting the correct params in the 2647 1.1 chopps * initial download. If this is a timeout `stat' will be 2648 1.1 chopps * marked busy. 2649 1.1 chopps */ 2650 1.1 chopps static ray_cmd_func_t 2651 1.84 msaitoh ray_start_join_net_done(struct ray_softc *sc, u_int cmd, bus_size_t ccs, 2652 1.84 msaitoh u_int stat) 2653 1.1 chopps { 2654 1.21 onoe int i; 2655 1.1 chopps struct ray_net_params np; 2656 1.1 chopps 2657 1.17 thorpej callout_stop(&sc->sc_start_join_timo_ch); 2658 1.1 chopps ray_cmd_done(sc, SCP_UPD_STARTJOIN); 2659 1.1 chopps 2660 1.1 chopps if (stat == RAY_CCS_STATUS_FAIL) { 2661 1.1 chopps /* XXX poke ifmedia when it supports this */ 2662 1.1 chopps sc->sc_havenet = 0; 2663 1.1 chopps return (ray_start_join_net); 2664 1.1 chopps } 2665 1.1 chopps if (stat == RAY_CCS_STATUS_BUSY || stat == RAY_CCS_STATUS_FREE) { 2666 1.1 chopps /* handle the timeout condition */ 2667 1.17 thorpej callout_reset(&sc->sc_start_join_timo_ch, RAY_START_TIMEOUT, 2668 1.17 thorpej ray_start_join_timo, sc); 2669 1.1 chopps 2670 1.1 chopps /* be safe -- not a lot occurs with no net though */ 2671 1.1 chopps if (!RAY_ECF_READY(sc)) 2672 1.1 chopps return (0); 2673 1.1 chopps 2674 1.1 chopps /* see if our nwid is up to date */ 2675 1.21 onoe if (!memcmp(&sc->sc_cnwid, &sc->sc_dnwid, sizeof(sc->sc_cnwid)) 2676 1.1 chopps && sc->sc_omode == sc->sc_mode) 2677 1.93 msaitoh SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 2678 1.93 msaitoh 0); 2679 1.1 chopps else { 2680 1.1 chopps memset(&np, 0, sizeof(np)); 2681 1.1 chopps np.p_net_type = sc->sc_mode; 2682 1.21 onoe memcpy(np.p_ssid, sc->sc_dnwid.i_nwid, 2683 1.21 onoe sizeof(np.p_ssid)); 2684 1.1 chopps ray_write_region(sc, RAY_HOST_TO_ECF_BASE, &np, 2685 1.1 chopps sizeof(np)); 2686 1.93 msaitoh SRAM_WRITE_FIELD_1(sc,ccs, ray_cmd_net, c_upd_param, 2687 1.93 msaitoh 1); 2688 1.1 chopps } 2689 1.1 chopps 2690 1.1 chopps if (sc->sc_mode == SC_MODE_ADHOC) 2691 1.1 chopps cmd = RAY_CMD_START_NET; 2692 1.1 chopps else 2693 1.1 chopps cmd = RAY_CMD_JOIN_NET; 2694 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_cmd, 2695 1.1 chopps RAY_CCS_STATUS_BUSY); 2696 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_status, 2697 1.1 chopps RAY_CCS_STATUS_BUSY); 2698 1.1 chopps 2699 1.1 chopps /* we simply poke the card again issuing the same ccs */ 2700 1.1 chopps SRAM_WRITE_1(sc, RAY_SCB_CCSI, RAY_GET_INDEX(ccs)); 2701 1.1 chopps RAY_ECF_START_CMD(sc); 2702 1.1 chopps ray_cmd_ran(sc, SCP_UPD_STARTJOIN); 2703 1.1 chopps return (0); 2704 1.1 chopps } 2705 1.1 chopps /* get the current ssid */ 2706 1.1 chopps SRAM_READ_FIELD_N(sc, ccs, ray_cmd_net, c_bss_id, sc->sc_bssid, 2707 1.1 chopps sizeof(sc->sc_bssid)); 2708 1.1 chopps 2709 1.1 chopps sc->sc_deftxrate = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_net,c_def_txrate); 2710 1.1 chopps sc->sc_encrypt = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_net, c_encrypt); 2711 1.1 chopps 2712 1.1 chopps /* adjust values for buggy build 4 */ 2713 1.1 chopps if (sc->sc_deftxrate == 0x55) 2714 1.1 chopps sc->sc_deftxrate = RAY_PID_BASIC_RATE_1500K; 2715 1.1 chopps if (sc->sc_encrypt == 0x55) 2716 1.1 chopps sc->sc_encrypt = 0; 2717 1.1 chopps 2718 1.1 chopps if (SRAM_READ_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param)) { 2719 1.1 chopps ray_read_region(sc, RAY_HOST_TO_ECF_BASE, &np, sizeof(np)); 2720 1.21 onoe /* XXX: Raylink firmware doesn't have length field for ssid */ 2721 1.21 onoe for (i = 0; i < sizeof(np.p_ssid); i++) { 2722 1.21 onoe if (np.p_ssid[i] == '\0') 2723 1.21 onoe break; 2724 1.21 onoe } 2725 1.21 onoe sc->sc_cnwid.i_len = i; 2726 1.81 msaitoh memcpy(sc->sc_cnwid.i_nwid, np.p_ssid, i); 2727 1.1 chopps sc->sc_omode = sc->sc_mode; 2728 1.1 chopps if (np.p_net_type != sc->sc_mode) 2729 1.1 chopps return (ray_start_join_net); 2730 1.1 chopps } 2731 1.3 chopps RAY_DPRINTF(("%s: net start/join nwid %.32s bssid %s inited %d\n", 2732 1.84 msaitoh device_xname(sc->sc_dev), sc->sc_cnwid.i_nwid, 2733 1.84 msaitoh ether_sprintf(sc->sc_bssid), 2734 1.84 msaitoh SRAM_READ_FIELD_1(sc, ccs, ray_cmd_net, c_inited))); 2735 1.1 chopps 2736 1.1 chopps /* network is now active */ 2737 1.93 msaitoh ray_cmd_schedule(sc, SCP_UPD_MCAST | SCP_UPD_PROMISC); 2738 1.1 chopps if (cmd == RAY_CMD_JOIN_NET) 2739 1.1 chopps return (ray_start_assoc); 2740 1.4 chopps else { 2741 1.4 chopps sc->sc_havenet = 1; 2742 1.1 chopps return (ray_intr_start); 2743 1.4 chopps } 2744 1.1 chopps } 2745 1.1 chopps 2746 1.1 chopps /* 2747 1.1 chopps * set the card in/out of promiscuous mode 2748 1.1 chopps */ 2749 1.1 chopps static void 2750 1.72 dsl ray_update_promisc(struct ray_softc *sc) 2751 1.1 chopps { 2752 1.1 chopps bus_size_t ccs; 2753 1.1 chopps int promisc; 2754 1.1 chopps 2755 1.1 chopps ray_cmd_cancel(sc, SCP_UPD_PROMISC); 2756 1.1 chopps 2757 1.1 chopps /* do the issue check before equality check */ 2758 1.22 thorpej if (sc->sc_if.if_flags & IFF_ALLMULTI) 2759 1.22 thorpej sc->sc_if.if_flags |= IFF_PROMISC; 2760 1.22 thorpej else if (sc->sc_if.if_pcount == 0) 2761 1.22 thorpej sc->sc_if.if_flags &= ~IFF_PROMISC; 2762 1.22 thorpej promisc = !!(sc->sc_if.if_flags & IFF_PROMISC); 2763 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 2764 1.1 chopps return; 2765 1.1 chopps else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) { 2766 1.1 chopps ray_cmd_schedule(sc, SCP_UPD_PROMISC); 2767 1.1 chopps return; 2768 1.1 chopps } else if (promisc == sc->sc_promisc) 2769 1.1 chopps return; 2770 1.1 chopps else if (!ray_alloc_ccs(sc,&ccs,RAY_CMD_UPDATE_PARAMS, SCP_UPD_PROMISC)) 2771 1.1 chopps return; 2772 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_paramid, RAY_PID_PROMISC); 2773 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_nparam, 1); 2774 1.1 chopps SRAM_WRITE_1(sc, RAY_HOST_TO_ECF_BASE, promisc); 2775 1.1 chopps (void)ray_issue_cmd(sc, ccs, SCP_UPD_PROMISC); 2776 1.1 chopps } 2777 1.1 chopps 2778 1.1 chopps /* 2779 1.1 chopps * update the parameter based on what the user passed in 2780 1.1 chopps */ 2781 1.1 chopps static void 2782 1.72 dsl ray_update_params(struct ray_softc *sc) 2783 1.1 chopps { 2784 1.1 chopps bus_size_t ccs; 2785 1.1 chopps 2786 1.1 chopps ray_cmd_cancel(sc, SCP_UPD_UPDATEPARAMS); 2787 1.1 chopps if (!sc->sc_updreq) { 2788 1.1 chopps /* XXX do we need to wakeup here? */ 2789 1.1 chopps return; 2790 1.1 chopps } 2791 1.1 chopps 2792 1.1 chopps /* do the issue check before equality check */ 2793 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 2794 1.1 chopps return; 2795 1.1 chopps else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) { 2796 1.1 chopps ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS); 2797 1.1 chopps return; 2798 1.1 chopps } else if (!ray_alloc_ccs(sc, &ccs, RAY_CMD_UPDATE_PARAMS, 2799 1.1 chopps SCP_UPD_UPDATEPARAMS)) 2800 1.1 chopps return; 2801 1.1 chopps 2802 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_paramid, 2803 1.1 chopps sc->sc_updreq->r_paramid); 2804 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_nparam, 1); 2805 1.1 chopps ray_write_region(sc, RAY_HOST_TO_ECF_BASE, sc->sc_updreq->r_data, 2806 1.1 chopps sc->sc_updreq->r_len); 2807 1.1 chopps 2808 1.1 chopps (void)ray_issue_cmd(sc, ccs, SCP_UPD_UPDATEPARAMS); 2809 1.1 chopps } 2810 1.1 chopps 2811 1.1 chopps /* 2812 1.1 chopps * set the multicast filter list 2813 1.1 chopps */ 2814 1.1 chopps static void 2815 1.72 dsl ray_update_mcast(struct ray_softc *sc) 2816 1.1 chopps { 2817 1.1 chopps bus_size_t ccs; 2818 1.1 chopps struct ether_multistep step; 2819 1.1 chopps struct ether_multi *enm; 2820 1.1 chopps struct ethercom *ec; 2821 1.1 chopps bus_size_t bufp; 2822 1.1 chopps int count; 2823 1.1 chopps 2824 1.1 chopps ec = &sc->sc_ec; 2825 1.1 chopps ray_cmd_cancel(sc, SCP_UPD_MCAST); 2826 1.1 chopps 2827 1.96 msaitoh ETHER_LOCK(ec); 2828 1.1 chopps /* see if we have any ranges */ 2829 1.1 chopps if ((count = sc->sc_ec.ec_multicnt) < 17) { 2830 1.1 chopps ETHER_FIRST_MULTI(step, ec, enm); 2831 1.1 chopps while (enm) { 2832 1.1 chopps /* see if this is a range */ 2833 1.1 chopps if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 2834 1.1 chopps ETHER_ADDR_LEN)) { 2835 1.1 chopps count = 17; 2836 1.1 chopps break; 2837 1.1 chopps } 2838 1.1 chopps ETHER_NEXT_MULTI(step, enm); 2839 1.1 chopps } 2840 1.1 chopps } 2841 1.96 msaitoh ETHER_UNLOCK(ec); 2842 1.1 chopps 2843 1.1 chopps /* track this stuff even when not running */ 2844 1.1 chopps if (count > 16) { 2845 1.1 chopps sc->sc_if.if_flags |= IFF_ALLMULTI; 2846 1.1 chopps ray_update_promisc(sc); 2847 1.1 chopps return; 2848 1.1 chopps } else if (sc->sc_if.if_flags & IFF_ALLMULTI) { 2849 1.1 chopps sc->sc_if.if_flags &= ~IFF_ALLMULTI; 2850 1.1 chopps ray_update_promisc(sc); 2851 1.1 chopps } 2852 1.1 chopps 2853 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 2854 1.1 chopps return; 2855 1.1 chopps else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) { 2856 1.1 chopps ray_cmd_schedule(sc, SCP_UPD_MCAST); 2857 1.1 chopps return; 2858 1.1 chopps } else if (!ray_alloc_ccs(sc,&ccs, RAY_CMD_UPDATE_MCAST, SCP_UPD_MCAST)) 2859 1.1 chopps return; 2860 1.1 chopps SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update_mcast, c_nmcast, count); 2861 1.1 chopps bufp = RAY_HOST_TO_ECF_BASE; 2862 1.94 msaitoh ETHER_LOCK(ec); 2863 1.1 chopps ETHER_FIRST_MULTI(step, ec, enm); 2864 1.1 chopps while (enm) { 2865 1.1 chopps ray_write_region(sc, bufp, enm->enm_addrlo, ETHER_ADDR_LEN); 2866 1.1 chopps bufp += ETHER_ADDR_LEN; 2867 1.1 chopps ETHER_NEXT_MULTI(step, enm); 2868 1.1 chopps } 2869 1.94 msaitoh ETHER_UNLOCK(ec); 2870 1.1 chopps (void)ray_issue_cmd(sc, ccs, SCP_UPD_MCAST); 2871 1.1 chopps } 2872 1.1 chopps 2873 1.1 chopps /* 2874 1.1 chopps * User issued commands 2875 1.1 chopps */ 2876 1.1 chopps 2877 1.1 chopps /* 2878 1.39 mjl * issue an "update params" 2879 1.1 chopps * 2880 1.39 mjl * expected to be called in sleepable context -- intended for user stuff 2881 1.1 chopps */ 2882 1.1 chopps static int 2883 1.72 dsl ray_user_update_params(struct ray_softc *sc, struct ray_param_req *pr) 2884 1.1 chopps { 2885 1.1 chopps int rv; 2886 1.1 chopps 2887 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { 2888 1.1 chopps pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; 2889 1.1 chopps return (EIO); 2890 1.1 chopps } 2891 1.1 chopps 2892 1.1 chopps /* wait to be able to issue the command */ 2893 1.1 chopps rv = 0; 2894 1.1 chopps while (ray_cmd_is_running(sc, SCP_UPD_UPDATEPARAMS) || 2895 1.1 chopps ray_cmd_is_scheduled(sc, SCP_UPD_UPDATEPARAMS)) { 2896 1.1 chopps rv = tsleep(ray_update_params, 0|PCATCH, "cmd in use", 0); 2897 1.1 chopps if (rv) 2898 1.1 chopps return (rv); 2899 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { 2900 1.1 chopps pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; 2901 1.1 chopps return (EIO); 2902 1.1 chopps } 2903 1.1 chopps } 2904 1.1 chopps 2905 1.1 chopps pr->r_failcause = RAY_FAILCAUSE_WAITING; 2906 1.1 chopps sc->sc_updreq = pr; 2907 1.1 chopps ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS); 2908 1.1 chopps ray_check_scheduled(sc); 2909 1.1 chopps 2910 1.1 chopps while (pr->r_failcause == RAY_FAILCAUSE_WAITING) 2911 1.1 chopps (void)tsleep(ray_update_params, 0, "waiting cmd", 0); 2912 1.1 chopps wakeup(ray_update_params); 2913 1.1 chopps 2914 1.1 chopps return (0); 2915 1.1 chopps } 2916 1.1 chopps 2917 1.1 chopps /* 2918 1.1 chopps * issue a report params 2919 1.1 chopps * 2920 1.44 wiz * expected to be called in sleepable context -- intended for user stuff 2921 1.1 chopps */ 2922 1.1 chopps static int 2923 1.72 dsl ray_user_report_params(struct ray_softc *sc, struct ray_param_req *pr) 2924 1.1 chopps { 2925 1.1 chopps int rv; 2926 1.1 chopps 2927 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { 2928 1.1 chopps pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; 2929 1.1 chopps return (EIO); 2930 1.1 chopps } 2931 1.56 perry 2932 1.1 chopps /* wait to be able to issue the command */ 2933 1.1 chopps rv = 0; 2934 1.1 chopps while (ray_cmd_is_running(sc, SCP_REPORTPARAMS) 2935 1.1 chopps || ray_cmd_is_scheduled(sc, SCP_REPORTPARAMS)) { 2936 1.1 chopps rv = tsleep(ray_report_params, 0|PCATCH, "cmd in use", 0); 2937 1.1 chopps if (rv) 2938 1.1 chopps return (rv); 2939 1.1 chopps if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { 2940 1.1 chopps pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; 2941 1.1 chopps return (EIO); 2942 1.1 chopps } 2943 1.1 chopps } 2944 1.1 chopps 2945 1.1 chopps pr->r_failcause = RAY_FAILCAUSE_WAITING; 2946 1.1 chopps sc->sc_repreq = pr; 2947 1.1 chopps ray_cmd_schedule(sc, SCP_REPORTPARAMS); 2948 1.1 chopps ray_check_scheduled(sc); 2949 1.1 chopps 2950 1.1 chopps while (pr->r_failcause == RAY_FAILCAUSE_WAITING) 2951 1.1 chopps (void)tsleep(ray_report_params, 0, "waiting cmd", 0); 2952 1.1 chopps wakeup(ray_report_params); 2953 1.1 chopps 2954 1.1 chopps return (0); 2955 1.1 chopps } 2956 1.1 chopps 2957 1.1 chopps 2958 1.1 chopps /* 2959 1.1 chopps * this is a temporary wrapper around bus_space_read_region_1 2960 1.1 chopps * as it seems to mess with gcc. the line numbers get offset 2961 1.1 chopps * presumably this is related to the inline asm on i386. 2962 1.1 chopps */ 2963 1.1 chopps 2964 1.1 chopps static void 2965 1.72 dsl ray_read_region(struct ray_softc *sc, bus_size_t off, void *vp, size_t c) 2966 1.1 chopps { 2967 1.10 chopps #ifdef RAY_USE_OPTIMIZED_COPY 2968 1.1 chopps u_int n2, n4, tmp; 2969 1.93 msaitoh uint8_t *p; 2970 1.1 chopps 2971 1.1 chopps p = vp; 2972 1.1 chopps 2973 1.1 chopps /* XXX we may be making poor assumptions here but lets hope */ 2974 1.1 chopps switch ((off|(bus_addr_t)p) & 0x03) { 2975 1.1 chopps case 0: 2976 1.1 chopps if ((n4 = c / 4)) { 2977 1.1 chopps bus_space_read_region_4(sc->sc_memt, sc->sc_memh, off, 2978 1.1 chopps p, n4); 2979 1.1 chopps tmp = c & ~0x3; 2980 1.1 chopps c &= 0x3; 2981 1.1 chopps p += tmp; 2982 1.1 chopps off += tmp; 2983 1.1 chopps } 2984 1.1 chopps switch (c) { 2985 1.1 chopps case 3: 2986 1.93 msaitoh *p = bus_space_read_1(sc->sc_memt, sc->sc_memh, off); 2987 1.1 chopps p++, off++; 2988 1.1 chopps case 2: 2989 1.93 msaitoh *p = bus_space_read_1(sc->sc_memt, sc->sc_memh, off); 2990 1.1 chopps p++, off++; 2991 1.1 chopps case 1: 2992 1.93 msaitoh *p = bus_space_read_1(sc->sc_memt, sc->sc_memh, off); 2993 1.1 chopps } 2994 1.1 chopps break; 2995 1.1 chopps case 2: 2996 1.1 chopps if ((n2 = (c >> 1))) 2997 1.1 chopps bus_space_read_region_2(sc->sc_memt, sc->sc_memh, off, 2998 1.1 chopps p, n2); 2999 1.1 chopps if (c & 1) { 3000 1.1 chopps c &= ~0x1; 3001 1.1 chopps *(p + c) = bus_space_read_1(sc->sc_memt, sc->sc_memh, 3002 1.1 chopps off + c); 3003 1.1 chopps } 3004 1.1 chopps break; 3005 1.1 chopps case 1: 3006 1.1 chopps case 3: 3007 1.1 chopps bus_space_read_region_1(sc->sc_memt, sc->sc_memh, off, p, c); 3008 1.1 chopps break; 3009 1.1 chopps } 3010 1.10 chopps #else 3011 1.10 chopps bus_space_read_region_1(sc->sc_memt, sc->sc_memh, off, vp, c); 3012 1.10 chopps #endif 3013 1.1 chopps } 3014 1.1 chopps 3015 1.1 chopps /* 3016 1.1 chopps * this is a temporary wrapper around bus_space_write_region_1 3017 1.1 chopps * as it seems to mess with gcc. the line numbers get offset 3018 1.1 chopps * presumably this is related to the inline asm on i386. 3019 1.1 chopps */ 3020 1.1 chopps static void 3021 1.72 dsl ray_write_region(struct ray_softc *sc, bus_size_t off, void *vp, size_t c) 3022 1.1 chopps { 3023 1.10 chopps #ifdef RAY_USE_OPTIMIZED_COPY 3024 1.1 chopps size_t n2, n4, tmp; 3025 1.93 msaitoh uint8_t *p; 3026 1.1 chopps 3027 1.1 chopps p = vp; 3028 1.1 chopps /* XXX we may be making poor assumptions here but lets hope */ 3029 1.1 chopps switch ((off|(bus_addr_t)p) & 0x03) { 3030 1.1 chopps case 0: 3031 1.1 chopps if ((n4 = (c >> 2))) { 3032 1.1 chopps bus_space_write_region_4(sc->sc_memt, sc->sc_memh, off, 3033 1.1 chopps p, n4); 3034 1.1 chopps tmp = c & ~0x3; 3035 1.1 chopps c &= 0x3; 3036 1.1 chopps p += tmp; 3037 1.1 chopps off += tmp; 3038 1.1 chopps } 3039 1.1 chopps switch (c) { 3040 1.1 chopps case 3: 3041 1.93 msaitoh bus_space_write_1(sc->sc_memt, sc->sc_memh, off, *p); 3042 1.1 chopps p++, off++; 3043 1.1 chopps case 2: 3044 1.93 msaitoh bus_space_write_1(sc->sc_memt, sc->sc_memh, off, *p); 3045 1.1 chopps p++, off++; 3046 1.1 chopps case 1: 3047 1.93 msaitoh bus_space_write_1(sc->sc_memt, sc->sc_memh, off, *p); 3048 1.1 chopps } 3049 1.1 chopps break; 3050 1.1 chopps case 2: 3051 1.1 chopps if ((n2 = (c >> 1))) 3052 1.1 chopps bus_space_write_region_2(sc->sc_memt, sc->sc_memh, off, 3053 1.1 chopps p, n2); 3054 1.1 chopps if (c & 0x1) { 3055 1.1 chopps c &= ~0x1; 3056 1.1 chopps bus_space_write_1(sc->sc_memt, sc->sc_memh, 3057 1.1 chopps off + c, *(p + c)); 3058 1.1 chopps } 3059 1.1 chopps break; 3060 1.1 chopps case 1: 3061 1.1 chopps case 3: 3062 1.1 chopps bus_space_write_region_1(sc->sc_memt, sc->sc_memh, off, p, c); 3063 1.1 chopps break; 3064 1.1 chopps } 3065 1.10 chopps #else 3066 1.10 chopps bus_space_write_region_1(sc->sc_memt, sc->sc_memh, off, vp, c); 3067 1.10 chopps #endif 3068 1.1 chopps } 3069 1.1 chopps 3070 1.1 chopps #ifdef RAY_DEBUG 3071 1.1 chopps 3072 1.1 chopps static void 3073 1.72 dsl ray_dump_mbuf(struct ray_softc *sc, struct mbuf *m) 3074 1.1 chopps { 3075 1.80 chs printf("%s: pkt dump:", device_xname(sc->sc_dev)); 3076 1.1 chopps for (; m; m = m->m_next) { 3077 1.88 christos hexdump(printf, NULL, mtod(m, void *), m->m_len); 3078 1.1 chopps } 3079 1.1 chopps } 3080 1.1 chopps #endif /* RAY_DEBUG */ 3081 1.14 augustss 3082 1.14 augustss #ifdef RAY_DO_SIGLEV 3083 1.14 augustss static void 3084 1.93 msaitoh ray_update_siglev(struct ray_softc *sc, uint8_t *src, uint8_t siglev) 3085 1.14 augustss { 3086 1.14 augustss int i, mini; 3087 1.14 augustss struct timeval mint; 3088 1.14 augustss struct ray_siglev *sl; 3089 1.14 augustss 3090 1.14 augustss /* try to find host */ 3091 1.14 augustss for (i = 0; i < RAY_NSIGLEVRECS; i++) { 3092 1.14 augustss sl = &sc->sc_siglevs[i]; 3093 1.14 augustss if (memcmp(sl->rsl_host, src, ETHER_ADDR_LEN) == 0) 3094 1.14 augustss goto found; 3095 1.14 augustss } 3096 1.14 augustss /* not found, find oldest slot */ 3097 1.14 augustss mini = 0; 3098 1.14 augustss mint.tv_sec = LONG_MAX; 3099 1.14 augustss mint.tv_usec = 0; 3100 1.14 augustss for (i = 0; i < RAY_NSIGLEVRECS; i++) { 3101 1.14 augustss sl = &sc->sc_siglevs[i]; 3102 1.14 augustss if (timercmp(&sl->rsl_time, &mint, <)) { 3103 1.14 augustss mini = i; 3104 1.14 augustss mint = sl->rsl_time; 3105 1.14 augustss } 3106 1.14 augustss } 3107 1.14 augustss sl = &sc->sc_siglevs[mini]; 3108 1.14 augustss memset(sl->rsl_siglevs, 0, RAY_NSIGLEV); 3109 1.14 augustss memcpy(sl->rsl_host, src, ETHER_ADDR_LEN); 3110 1.14 augustss 3111 1.14 augustss found: 3112 1.14 augustss microtime(&sl->rsl_time); 3113 1.14 augustss memmove(&sl->rsl_siglevs[1], sl->rsl_siglevs, RAY_NSIGLEV-1); 3114 1.14 augustss sl->rsl_siglevs[0] = siglev; 3115 1.14 augustss } 3116 1.14 augustss #endif 3117