[BACK]Return to if_ray.c CVS log [TXT][DIR] Up to [local] / sys / dev / pcmcia

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