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