diff options
author | dmlb <dmlb@FreeBSD.org> | 2000-04-22 14:22:51 +0000 |
---|---|---|
committer | dmlb <dmlb@FreeBSD.org> | 2000-04-22 14:22:51 +0000 |
commit | f1c4eef72a44b9c1e7d7b3f59a80e2dad0c5c34b (patch) | |
tree | 502e6f7eb311fa8201758cc546ed3ed69687f592 /sys/dev/ray | |
parent | 2f2ffe8fce8513399c5454bab832871742416b4b (diff) | |
download | FreeBSD-src-f1c4eef72a44b9c1e7d7b3f59a80e2dad0c5c34b.zip FreeBSD-src-f1c4eef72a44b9c1e7d7b3f59a80e2dad0c5c34b.tar.gz |
Moved functions around so that they are grouped a little more sensibly.
Diffstat (limited to 'sys/dev/ray')
-rw-r--r-- | sys/dev/ray/if_ray.c | 2028 |
1 files changed, 1016 insertions, 1012 deletions
diff --git a/sys/dev/ray/if_ray.c b/sys/dev/ray/if_ray.c index fe3687e..57694324 100644 --- a/sys/dev/ray/if_ray.c +++ b/sys/dev/ray/if_ray.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ray.c,v 1.17 2000/04/04 06:43:30 dmlb Exp $ + * $Id: if_ray.c,v 1.20 2000/04/21 15:01:49 dmlb Exp $ * */ @@ -1033,6 +1033,141 @@ ray_attach(dev_p) } /* + * Network ioctl request. + */ +static int +ray_ioctl(register struct ifnet *ifp, u_long command, caddr_t data) +{ + struct ray_softc *sc; + struct ray_param_req pr; + struct ray_stats_req sr; + struct ifreq *ifr; + int s, error, error2; + + sc = ifp->if_softc; + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_IOCTL, ""); + RAY_MAP_CM(sc); + + if (sc->gone) { + printf("ray%d: ray_ioctl unloaded!\n", sc->unit); + ifp->if_flags &= ~IFF_RUNNING; + return (ENXIO); + } + + ifr = (struct ifreq *)data; + error = 0; + error2 = 0; + + s = splimp(); + + switch (command) { + + case SIOCSIFADDR: + case SIOCGIFADDR: + case SIOCSIFMTU: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SIFADDR/GIFADDR/SIFMTU"); + error = ether_ioctl(ifp, command, data); + break; + + case SIOCSIFFLAGS: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SIFFLAGS"); + /* + * If the interface is marked up and stopped, then start + * it. If it is marked down and running, then stop it. + */ + if (ifp->if_flags & IFF_UP) { + if (!(ifp->if_flags & IFF_RUNNING)) + ray_init(sc); + else + ray_promisc_user(sc); + } else { + if (ifp->if_flags & IFF_RUNNING) + ray_stop(sc); + } + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "ADDMULTI/DELMULTI"); + error = ray_mcast_user(sc); + break; + + case SIOCSRAYPARAM: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SRAYPARAM"); + if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr)))) + break; + error = ray_user_update_params(sc, &pr); + error2 = copyout(&pr, ifr->ifr_data, sizeof(pr)); + error = error2 ? error2 : error; + break; + + case SIOCGRAYPARAM: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYPARAM"); + if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr)))) + break; + error = ray_user_report_params(sc, &pr); + error2 = copyout(&pr, ifr->ifr_data, sizeof(pr)); + error = error2 ? error2 : error; + break; + + case SIOCGRAYSTATS: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYSTATS"); + error = ray_user_report_stats(sc, &sr); + error2 = copyout(&sr, ifr->ifr_data, sizeof(sr)); + error = error2 ? error2 : error; + break; + + case SIOCGRAYSIGLEV: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYSIGLEV"); + error = copyout(sc->sc_siglevs, ifr->ifr_data, + sizeof(sc->sc_siglevs)); + break; + + case SIOCGIFFLAGS: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFFLAGS"); + error = EINVAL; + break; + + case SIOCGIFMETRIC: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMETRIC"); + error = EINVAL; + break; + + case SIOCGIFMTU: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMTU"); + error = EINVAL; + break; + + case SIOCGIFPHYS: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFPYHS"); + error = EINVAL; + break; + + case SIOCSIFMEDIA: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SIFMEDIA"); + error = EINVAL; + break; + + case SIOCGIFMEDIA: + RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMEDIA"); + error = EINVAL; + break; + + default: + error = EINVAL; + + } + + splx(s); + + return (error); +} + + + + +/* * User land entry to network initialisation. * *XXX change all this - it's wrong @@ -1193,6 +1328,317 @@ ray_init(xsc) } /* + * Download start up structures to card. + */ +static void +ray_download(struct ray_softc *sc, struct ray_comq_entry *com) +{ + struct ray_mib_4 ray_mib_4_default; + struct ray_mib_5 ray_mib_5_default; + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); + RAY_MAP_CM(sc); + +#define MIB4(m) ray_mib_4_default.##m +#define MIB5(m) ray_mib_5_default.##m +#define PUT2(p, v) \ + do { (p)[0] = ((v >> 8) & 0xff); (p)[1] = (v & 0xff); } while(0) + + /* + * Firmware version 4 defaults - see if_raymib.h for details + */ + MIB4(mib_net_type) = sc->sc_d.np_net_type; + MIB4(mib_ap_status) = sc->sc_d.np_ap_status; + bcopy(sc->sc_d.np_ssid, MIB4(mib_ssid), IEEE80211_NWID_LEN); + MIB4(mib_scan_mode) = RAY_MIB_SCAN_MODE_DEFAULT; + MIB4(mib_apm_mode) = RAY_MIB_APM_MODE_DEFAULT; + bcopy(sc->sc_station_addr, MIB4(mib_mac_addr), ETHER_ADDR_LEN); + PUT2(MIB4(mib_frag_thresh), RAY_MIB_FRAG_THRESH_DEFAULT); + PUT2(MIB4(mib_dwell_time), RAY_MIB_DWELL_TIME_V4); + PUT2(MIB4(mib_beacon_period), RAY_MIB_BEACON_PERIOD_V4); + MIB4(mib_dtim_interval) = RAY_MIB_DTIM_INTERVAL_DEFAULT; + MIB4(mib_max_retry) = RAY_MIB_MAX_RETRY_DEFAULT; + MIB4(mib_ack_timo) = RAY_MIB_ACK_TIMO_DEFAULT; + MIB4(mib_sifs) = RAY_MIB_SIFS_DEFAULT; + MIB4(mib_difs) = RAY_MIB_DIFS_DEFAULT; + MIB4(mib_pifs) = RAY_MIB_PIFS_V4; + PUT2(MIB4(mib_rts_thresh), RAY_MIB_RTS_THRESH_DEFAULT); + PUT2(MIB4(mib_scan_dwell), RAY_MIB_SCAN_DWELL_V4); + PUT2(MIB4(mib_scan_max_dwell), RAY_MIB_SCAN_MAX_DWELL_V4); + MIB4(mib_assoc_timo) = RAY_MIB_ASSOC_TIMO_DEFAULT; + MIB4(mib_adhoc_scan_cycle) = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT; + MIB4(mib_infra_scan_cycle) = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT; + MIB4(mib_infra_super_scan_cycle) + = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT; + MIB4(mib_promisc) = RAY_MIB_PROMISC_DEFAULT; + PUT2(MIB4(mib_uniq_word), RAY_MIB_UNIQ_WORD_DEFAULT); + MIB4(mib_slot_time) = RAY_MIB_SLOT_TIME_V4; + MIB4(mib_roam_low_snr_thresh) = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT; + MIB4(mib_low_snr_count) = RAY_MIB_LOW_SNR_COUNT_DEFAULT; + MIB4(mib_infra_missed_beacon_count) + = RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT; + MIB4(mib_adhoc_missed_beacon_count) + = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT; + MIB4(mib_country_code) = RAY_MIB_COUNTRY_CODE_DEFAULT; + MIB4(mib_hop_seq) = RAY_MIB_HOP_SEQ_DEFAULT; + MIB4(mib_hop_seq_len) = RAY_MIB_HOP_SEQ_LEN_V4; + MIB4(mib_cw_max) = RAY_MIB_CW_MAX_V4; + MIB4(mib_cw_min) = RAY_MIB_CW_MIN_V4; + MIB4(mib_noise_filter_gain) = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT; + MIB4(mib_noise_limit_offset) = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT; + MIB4(mib_rssi_thresh_offset) = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT; + MIB4(mib_busy_thresh_offset) = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT; + MIB4(mib_sync_thresh) = RAY_MIB_SYNC_THRESH_DEFAULT; + MIB4(mib_test_mode) = RAY_MIB_TEST_MODE_DEFAULT; + MIB4(mib_test_min_chan) = RAY_MIB_TEST_MIN_CHAN_DEFAULT; + MIB4(mib_test_max_chan) = RAY_MIB_TEST_MAX_CHAN_DEFAULT; + + /* + * Firmware version 5 defaults - see if_raymib.h for details + */ + MIB5(mib_net_type) = sc->sc_d.np_net_type; + MIB4(mib_ap_status) = sc->sc_d.np_ap_status; + bcopy(sc->sc_d.np_ssid, MIB5(mib_ssid), IEEE80211_NWID_LEN); + MIB5(mib_scan_mode) = RAY_MIB_SCAN_MODE_DEFAULT; + MIB5(mib_apm_mode) = RAY_MIB_APM_MODE_DEFAULT; + bcopy(sc->sc_station_addr, MIB5(mib_mac_addr), ETHER_ADDR_LEN); + PUT2(MIB5(mib_frag_thresh), RAY_MIB_FRAG_THRESH_DEFAULT); + PUT2(MIB5(mib_dwell_time), RAY_MIB_DWELL_TIME_V5); + PUT2(MIB5(mib_beacon_period), RAY_MIB_BEACON_PERIOD_V5); + MIB5(mib_dtim_interval) = RAY_MIB_DTIM_INTERVAL_DEFAULT; + MIB5(mib_max_retry) = RAY_MIB_MAX_RETRY_DEFAULT; + MIB5(mib_ack_timo) = RAY_MIB_ACK_TIMO_DEFAULT; + MIB5(mib_sifs) = RAY_MIB_SIFS_DEFAULT; + MIB5(mib_difs) = RAY_MIB_DIFS_DEFAULT; + MIB5(mib_pifs) = RAY_MIB_PIFS_V5; + PUT2(MIB5(mib_rts_thresh), RAY_MIB_RTS_THRESH_DEFAULT); + PUT2(MIB5(mib_scan_dwell), RAY_MIB_SCAN_DWELL_V5); + PUT2(MIB5(mib_scan_max_dwell), RAY_MIB_SCAN_MAX_DWELL_V5); + MIB5(mib_assoc_timo) = RAY_MIB_ASSOC_TIMO_DEFAULT; + MIB5(mib_adhoc_scan_cycle) = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT; + MIB5(mib_infra_scan_cycle) = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT; + MIB5(mib_infra_super_scan_cycle) + = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT; + MIB5(mib_promisc) = RAY_MIB_PROMISC_DEFAULT; + PUT2(MIB5(mib_uniq_word), RAY_MIB_UNIQ_WORD_DEFAULT); + MIB5(mib_slot_time) = RAY_MIB_SLOT_TIME_V5; + MIB5(mib_roam_low_snr_thresh) = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT; + MIB5(mib_low_snr_count) = RAY_MIB_LOW_SNR_COUNT_DEFAULT; + MIB5(mib_infra_missed_beacon_count) + = RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT; + MIB5(mib_adhoc_missed_beacon_count) + = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT; + MIB5(mib_country_code) = RAY_MIB_COUNTRY_CODE_DEFAULT; + MIB5(mib_hop_seq) = RAY_MIB_HOP_SEQ_DEFAULT; + MIB5(mib_hop_seq_len) = RAY_MIB_HOP_SEQ_LEN_V5; + PUT2(MIB5(mib_cw_max), RAY_MIB_CW_MAX_V5); + PUT2(MIB5(mib_cw_min), RAY_MIB_CW_MIN_V5); + MIB5(mib_noise_filter_gain) = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT; + MIB5(mib_noise_limit_offset) = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT; + MIB5(mib_rssi_thresh_offset) = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT; + MIB5(mib_busy_thresh_offset) = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT; + MIB5(mib_sync_thresh) = RAY_MIB_SYNC_THRESH_DEFAULT; + MIB5(mib_test_mode) = RAY_MIB_TEST_MODE_DEFAULT; + MIB5(mib_test_min_chan) = RAY_MIB_TEST_MIN_CHAN_DEFAULT; + MIB5(mib_test_max_chan) = RAY_MIB_TEST_MAX_CHAN_DEFAULT; + MIB5(mib_allow_probe_resp) = RAY_MIB_ALLOW_PROBE_RESP_DEFAULT; + MIB5(mib_privacy_must_start) = sc->sc_d.np_priv_start; + MIB5(mib_privacy_can_join) = sc->sc_d.np_priv_join; + MIB5(mib_basic_rate_set[0]) = sc->sc_d.np_def_txrate; + + if (sc->sc_version == RAY_ECFS_BUILD_4) + ray_write_region(sc, RAY_HOST_TO_ECF_BASE, + &ray_mib_4_default, sizeof(ray_mib_4_default)); + else + ray_write_region(sc, RAY_HOST_TO_ECF_BASE, + &ray_mib_5_default, sizeof(ray_mib_5_default)); + + (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_DOWNLOAD_PARAMS, 0); + ray_com_ecf(sc, com); +} + +/* + * Download completion routine. + */ +static void +ray_download_done(struct ray_softc *sc, size_t ccs) +{ + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); + RAY_DCOM_CHECK(sc, ccs); + + /* + * Fake the current network parameter settings so start_join_net + * will not bother updating them to the card (we would need to + * zero these anyway, so we might as well copy). + */ + sc->sc_c.np_net_type = sc->sc_d.np_net_type; + bcopy(sc->sc_d.np_ssid, sc->sc_c.np_ssid, IEEE80211_NWID_LEN); + + ray_com_ecf_done(sc); +} + +/* + * Start or join a network + */ +static void +ray_sj(struct ray_softc *sc, struct ray_comq_entry *com) +{ + struct ray_net_params np; + struct ifnet *ifp; + int update; + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); + RAY_MAP_CM(sc); + + /* XXX do I need this anymore? how can IFF_RUNNING be cleared + * XXX before this routine exits - check in ray_ioctl and the + * network code itself. + */ + ifp = &sc->arpcom.ac_if; + if ((ifp->if_flags & IFF_RUNNING) == 0) { + RAY_PANIC(sc, "IFF_RUNNING == 0"); + } + + sc->sc_havenet = 0; + if (sc->sc_d.np_net_type == RAY_MIB_NET_TYPE_ADHOC) + (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_START_NET, 0); + else + (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_JOIN_NET, 0); + + update = 0; + if (bcmp(sc->sc_c.np_ssid, sc->sc_d.np_ssid, IEEE80211_NWID_LEN)) + update++; + if (sc->sc_c.np_net_type != sc->sc_d.np_net_type) + update++; + RAY_DPRINTF(sc, RAY_DBG_STARTJOIN, + "%s updating nw params", update?"is":"not"); + if (update) { + bzero(&np, sizeof(np)); + np.p_net_type = sc->sc_d.np_net_type; + bcopy(sc->sc_d.np_ssid, np.p_ssid, IEEE80211_NWID_LEN); + np.p_privacy_must_start = sc->sc_d.np_priv_start; + np.p_privacy_can_join = sc->sc_d.np_priv_join; + + ray_write_region(sc, RAY_HOST_TO_ECF_BASE, &np, sizeof(np)); + SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_net, c_upd_param, 1); + } else + SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_net, c_upd_param, 0); + + ray_com_ecf(sc, com); +} + +/* + * Complete start command or intermediate step in join command + */ +static void +ray_sj_done(struct ray_softc *sc, size_t ccs) +{ + struct ifnet *ifp; + u_int8_t o_net_type; + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); + RAY_DCOM_CHECK(sc, ccs); + RAY_MAP_CM(sc); + + /* + * Read back any network parameters the ECF changed + */ + ray_read_region(sc, ccs, &sc->sc_c.p_1, sizeof(struct ray_cmd_net)); + + /* adjust values for buggy build 4 */ + if (sc->sc_c.np_def_txrate == 0x55) + sc->sc_c.np_def_txrate = sc->sc_d.np_def_txrate; + if (sc->sc_c.np_encrypt == 0x55) + sc->sc_c.np_encrypt = sc->sc_d.np_encrypt; + + /* card is telling us to update the network parameters */ + if (sc->sc_c.np_upd_param) { + RAY_DPRINTF(sc, RAY_DBG_STARTJOIN, "card updating parameters"); + o_net_type = sc->sc_c.np_net_type; /* XXX this may be wrong? */ + ray_read_region(sc, RAY_HOST_TO_ECF_BASE, + &sc->sc_c.p_2, sizeof(struct ray_net_params)); + if (sc->sc_c.np_net_type != o_net_type) { + RAY_PANIC(sc, "card changing network type"); +#if XXX + restart ray_start_join sequence + may need to split download_done for this +#endif + } + } + RAY_DNET_DUMP(sc, " after start/join network completed."); + + /* + * Hurrah! The network is now active. + * + * Clearing IFF_OACTIVE will ensure that the system will queue + * packets. Just before we return from the interrupt context + * we check to see if packets have been queued. + */ + ifp = &sc->arpcom.ac_if; +#if XXX_ASSOCWORKING_AGAIN + if (SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd) == RAY_CMD_JOIN_NET) + ray_start_assoc(sc); + else { + sc->sc_havenet = 1; + ifp->if_flags &= ~IFF_OACTIVE; + } +#else + sc->sc_havenet = 1; + ifp->if_flags &= ~IFF_OACTIVE; +#endif XXX_ASSOCWORKING_AGAIN + + ray_com_ecf_done(sc); +} + +#if XXX_ASSOCWORKING_AGAIN +/*XXX move this further down the code */ +/* + * Start an association with an access point + */ +static void +ray_start_assoc(struct ray_softc *sc) +{ + struct ifnet *ifp; + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); + RAY_MAP_CM(sc); + + ifp = &sc->arpcom.ac_if; + + if ((ifp->if_flags & IFF_RUNNING) == 0) + return; + + (void)ray_cmd_simple(sc, RAY_CMD_START_ASSOC, SCP_STARTASSOC); +} + +/* + * Complete association + */ +static void +ray_start_assoc_done(struct ray_softc *sc, size_t ccs) +{ + struct ifnet *ifp; + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); + RAY_MAP_CM(sc); + RAY_DCOM_CHECK(sc, ccs); + + /* + * Hurrah! The network is now active. + * + * Clearing IFF_OACTIVE will ensure that the system will queue + * packets. Just before we return from the interrupt context + * we check to see if packets have been queued. + */ + ifp = &sc->arpcom.ac_if; + sc->sc_havenet = 1; + ifp->if_flags &= ~IFF_OACTIVE; + + ray_com_ecf_done(sc); +} +#endif XXX_ASSOCWORKING_AGAIN + +/* * Network stop. * * Assumes that a ray_init is used to restart the card. @@ -1361,138 +1807,6 @@ ray_watchdog(ifp) ******************************************************************************/ /* - * Network ioctl request. - */ -static int -ray_ioctl(register struct ifnet *ifp, u_long command, caddr_t data) -{ - struct ray_softc *sc; - struct ray_param_req pr; - struct ray_stats_req sr; - struct ifreq *ifr; - int s, error, error2; - - sc = ifp->if_softc; - - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_IOCTL, ""); - RAY_MAP_CM(sc); - - if (sc->gone) { - printf("ray%d: ray_ioctl unloaded!\n", sc->unit); - ifp->if_flags &= ~IFF_RUNNING; - return (ENXIO); - } - - ifr = (struct ifreq *)data; - error = 0; - error2 = 0; - - s = splimp(); - - switch (command) { - - case SIOCSIFADDR: - case SIOCGIFADDR: - case SIOCSIFMTU: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SIFADDR/GIFADDR/SIFMTU"); - error = ether_ioctl(ifp, command, data); - break; - - case SIOCSIFFLAGS: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SIFFLAGS"); - /* - * If the interface is marked up and stopped, then start - * it. If it is marked down and running, then stop it. - */ - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_flags & IFF_RUNNING)) - ray_init(sc); - else - ray_promisc_user(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) - ray_stop(sc); - } - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "ADDMULTI/DELMULTI"); - error = ray_mcast_user(sc); - break; - - case SIOCSRAYPARAM: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SRAYPARAM"); - if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr)))) - break; - error = ray_user_update_params(sc, &pr); - error2 = copyout(&pr, ifr->ifr_data, sizeof(pr)); - error = error2 ? error2 : error; - break; - - case SIOCGRAYPARAM: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYPARAM"); - if ((error = copyin(ifr->ifr_data, &pr, sizeof(pr)))) - break; - error = ray_user_report_params(sc, &pr); - error2 = copyout(&pr, ifr->ifr_data, sizeof(pr)); - error = error2 ? error2 : error; - break; - - case SIOCGRAYSTATS: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYSTATS"); - error = ray_user_report_stats(sc, &sr); - error2 = copyout(&sr, ifr->ifr_data, sizeof(sr)); - error = error2 ? error2 : error; - break; - - case SIOCGRAYSIGLEV: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GRAYSIGLEV"); - error = copyout(sc->sc_siglevs, ifr->ifr_data, - sizeof(sc->sc_siglevs)); - break; - - case SIOCGIFFLAGS: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFFLAGS"); - error = EINVAL; - break; - - case SIOCGIFMETRIC: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMETRIC"); - error = EINVAL; - break; - - case SIOCGIFMTU: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMTU"); - error = EINVAL; - break; - - case SIOCGIFPHYS: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFPYHS"); - error = EINVAL; - break; - - case SIOCSIFMEDIA: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "SIFMEDIA"); - error = EINVAL; - break; - - case SIOCGIFMEDIA: - RAY_DPRINTF(sc, RAY_DBG_IOCTL, "GIFMEDIA"); - error = EINVAL; - break; - - default: - error = EINVAL; - - } - - splx(s); - - return (error); -} - -/* * Transmit packet handling */ @@ -2496,74 +2810,561 @@ ray_rcs_intr(struct ray_softc *sc, size_t rcs) } /* - * CCS allocator for commands + * Functions based on CCS commands */ /* - * Obtain a ccs and fill easy bits in + * User land entry to multicast list changes + */ +static int +ray_mcast_user(struct ray_softc *sc) +{ + struct ifnet *ifp; + struct ray_comq_entry *com[2]; + int error, count; + + RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); + + ifp = &sc->arpcom.ac_if; + + /* + * The multicast list is only 16 items long so use promiscuous + * mode if needed. + * + * We track this stuff even when not running. + */ + for (ifma = ifp->if_multiaddrs.lh_first, count = 0; ifma != NULL; + ifma = ifma->ifma_link.le_next, count++) + if (count > 16) + ifp->if_flags |= IFF_ALLMULTI; + else if (ifp->if_flags & IFF_ALLMULTI) + ifp->if_flags &= ~IFF_ALLMULTI; + + if ((ifp->if_flags & IFF_RUNNING) == 0) { + return (0); + } + + /* + * If we need to change the promiscuous mode then do so. + */ + if (sc->promisc != !!(ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))) { + MALLOC(com[0], struct ray_comq_entry *, + sizeof(struct ray_comq_entry), M_RAYCOM, M_WAITOK); + com[0]->c_function = ray_promisc; + com[0]->c_flags = RAY_COM_FWOK; + com[0]->c_retval = 0; + com[0]->c_ccs = NULL; + com[0]->c_wakeup = com[1]; +#if RAY_DEBUG > 0 + com[0]->c_mesg = "ray_promisc"; +#endif /* RAY_DEBUG > 0 */ + ray_com_runq_add(sc, com[0]); + } else + com[0] = NULL; + + /* + * If we need to set the mcast list then do so. + */ + if (!(ifp->if_flags & IFF_ALLMULTI)) + MALLOC(com[1], struct ray_comq_entry *, + sizeof(struct ray_comq_entry), M_RAYCOM, M_WAITOK); + com[1]->c_function = ray_mcast; + com[0]->c_flags &= ~RAY_COM_FWOK; + com[1]->c_flags = RAY_COM_FWOK; + com[1]->c_retval = 0; + com[1]->c_ccs = NULL; + com[1]->c_wakeup = com[1]; +#if RAY_DEBUG > 0 + com[1]->c_mesg = "ray_mcast"; +#endif /* RAY_DEBUG > 0 */ + ray_com_runq_add(sc, com[1]); + } else + com[1] = NULL; + + ray_com_runq(sc); + RAY_DPRINTF(sc, RAY_DBG_COM, "sleeping"); + (void)tsleep(com[1], 0, "raymcast", 0); + RAY_DPRINTF(sc, RAY_DBG_COM, "awakened"); + + error = com->c_retval; + if (com[0] != NULL) + FREE(com[0], M_RAYCOM); + if (com[1] != NULL) + FREE(com[1], M_RAYCOM); + return (error); +} + +/* + * Set the multicast filter list + */ +static void +ray_mcast(struct ray_softc *sc, struct ray_comq_entry *com) +{ + struct ifnet *ifp; + struct ifmultiaddr *ifma; + size_t bufp; + + RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); + RAY_MAP_CM(sc); + + ifp = &sc->arpcom.ac_if; + + (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_UPDATE_MCAST, 0); + SRAM_WRITE_FIELD_1(sc, &com->c_ccs, + ray_cmd_update_mcast, c_nmcast, count); + bufp = RAY_HOST_TO_ECF_BASE; + for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; + ifma = ifma->ifma_link.le_next) { + ray_write_region( + sc, + bufp, + LLADDR((struct sockaddr_dl *)ifma->ifma_addr), + ETHER_ADDR_LEN + ); + bufp += ETHER_ADDR_LEN; + } + + ray_com_ecf(sc, com); +} + +/* + * Complete the multicast filter list update + */ +static void +ray_mcast_done(struct ray_softc *sc, size_t ccs) +{ + RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); + RAY_DCOM_CHECK(sc, ccs); + + ray_com_ecf_done(sc); +} + +#if 0 +/* + * User land entry to promiscuous mode changes + */ +static int +ray_promisc_user(struct ray_softc *sc) +{ + struct ifnet *ifp; + struct ray_comq_entry *com; + int error; + + RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); + + if ((ifp->if_flags & IFF_RUNNING) == 0) + return (0); + if (sc->promisc != !!(ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))) + return (0); + + MALLOC(com, struct ray_comq_entry *, sizeof(struct ray_comq_entry), + M_RAYCOM, M_WAITOK); + com->c_function = ray_promisc; + com->c_flags = RAY_COM_FWOK; + com->c_retval = 0; + com->c_ccs = NULL; + com->c_wakeup = com; +#if RAY_DEBUG > 0 + com->c_mesg = "ray_promisc"; +#endif /* RAY_DEBUG > 0 */ + ray_com_runq_add(sc, com); + + ray_com_runq(sc); + RAY_DPRINTF(sc, RAY_DBG_COM, "sleeping"); + (void)tsleep(com[3], 0, "raypromisc", 0); + RAY_DPRINTF(sc, RAY_DBG_COM, "awakened"); + + error = com->c_retval; + FREE(com, M_RAYCOM); + return (error); +} + +/* + * Set/reset promiscuous mode + */ +static void +ray_promisc(struct ray_softc *sc, struct ray_comq_entry *com) +{ + struct ifnet *ifp; + + RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); + RAY_MAP_CM(sc); + + ifp = &sc->arpcom.ac_if; + + (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_UPDATE_PARAMS, 0); + SRAM_WRITE_FIELD_1(sc, &com->c_ccs, + ray_cmd_update, c_paramid, RAY_MIB_PROMISC); + SRAM_WRITE_FIELD_1(sc, &com->c_ccs, ray_cmd_update, c_nparam, 1); + SRAM_WRITE_1(sc, RAY_HOST_TO_ECF_BASE, + !!(ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))); + + ray_com_ecf(sc, com); +} + +/* + * Complete the promiscuous mode update + */ +static void +ray_promisc_done(struct ray_softc *sc, size_t ccs) +{ + RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); + RAY_DCOM_CHECK(sc, ccs); + + ray_com_ecf_done(sc); +} + +/* + * issue a report params * - * Returns 1 and in `ccsp' the bus offset of the free ccs. Will block - * awaiting free ccs if needed, timo is passed to tsleep and will - * return 0 if the timeout expired. + * expected to be called in sleapable context -- intended for user stuff */ static int -ray_ccs_alloc(struct ray_softc *sc, size_t *ccsp, u_int cmd, int timo) +ray_user_report_params(struct ray_softc *sc, struct ray_param_req *pr) { - size_t ccs; - u_int i; + struct ifnet *ifp; + int mib_sizes[] = RAY_MIB_SIZES; + int rv; - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CCS, ""); + RAY_DPRINTFN(RAY_DBG_SUBR, + ("ray%d: ray_user_report_params\n", sc->unit)); RAY_MAP_CM(sc); - for (;;) { - for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) { - /* we probe here to make the card go */ - (void)SRAM_READ_FIELD_1(sc, RAY_CCS_ADDRESS(i), ray_cmd, - c_status); - if (!sc->sc_ccsinuse[i]) - break; - } - if (i > RAY_CCS_CMD_LAST) { - RAY_PANIC(sc, "out of CCS's"); - } else + ifp = &sc->arpcom.ac_if; + + if ((ifp->if_flags & IFF_RUNNING) == 0) { + pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; + return (EIO); + } + + /* test for illegal values or immediate responses */ + if (pr->r_paramid > RAY_MIB_LASTUSER) { + switch (pr->r_paramid) { + + case RAY_MIB_VERSION: + if (sc->sc_version == RAY_ECFS_BUILD_4) + *pr->r_data = 4; + else + *pr->r_data = 5; break; + + case RAY_MIB_CUR_BSSID: + bcopy(sc->sc_c.np_bss_id, pr->r_data, ETHER_ADDR_LEN); + break; + case RAY_MIB_CUR_INITED: + *pr->r_data = sc->sc_c.np_inited; + break; + case RAY_MIB_CUR_DEF_TXRATE: + *pr->r_data = sc->sc_c.np_def_txrate; + break; + case RAY_MIB_CUR_ENCRYPT: + *pr->r_data = sc->sc_c.np_encrypt; + break; + case RAY_MIB_CUR_NET_TYPE: + *pr->r_data = sc->sc_c.np_net_type; + break; + case RAY_MIB_CUR_SSID: + bcopy(sc->sc_c.np_ssid, pr->r_data, IEEE80211_NWID_LEN); + break; + case RAY_MIB_CUR_PRIV_START: + *pr->r_data = sc->sc_c.np_priv_start; + break; + case RAY_MIB_CUR_PRIV_JOIN: + *pr->r_data = sc->sc_c.np_priv_join; + break; + + case RAY_MIB_DES_BSSID: + bcopy(sc->sc_d.np_bss_id, pr->r_data, ETHER_ADDR_LEN); + break; + case RAY_MIB_DES_INITED: + *pr->r_data = sc->sc_d.np_inited; + break; + case RAY_MIB_DES_DEF_TXRATE: + *pr->r_data = sc->sc_d.np_def_txrate; + break; + case RAY_MIB_DES_ENCRYPT: + *pr->r_data = sc->sc_d.np_encrypt; + break; + case RAY_MIB_DES_NET_TYPE: + *pr->r_data = sc->sc_d.np_net_type; + break; + case RAY_MIB_DES_SSID: + bcopy(sc->sc_d.np_ssid, pr->r_data, IEEE80211_NWID_LEN); + break; + case RAY_MIB_DES_PRIV_START: + *pr->r_data = sc->sc_d.np_priv_start; + break; + case RAY_MIB_DES_PRIV_JOIN: + *pr->r_data = sc->sc_d.np_priv_join; + break; + + default: + return (EINVAL); + break; + } + pr->r_failcause = 0; + pr->r_len = mib_sizes[pr->r_paramid]; + return (0); } - sc->sc_ccsinuse[i] = 1; - ccs = RAY_CCS_ADDRESS(i); - RAY_DPRINTF(sc, RAY_DBG_CCS, "allocated 0x%02x", i); - SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_BUSY); - SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_cmd, cmd); - SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_link, RAY_CCS_LINK_NULL); + /* wait to be able to issue the command */ + rv = 0; + while (ray_cmd_is_running(sc, SCP_REPORTPARAMS) + || ray_cmd_is_scheduled(sc, SCP_REPORTPARAMS)) { + rv = tsleep(ray_report_params, 0|PCATCH, "cmd in use", 0); + if (rv) + return (rv); + if ((ifp->if_flags & IFF_RUNNING) == 0) { + pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; + return (EIO); + } + } - *ccsp = ccs; - return (1); + pr->r_failcause = RAY_FAILCAUSE_WAITING; + sc->sc_repreq = pr; + ray_cmd_schedule(sc, SCP_REPORTPARAMS); + ray_cmd_check_scheduled(sc); + + while (pr->r_failcause == RAY_FAILCAUSE_WAITING) + (void)tsleep(ray_report_params, 0, "waiting cmd", 0); + wakeup(ray_report_params); + + return (0); } /* - * Free up a ccs allocated via ray_ccs_alloc + * report a parameter + */ +static void +ray_report_params(struct ray_softc *sc) +{ + struct ifnet *ifp; + size_t ccs; + + RAY_DPRINTFN(RAY_DBG_SUBR, ("ray%d: ray_report_params\n", sc->unit)); + RAY_MAP_CM(sc); + + ifp = &sc->arpcom.ac_if; + + if (!sc->sc_repreq) + return; + + /* do the issue check before equality check */ + if ((ifp->if_flags & IFF_RUNNING) == 0) + return; + else if (!ray_ccs_alloc(sc, &ccs, RAY_CMD_REPORT_PARAMS, 0)) + return; + + SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_paramid, + sc->sc_repreq->r_paramid); + SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_nparam, 1); + +} + +/* + * Return the error counters + */ +static int +ray_user_report_stats(struct ray_softc *sc, struct ray_stats_req *sr) +{ + struct ifnet *ifp; + + RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); + + ifp = &sc->arpcom.ac_if; + if ((ifp->if_flags & IFF_RUNNING) == 0) { + return (EIO); + } + + sr->rxoverflow = sc->sc_rxoverflow; + sr->rxcksum = sc->sc_rxcksum; + sr->rxhcksum = sc->sc_rxhcksum; + sr->rxnoise = sc->sc_rxnoise; + + return (0); +} + +/* + * issue a update params * - * Return the old status. This routine is only used for ccs allocated via - * ray_ccs_alloc (not tx, rx or ECF command requests). + * expected to be called in sleepable context -- intended for user stuff */ -static u_int8_t -ray_ccs_free(struct ray_softc *sc, size_t ccs) +static int +ray_user_update_params(struct ray_softc *sc, struct ray_param_req *pr) { - u_int8_t status; + struct ifnet *ifp; + int rv; - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CCS, ""); + RAY_DPRINTFN(RAY_DBG_SUBR, + ("ray%d: ray_user_update_params\n", sc->unit)); RAY_MAP_CM(sc); - status = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status); - RAY_CCS_FREE(sc, ccs); - sc->sc_ccsinuse[RAY_CCS_INDEX(ccs)] = 0; - wakeup(ray_ccs_alloc); - RAY_DPRINTF(sc, RAY_DBG_CCS, "freed 0x%02x", RAY_CCS_INDEX(ccs)); + ifp = &sc->arpcom.ac_if; - return (status); + if ((ifp->if_flags & IFF_RUNNING) == 0) { + pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; + return (EIO); + } + + if (pr->r_paramid > RAY_MIB_MAX) { + return (EINVAL); + } + + /* + * Handle certain parameters specially + */ + switch (pr->r_paramid) { + case RAY_MIB_NET_TYPE: + if (sc->sc_c.np_net_type == *pr->r_data) + return (0); + sc->sc_d.np_net_type = *pr->r_data; + if (ifp->if_flags & IFF_RUNNING) + ray_sj_net(sc); + return (0); + + case RAY_MIB_SSID: + if (bcmp(sc->sc_c.np_ssid, pr->r_data, IEEE80211_NWID_LEN) == 0) + return (0); + bcopy(pr->r_data, sc->sc_d.np_ssid, IEEE80211_NWID_LEN); + if (ifp->if_flags & IFF_RUNNING) + ray_sj_net(sc); + return (0); + + case RAY_MIB_BASIC_RATE_SET: + sc->sc_d.np_def_txrate = *pr->r_data; + break; + + case RAY_MIB_AP_STATUS: /* Unsupported */ + case RAY_MIB_MAC_ADDR: /* XXX Need interface up */ + case RAY_MIB_PROMISC: /* BPF */ + return (EINVAL); + break; + + default: + break; + } + + if (pr->r_paramid > RAY_MIB_LASTUSER) { + return (EINVAL); + } + + /* wait to be able to issue the command */ + rv = 0; + while (ray_cmd_is_running(sc, SCP_UPD_UPDATEPARAMS) || + ray_cmd_is_scheduled(sc, SCP_UPD_UPDATEPARAMS)) { + rv = tsleep(ray_update_params, 0|PCATCH, "cmd in use", 0); + if (rv) + return (rv); + if ((ifp->if_flags & IFF_RUNNING) == 0) { + pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; + return (EIO); + } + } + + pr->r_failcause = RAY_FAILCAUSE_WAITING; + sc->sc_updreq = pr; + ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS); + ray_cmd_check_scheduled(sc); + + while (pr->r_failcause == RAY_FAILCAUSE_WAITING) + (void)tsleep(ray_update_params, 0, "waiting cmd", 0); + wakeup(ray_update_params); + + return (0); } /* + * update the parameter based on what the user passed in + */ +static void +ray_update_params(struct ray_softc *sc) +{ + struct ifnet *ifp; + size_t ccs; + + RAY_DPRINTFN(RAY_DBG_SUBR, ("ray%d: ray_update_params\n", sc->unit)); + RAY_MAP_CM(sc); + + ifp = &sc->arpcom.ac_if; + + ray_cmd_cancel(sc, SCP_UPD_UPDATEPARAMS); + if (!sc->sc_updreq) { + /* XXX do we need to wakeup here? */ + return; + } + + /* do the issue check before equality check */ + if ((ifp->if_flags & IFF_RUNNING) == 0) + return; + else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) { + ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS); + return; + } else if (!ray_ccs_alloc(sc, &ccs, RAY_CMD_UPDATE_PARAMS, 0)) + return; + + SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_paramid, + sc->sc_updreq->r_paramid); + SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_nparam, 1); + ray_write_region(sc, RAY_HOST_TO_ECF_BASE, sc->sc_updreq->r_data, + sc->sc_updreq->r_len); + + (void)ray_cmd_issue(sc, ccs, SCP_UPD_UPDATEPARAMS); +} + +/* + * an update params command has completed lookup which command and + * the status + * + * XXX this isn't finished yet, we need to grok the command used + */ +static void +ray_update_params_done(struct ray_softc *sc, size_t ccs, u_int stat) +{ + RAY_DPRINTFN(RAY_DBG_SUBR, + ("ray%d: ray_update_params_done\n", sc->unit)); + RAY_MAP_CM(sc); + + /* this will get more complex as we add commands */ + if (stat == RAY_CCS_STATUS_FAIL) { + printf("ray%d: failed to update a promisc\n", sc->unit); + /* XXX should probably reset */ + /* rcmd = ray_reset; */ + } + + if (sc->sc_running & SCP_UPD_PROMISC) { + ray_cmd_done(sc, SCP_UPD_PROMISC); + sc->sc_promisc = SRAM_READ_1(sc, RAY_HOST_TO_ECF_BASE); + RAY_DPRINTFN(RAY_DBG_IOCTL, + ("ray%d: new promisc value %d\n", sc->unit, + sc->sc_promisc)); + } else if (sc->sc_updreq) { + ray_cmd_done(sc, SCP_UPD_UPDATEPARAMS); + /* get the update parameter */ + sc->sc_updreq->r_failcause = + SRAM_READ_FIELD_1(sc, ccs, ray_cmd_update, c_failcause); + sc->sc_updreq = 0; + wakeup(ray_update_params); + ray_sj_net(sc); + } +} + +#else +static void ray_update_params(struct ray_softc *sc) {} +static void ray_update_params_done(struct ray_softc *sc, size_t ccs, u_int stat) {} + +static int ray_mcast_user(struct ray_softc *sc) {return (0);} +static void ray_mcast(struct ray_softc *sc, struct ray_comq_entry *com) {} +static void ray_mcast_done(struct ray_softc *sc, size_t ccs) {} +static int ray_promisc_user(struct ray_softc *sc) {return (0);} +static void ray_promisc(struct ray_softc *sc, struct ray_comq_entry *com) {} +static void ray_promisc_done(struct ray_softc *sc, size_t ccs) {} + + +static int ray_user_update_params(struct ray_softc *sc, struct ray_param_req *pr) {return (0);} +static int ray_user_report_params(struct ray_softc *sc, struct ray_param_req *pr) {return (0);} +#endif + +/* * Command queuing and execution * * XXX @@ -2851,868 +3652,71 @@ ray_com_ecf_check(struct ray_softc *sc, size_t ccs, char *mesg) #endif /* RAY_DEBUG & RAY_DBG_COM */ /* - * Functions based on CCS commands - */ - -/* - * report a parameter - */ -static void -ray_report_params(struct ray_softc *sc) -{ - struct ifnet *ifp; - size_t ccs; - - RAY_DPRINTFN(RAY_DBG_SUBR, ("ray%d: ray_report_params\n", sc->unit)); - RAY_MAP_CM(sc); - - ifp = &sc->arpcom.ac_if; - - if (!sc->sc_repreq) - return; - - /* do the issue check before equality check */ - if ((ifp->if_flags & IFF_RUNNING) == 0) - return; - else if (!ray_ccs_alloc(sc, &ccs, RAY_CMD_REPORT_PARAMS, 0)) - return; - - SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_paramid, - sc->sc_repreq->r_paramid); - SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_report, c_nparam, 1); - -} - -#if XXX_ASSOCWORKING_AGAIN -/*XXX move this further down the code */ -/* - * Start an association with an access point - */ -static void -ray_start_assoc(struct ray_softc *sc) -{ - struct ifnet *ifp; - - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); - RAY_MAP_CM(sc); - - ifp = &sc->arpcom.ac_if; - - if ((ifp->if_flags & IFF_RUNNING) == 0) - return; - - (void)ray_cmd_simple(sc, RAY_CMD_START_ASSOC, SCP_STARTASSOC); -} - -/* - * Complete association - */ -static void -ray_start_assoc_done(struct ray_softc *sc, size_t ccs) -{ - struct ifnet *ifp; - - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); - RAY_MAP_CM(sc); - RAY_DCOM_CHECK(sc, ccs); - - /* - * Hurrah! The network is now active. - * - * Clearing IFF_OACTIVE will ensure that the system will queue - * packets. Just before we return from the interrupt context - * we check to see if packets have been queued. - */ - ifp = &sc->arpcom.ac_if; - sc->sc_havenet = 1; - ifp->if_flags &= ~IFF_OACTIVE; - - ray_com_ecf_done(sc); -} -#endif XXX_ASSOCWORKING_AGAIN - -/* - * Download start up structures to card. - */ -static void -ray_download(struct ray_softc *sc, struct ray_comq_entry *com) -{ - struct ray_mib_4 ray_mib_4_default; - struct ray_mib_5 ray_mib_5_default; - - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); - RAY_MAP_CM(sc); - -#define MIB4(m) ray_mib_4_default.##m -#define MIB5(m) ray_mib_5_default.##m -#define PUT2(p, v) \ - do { (p)[0] = ((v >> 8) & 0xff); (p)[1] = (v & 0xff); } while(0) - - /* - * Firmware version 4 defaults - see if_raymib.h for details - */ - MIB4(mib_net_type) = sc->sc_d.np_net_type; - MIB4(mib_ap_status) = sc->sc_d.np_ap_status; - bcopy(sc->sc_d.np_ssid, MIB4(mib_ssid), IEEE80211_NWID_LEN); - MIB4(mib_scan_mode) = RAY_MIB_SCAN_MODE_DEFAULT; - MIB4(mib_apm_mode) = RAY_MIB_APM_MODE_DEFAULT; - bcopy(sc->sc_station_addr, MIB4(mib_mac_addr), ETHER_ADDR_LEN); - PUT2(MIB4(mib_frag_thresh), RAY_MIB_FRAG_THRESH_DEFAULT); - PUT2(MIB4(mib_dwell_time), RAY_MIB_DWELL_TIME_V4); - PUT2(MIB4(mib_beacon_period), RAY_MIB_BEACON_PERIOD_V4); - MIB4(mib_dtim_interval) = RAY_MIB_DTIM_INTERVAL_DEFAULT; - MIB4(mib_max_retry) = RAY_MIB_MAX_RETRY_DEFAULT; - MIB4(mib_ack_timo) = RAY_MIB_ACK_TIMO_DEFAULT; - MIB4(mib_sifs) = RAY_MIB_SIFS_DEFAULT; - MIB4(mib_difs) = RAY_MIB_DIFS_DEFAULT; - MIB4(mib_pifs) = RAY_MIB_PIFS_V4; - PUT2(MIB4(mib_rts_thresh), RAY_MIB_RTS_THRESH_DEFAULT); - PUT2(MIB4(mib_scan_dwell), RAY_MIB_SCAN_DWELL_V4); - PUT2(MIB4(mib_scan_max_dwell), RAY_MIB_SCAN_MAX_DWELL_V4); - MIB4(mib_assoc_timo) = RAY_MIB_ASSOC_TIMO_DEFAULT; - MIB4(mib_adhoc_scan_cycle) = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT; - MIB4(mib_infra_scan_cycle) = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT; - MIB4(mib_infra_super_scan_cycle) - = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT; - MIB4(mib_promisc) = RAY_MIB_PROMISC_DEFAULT; - PUT2(MIB4(mib_uniq_word), RAY_MIB_UNIQ_WORD_DEFAULT); - MIB4(mib_slot_time) = RAY_MIB_SLOT_TIME_V4; - MIB4(mib_roam_low_snr_thresh) = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT; - MIB4(mib_low_snr_count) = RAY_MIB_LOW_SNR_COUNT_DEFAULT; - MIB4(mib_infra_missed_beacon_count) - = RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT; - MIB4(mib_adhoc_missed_beacon_count) - = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT; - MIB4(mib_country_code) = RAY_MIB_COUNTRY_CODE_DEFAULT; - MIB4(mib_hop_seq) = RAY_MIB_HOP_SEQ_DEFAULT; - MIB4(mib_hop_seq_len) = RAY_MIB_HOP_SEQ_LEN_V4; - MIB4(mib_cw_max) = RAY_MIB_CW_MAX_V4; - MIB4(mib_cw_min) = RAY_MIB_CW_MIN_V4; - MIB4(mib_noise_filter_gain) = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT; - MIB4(mib_noise_limit_offset) = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT; - MIB4(mib_rssi_thresh_offset) = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT; - MIB4(mib_busy_thresh_offset) = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT; - MIB4(mib_sync_thresh) = RAY_MIB_SYNC_THRESH_DEFAULT; - MIB4(mib_test_mode) = RAY_MIB_TEST_MODE_DEFAULT; - MIB4(mib_test_min_chan) = RAY_MIB_TEST_MIN_CHAN_DEFAULT; - MIB4(mib_test_max_chan) = RAY_MIB_TEST_MAX_CHAN_DEFAULT; - - /* - * Firmware version 5 defaults - see if_raymib.h for details - */ - MIB5(mib_net_type) = sc->sc_d.np_net_type; - MIB4(mib_ap_status) = sc->sc_d.np_ap_status; - bcopy(sc->sc_d.np_ssid, MIB5(mib_ssid), IEEE80211_NWID_LEN); - MIB5(mib_scan_mode) = RAY_MIB_SCAN_MODE_DEFAULT; - MIB5(mib_apm_mode) = RAY_MIB_APM_MODE_DEFAULT; - bcopy(sc->sc_station_addr, MIB5(mib_mac_addr), ETHER_ADDR_LEN); - PUT2(MIB5(mib_frag_thresh), RAY_MIB_FRAG_THRESH_DEFAULT); - PUT2(MIB5(mib_dwell_time), RAY_MIB_DWELL_TIME_V5); - PUT2(MIB5(mib_beacon_period), RAY_MIB_BEACON_PERIOD_V5); - MIB5(mib_dtim_interval) = RAY_MIB_DTIM_INTERVAL_DEFAULT; - MIB5(mib_max_retry) = RAY_MIB_MAX_RETRY_DEFAULT; - MIB5(mib_ack_timo) = RAY_MIB_ACK_TIMO_DEFAULT; - MIB5(mib_sifs) = RAY_MIB_SIFS_DEFAULT; - MIB5(mib_difs) = RAY_MIB_DIFS_DEFAULT; - MIB5(mib_pifs) = RAY_MIB_PIFS_V5; - PUT2(MIB5(mib_rts_thresh), RAY_MIB_RTS_THRESH_DEFAULT); - PUT2(MIB5(mib_scan_dwell), RAY_MIB_SCAN_DWELL_V5); - PUT2(MIB5(mib_scan_max_dwell), RAY_MIB_SCAN_MAX_DWELL_V5); - MIB5(mib_assoc_timo) = RAY_MIB_ASSOC_TIMO_DEFAULT; - MIB5(mib_adhoc_scan_cycle) = RAY_MIB_ADHOC_SCAN_CYCLE_DEFAULT; - MIB5(mib_infra_scan_cycle) = RAY_MIB_INFRA_SCAN_CYCLE_DEFAULT; - MIB5(mib_infra_super_scan_cycle) - = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT; - MIB5(mib_promisc) = RAY_MIB_PROMISC_DEFAULT; - PUT2(MIB5(mib_uniq_word), RAY_MIB_UNIQ_WORD_DEFAULT); - MIB5(mib_slot_time) = RAY_MIB_SLOT_TIME_V5; - MIB5(mib_roam_low_snr_thresh) = RAY_MIB_ROAM_LOW_SNR_THRESH_DEFAULT; - MIB5(mib_low_snr_count) = RAY_MIB_LOW_SNR_COUNT_DEFAULT; - MIB5(mib_infra_missed_beacon_count) - = RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT; - MIB5(mib_adhoc_missed_beacon_count) - = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_DEFAULT; - MIB5(mib_country_code) = RAY_MIB_COUNTRY_CODE_DEFAULT; - MIB5(mib_hop_seq) = RAY_MIB_HOP_SEQ_DEFAULT; - MIB5(mib_hop_seq_len) = RAY_MIB_HOP_SEQ_LEN_V5; - PUT2(MIB5(mib_cw_max), RAY_MIB_CW_MAX_V5); - PUT2(MIB5(mib_cw_min), RAY_MIB_CW_MIN_V5); - MIB5(mib_noise_filter_gain) = RAY_MIB_NOISE_FILTER_GAIN_DEFAULT; - MIB5(mib_noise_limit_offset) = RAY_MIB_NOISE_LIMIT_OFFSET_DEFAULT; - MIB5(mib_rssi_thresh_offset) = RAY_MIB_RSSI_THRESH_OFFSET_DEFAULT; - MIB5(mib_busy_thresh_offset) = RAY_MIB_BUSY_THRESH_OFFSET_DEFAULT; - MIB5(mib_sync_thresh) = RAY_MIB_SYNC_THRESH_DEFAULT; - MIB5(mib_test_mode) = RAY_MIB_TEST_MODE_DEFAULT; - MIB5(mib_test_min_chan) = RAY_MIB_TEST_MIN_CHAN_DEFAULT; - MIB5(mib_test_max_chan) = RAY_MIB_TEST_MAX_CHAN_DEFAULT; - MIB5(mib_allow_probe_resp) = RAY_MIB_ALLOW_PROBE_RESP_DEFAULT; - MIB5(mib_privacy_must_start) = sc->sc_d.np_priv_start; - MIB5(mib_privacy_can_join) = sc->sc_d.np_priv_join; - MIB5(mib_basic_rate_set[0]) = sc->sc_d.np_def_txrate; - - if (sc->sc_version == RAY_ECFS_BUILD_4) - ray_write_region(sc, RAY_HOST_TO_ECF_BASE, - &ray_mib_4_default, sizeof(ray_mib_4_default)); - else - ray_write_region(sc, RAY_HOST_TO_ECF_BASE, - &ray_mib_5_default, sizeof(ray_mib_5_default)); - - (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_DOWNLOAD_PARAMS, 0); - ray_com_ecf(sc, com); -} - -/* - * Download completion routine. - */ -static void -ray_download_done(struct ray_softc *sc, size_t ccs) -{ - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); - RAY_DCOM_CHECK(sc, ccs); - - /* - * Fake the current network parameter settings so start_join_net - * will not bother updating them to the card (we would need to - * zero these anyway, so we might as well copy). - */ - sc->sc_c.np_net_type = sc->sc_d.np_net_type; - bcopy(sc->sc_d.np_ssid, sc->sc_c.np_ssid, IEEE80211_NWID_LEN); - - ray_com_ecf_done(sc); -} - -/* - * Start or join a network - */ -static void -ray_sj(struct ray_softc *sc, struct ray_comq_entry *com) -{ - struct ray_net_params np; - struct ifnet *ifp; - int update; - - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); - RAY_MAP_CM(sc); - - /* XXX do I need this anymore? how can IFF_RUNNING be cleared - * XXX before this routine exits - check in ray_ioctl and the - * network code itself. - */ - ifp = &sc->arpcom.ac_if; - if ((ifp->if_flags & IFF_RUNNING) == 0) { - RAY_PANIC(sc, "IFF_RUNNING == 0"); - } - - sc->sc_havenet = 0; - if (sc->sc_d.np_net_type == RAY_MIB_NET_TYPE_ADHOC) - (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_START_NET, 0); - else - (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_JOIN_NET, 0); - - update = 0; - if (bcmp(sc->sc_c.np_ssid, sc->sc_d.np_ssid, IEEE80211_NWID_LEN)) - update++; - if (sc->sc_c.np_net_type != sc->sc_d.np_net_type) - update++; - RAY_DPRINTF(sc, RAY_DBG_STARTJOIN, - "%s updating nw params", update?"is":"not"); - if (update) { - bzero(&np, sizeof(np)); - np.p_net_type = sc->sc_d.np_net_type; - bcopy(sc->sc_d.np_ssid, np.p_ssid, IEEE80211_NWID_LEN); - np.p_privacy_must_start = sc->sc_d.np_priv_start; - np.p_privacy_can_join = sc->sc_d.np_priv_join; - - ray_write_region(sc, RAY_HOST_TO_ECF_BASE, &np, sizeof(np)); - SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_net, c_upd_param, 1); - } else - SRAM_WRITE_FIELD_1(sc, com->c_ccs, ray_cmd_net, c_upd_param, 0); - - ray_com_ecf(sc, com); -} - -/* - * Complete start command or intermediate step in join command - */ -static void -ray_sj_done(struct ray_softc *sc, size_t ccs) -{ - struct ifnet *ifp; - u_int8_t o_net_type; - - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); - RAY_DCOM_CHECK(sc, ccs); - RAY_MAP_CM(sc); - - /* - * Read back any network parameters the ECF changed - */ - ray_read_region(sc, ccs, &sc->sc_c.p_1, sizeof(struct ray_cmd_net)); - - /* adjust values for buggy build 4 */ - if (sc->sc_c.np_def_txrate == 0x55) - sc->sc_c.np_def_txrate = sc->sc_d.np_def_txrate; - if (sc->sc_c.np_encrypt == 0x55) - sc->sc_c.np_encrypt = sc->sc_d.np_encrypt; - - /* card is telling us to update the network parameters */ - if (sc->sc_c.np_upd_param) { - RAY_DPRINTF(sc, RAY_DBG_STARTJOIN, "card updating parameters"); - o_net_type = sc->sc_c.np_net_type; /* XXX this may be wrong? */ - ray_read_region(sc, RAY_HOST_TO_ECF_BASE, - &sc->sc_c.p_2, sizeof(struct ray_net_params)); - if (sc->sc_c.np_net_type != o_net_type) { - RAY_PANIC(sc, "card changing network type"); -#if XXX - restart ray_start_join sequence - may need to split download_done for this -#endif - } - } - RAY_DNET_DUMP(sc, " after start/join network completed."); - - /* - * Hurrah! The network is now active. - * - * Clearing IFF_OACTIVE will ensure that the system will queue - * packets. Just before we return from the interrupt context - * we check to see if packets have been queued. - */ - ifp = &sc->arpcom.ac_if; -#if XXX_ASSOCWORKING_AGAIN - if (SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd) == RAY_CMD_JOIN_NET) - ray_start_assoc(sc); - else { - sc->sc_havenet = 1; - ifp->if_flags &= ~IFF_OACTIVE; - } -#else - sc->sc_havenet = 1; - ifp->if_flags &= ~IFF_OACTIVE; -#endif XXX_ASSOCWORKING_AGAIN - - ray_com_ecf_done(sc); -} - -#if 0 -/* - * User land entry to promiscuous mode changes - */ -static int -ray_promisc_user(struct ray_softc *sc) -{ - struct ifnet *ifp; - struct ray_comq_entry *com; - int error; - - RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); - - if ((ifp->if_flags & IFF_RUNNING) == 0) - return (0); - if (sc->promisc != !!(ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))) - return (0); - - MALLOC(com, struct ray_comq_entry *, sizeof(struct ray_comq_entry), - M_RAYCOM, M_WAITOK); - com->c_function = ray_promisc; - com->c_flags = RAY_COM_FWOK; - com->c_retval = 0; - com->c_ccs = NULL; - com->c_wakeup = com; -#if RAY_DEBUG > 0 - com->c_mesg = "ray_promisc"; -#endif /* RAY_DEBUG > 0 */ - ray_com_runq_add(sc, com); - - ray_com_runq(sc); - RAY_DPRINTF(sc, RAY_DBG_COM, "sleeping"); - (void)tsleep(com[3], 0, "raypromisc", 0); - RAY_DPRINTF(sc, RAY_DBG_COM, "awakened"); - - error = com->c_retval; - FREE(com, M_RAYCOM); - return (error); -} - -/* - * Set/reset promiscuous mode - */ -static void -ray_promisc(struct ray_softc *sc, struct ray_comq_entry *com) -{ - struct ifnet *ifp; - - RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); - RAY_MAP_CM(sc); - - ifp = &sc->arpcom.ac_if; - - (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_UPDATE_PARAMS, 0); - SRAM_WRITE_FIELD_1(sc, &com->c_ccs, - ray_cmd_update, c_paramid, RAY_MIB_PROMISC); - SRAM_WRITE_FIELD_1(sc, &com->c_ccs, ray_cmd_update, c_nparam, 1); - SRAM_WRITE_1(sc, RAY_HOST_TO_ECF_BASE, - !!(ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))); - - ray_com_ecf(sc, com); -} - -/* - * Complete the promiscuous mode update - */ -static void -ray_promisc_done(struct ray_softc *sc, size_t ccs) -{ - RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); - RAY_DCOM_CHECK(sc, ccs); - - ray_com_ecf_done(sc); -} - -/* - * update the parameter based on what the user passed in - */ -static void -ray_update_params(struct ray_softc *sc) -{ - struct ifnet *ifp; - size_t ccs; - - RAY_DPRINTFN(RAY_DBG_SUBR, ("ray%d: ray_update_params\n", sc->unit)); - RAY_MAP_CM(sc); - - ifp = &sc->arpcom.ac_if; - - ray_cmd_cancel(sc, SCP_UPD_UPDATEPARAMS); - if (!sc->sc_updreq) { - /* XXX do we need to wakeup here? */ - return; - } - - /* do the issue check before equality check */ - if ((ifp->if_flags & IFF_RUNNING) == 0) - return; - else if (ray_cmd_is_running(sc, SCP_UPDATESUBCMD)) { - ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS); - return; - } else if (!ray_ccs_alloc(sc, &ccs, RAY_CMD_UPDATE_PARAMS, 0)) - return; - - SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_paramid, - sc->sc_updreq->r_paramid); - SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_update, c_nparam, 1); - ray_write_region(sc, RAY_HOST_TO_ECF_BASE, sc->sc_updreq->r_data, - sc->sc_updreq->r_len); - - (void)ray_cmd_issue(sc, ccs, SCP_UPD_UPDATEPARAMS); -} - -/* - * an update params command has completed lookup which command and - * the status - * - * XXX this isn't finished yet, we need to grok the command used - */ -static void -ray_update_params_done(struct ray_softc *sc, size_t ccs, u_int stat) -{ - RAY_DPRINTFN(RAY_DBG_SUBR, - ("ray%d: ray_update_params_done\n", sc->unit)); - RAY_MAP_CM(sc); - - /* this will get more complex as we add commands */ - if (stat == RAY_CCS_STATUS_FAIL) { - printf("ray%d: failed to update a promisc\n", sc->unit); - /* XXX should probably reset */ - /* rcmd = ray_reset; */ - } - - if (sc->sc_running & SCP_UPD_PROMISC) { - ray_cmd_done(sc, SCP_UPD_PROMISC); - sc->sc_promisc = SRAM_READ_1(sc, RAY_HOST_TO_ECF_BASE); - RAY_DPRINTFN(RAY_DBG_IOCTL, - ("ray%d: new promisc value %d\n", sc->unit, - sc->sc_promisc)); - } else if (sc->sc_updreq) { - ray_cmd_done(sc, SCP_UPD_UPDATEPARAMS); - /* get the update parameter */ - sc->sc_updreq->r_failcause = - SRAM_READ_FIELD_1(sc, ccs, ray_cmd_update, c_failcause); - sc->sc_updreq = 0; - wakeup(ray_update_params); - ray_sj_net(sc); - } -} - -/* - * User land entry to multicast list changes - */ -static int -ray_mcast_user(struct ray_softc *sc) -{ - struct ifnet *ifp; - struct ray_comq_entry *com[2]; - int error, count; - - RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); - - ifp = &sc->arpcom.ac_if; - - /* - * The multicast list is only 16 items long so use promiscuous - * mode if needed. - * - * We track this stuff even when not running. - */ - for (ifma = ifp->if_multiaddrs.lh_first, count = 0; ifma != NULL; - ifma = ifma->ifma_link.le_next, count++) - if (count > 16) - ifp->if_flags |= IFF_ALLMULTI; - else if (ifp->if_flags & IFF_ALLMULTI) - ifp->if_flags &= ~IFF_ALLMULTI; - - if ((ifp->if_flags & IFF_RUNNING) == 0) { - return (0); - } - - /* - * If we need to change the promiscuous mode then do so. - */ - if (sc->promisc != !!(ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))) { - MALLOC(com[0], struct ray_comq_entry *, - sizeof(struct ray_comq_entry), M_RAYCOM, M_WAITOK); - com[0]->c_function = ray_promisc; - com[0]->c_flags = RAY_COM_FWOK; - com[0]->c_retval = 0; - com[0]->c_ccs = NULL; - com[0]->c_wakeup = com[1]; -#if RAY_DEBUG > 0 - com[0]->c_mesg = "ray_promisc"; -#endif /* RAY_DEBUG > 0 */ - ray_com_runq_add(sc, com[0]); - } else - com[0] = NULL; - - /* - * If we need to set the mcast list then do so. - */ - if (!(ifp->if_flags & IFF_ALLMULTI)) - MALLOC(com[1], struct ray_comq_entry *, - sizeof(struct ray_comq_entry), M_RAYCOM, M_WAITOK); - com[1]->c_function = ray_mcast; - com[0]->c_flags &= ~RAY_COM_FWOK; - com[1]->c_flags = RAY_COM_FWOK; - com[1]->c_retval = 0; - com[1]->c_ccs = NULL; - com[1]->c_wakeup = com[1]; -#if RAY_DEBUG > 0 - com[1]->c_mesg = "ray_mcast"; -#endif /* RAY_DEBUG > 0 */ - ray_com_runq_add(sc, com[1]); - } else - com[1] = NULL; - - ray_com_runq(sc); - RAY_DPRINTF(sc, RAY_DBG_COM, "sleeping"); - (void)tsleep(com[1], 0, "raymcast", 0); - RAY_DPRINTF(sc, RAY_DBG_COM, "awakened"); - - error = com->c_retval; - if (com[0] != NULL) - FREE(com[0], M_RAYCOM); - if (com[1] != NULL) - FREE(com[1], M_RAYCOM); - return (error); -} - -/* - * Set the multicast filter list - */ -static void -ray_mcast(struct ray_softc *sc, struct ray_comq_entry *com) -{ - struct ifnet *ifp; - struct ifmultiaddr *ifma; - size_t bufp; - - RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); - RAY_MAP_CM(sc); - - ifp = &sc->arpcom.ac_if; - - (void)ray_ccs_alloc(sc, &com->c_ccs, RAY_CMD_UPDATE_MCAST, 0); - SRAM_WRITE_FIELD_1(sc, &com->c_ccs, - ray_cmd_update_mcast, c_nmcast, count); - bufp = RAY_HOST_TO_ECF_BASE; - for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; - ifma = ifma->ifma_link.le_next) { - ray_write_region( - sc, - bufp, - LLADDR((struct sockaddr_dl *)ifma->ifma_addr), - ETHER_ADDR_LEN - ); - bufp += ETHER_ADDR_LEN; - } - - ray_com_ecf(sc, com); -} - -/* - * Complete the multicast filter list update + * CCS allocator for commands */ -static void -ray_mcast_done(struct ray_softc *sc, size_t ccs) -{ - RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); - RAY_DCOM_CHECK(sc, ccs); - - ray_com_ecf_done(sc); -} /* - * issue a update params + * Obtain a ccs and fill easy bits in * - * expected to be called in sleepable context -- intended for user stuff + * Returns 1 and in `ccsp' the bus offset of the free ccs. Will block + * awaiting free ccs if needed, timo is passed to tsleep and will + * return 0 if the timeout expired. */ static int -ray_user_update_params(struct ray_softc *sc, struct ray_param_req *pr) +ray_ccs_alloc(struct ray_softc *sc, size_t *ccsp, u_int cmd, int timo) { - struct ifnet *ifp; - int rv; + size_t ccs; + u_int i; - RAY_DPRINTFN(RAY_DBG_SUBR, - ("ray%d: ray_user_update_params\n", sc->unit)); + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CCS, ""); RAY_MAP_CM(sc); - ifp = &sc->arpcom.ac_if; - - if ((ifp->if_flags & IFF_RUNNING) == 0) { - pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; - return (EIO); - } - - if (pr->r_paramid > RAY_MIB_MAX) { - return (EINVAL); - } - - /* - * Handle certain parameters specially - */ - switch (pr->r_paramid) { - case RAY_MIB_NET_TYPE: - if (sc->sc_c.np_net_type == *pr->r_data) - return (0); - sc->sc_d.np_net_type = *pr->r_data; - if (ifp->if_flags & IFF_RUNNING) - ray_sj_net(sc); - return (0); - - case RAY_MIB_SSID: - if (bcmp(sc->sc_c.np_ssid, pr->r_data, IEEE80211_NWID_LEN) == 0) - return (0); - bcopy(pr->r_data, sc->sc_d.np_ssid, IEEE80211_NWID_LEN); - if (ifp->if_flags & IFF_RUNNING) - ray_sj_net(sc); - return (0); - - case RAY_MIB_BASIC_RATE_SET: - sc->sc_d.np_def_txrate = *pr->r_data; - break; - - case RAY_MIB_AP_STATUS: /* Unsupported */ - case RAY_MIB_MAC_ADDR: /* XXX Need interface up */ - case RAY_MIB_PROMISC: /* BPF */ - return (EINVAL); - break; - - default: - break; - } - - if (pr->r_paramid > RAY_MIB_LASTUSER) { - return (EINVAL); - } - - /* wait to be able to issue the command */ - rv = 0; - while (ray_cmd_is_running(sc, SCP_UPD_UPDATEPARAMS) || - ray_cmd_is_scheduled(sc, SCP_UPD_UPDATEPARAMS)) { - rv = tsleep(ray_update_params, 0|PCATCH, "cmd in use", 0); - if (rv) - return (rv); - if ((ifp->if_flags & IFF_RUNNING) == 0) { - pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; - return (EIO); + for (;;) { + for (i = RAY_CCS_CMD_FIRST; i <= RAY_CCS_CMD_LAST; i++) { + /* we probe here to make the card go */ + (void)SRAM_READ_FIELD_1(sc, RAY_CCS_ADDRESS(i), ray_cmd, + c_status); + if (!sc->sc_ccsinuse[i]) + break; } + if (i > RAY_CCS_CMD_LAST) { + RAY_PANIC(sc, "out of CCS's"); + } else + break; } - pr->r_failcause = RAY_FAILCAUSE_WAITING; - sc->sc_updreq = pr; - ray_cmd_schedule(sc, SCP_UPD_UPDATEPARAMS); - ray_cmd_check_scheduled(sc); - - while (pr->r_failcause == RAY_FAILCAUSE_WAITING) - (void)tsleep(ray_update_params, 0, "waiting cmd", 0); - wakeup(ray_update_params); + sc->sc_ccsinuse[i] = 1; + ccs = RAY_CCS_ADDRESS(i); + RAY_DPRINTF(sc, RAY_DBG_CCS, "allocated 0x%02x", i); + SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_status, RAY_CCS_STATUS_BUSY); + SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_cmd, cmd); + SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd, c_link, RAY_CCS_LINK_NULL); - return (0); + *ccsp = ccs; + return (1); } /* - * issue a report params + * Free up a ccs allocated via ray_ccs_alloc * - * expected to be called in sleapable context -- intended for user stuff + * Return the old status. This routine is only used for ccs allocated via + * ray_ccs_alloc (not tx, rx or ECF command requests). */ -static int -ray_user_report_params(struct ray_softc *sc, struct ray_param_req *pr) +static u_int8_t +ray_ccs_free(struct ray_softc *sc, size_t ccs) { - struct ifnet *ifp; - int mib_sizes[] = RAY_MIB_SIZES; - int rv; + u_int8_t status; - RAY_DPRINTFN(RAY_DBG_SUBR, - ("ray%d: ray_user_report_params\n", sc->unit)); + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_CCS, ""); RAY_MAP_CM(sc); - ifp = &sc->arpcom.ac_if; - - if ((ifp->if_flags & IFF_RUNNING) == 0) { - pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; - return (EIO); - } - - /* test for illegal values or immediate responses */ - if (pr->r_paramid > RAY_MIB_LASTUSER) { - switch (pr->r_paramid) { - - case RAY_MIB_VERSION: - if (sc->sc_version == RAY_ECFS_BUILD_4) - *pr->r_data = 4; - else - *pr->r_data = 5; - break; - - case RAY_MIB_CUR_BSSID: - bcopy(sc->sc_c.np_bss_id, pr->r_data, ETHER_ADDR_LEN); - break; - case RAY_MIB_CUR_INITED: - *pr->r_data = sc->sc_c.np_inited; - break; - case RAY_MIB_CUR_DEF_TXRATE: - *pr->r_data = sc->sc_c.np_def_txrate; - break; - case RAY_MIB_CUR_ENCRYPT: - *pr->r_data = sc->sc_c.np_encrypt; - break; - case RAY_MIB_CUR_NET_TYPE: - *pr->r_data = sc->sc_c.np_net_type; - break; - case RAY_MIB_CUR_SSID: - bcopy(sc->sc_c.np_ssid, pr->r_data, IEEE80211_NWID_LEN); - break; - case RAY_MIB_CUR_PRIV_START: - *pr->r_data = sc->sc_c.np_priv_start; - break; - case RAY_MIB_CUR_PRIV_JOIN: - *pr->r_data = sc->sc_c.np_priv_join; - break; - - case RAY_MIB_DES_BSSID: - bcopy(sc->sc_d.np_bss_id, pr->r_data, ETHER_ADDR_LEN); - break; - case RAY_MIB_DES_INITED: - *pr->r_data = sc->sc_d.np_inited; - break; - case RAY_MIB_DES_DEF_TXRATE: - *pr->r_data = sc->sc_d.np_def_txrate; - break; - case RAY_MIB_DES_ENCRYPT: - *pr->r_data = sc->sc_d.np_encrypt; - break; - case RAY_MIB_DES_NET_TYPE: - *pr->r_data = sc->sc_d.np_net_type; - break; - case RAY_MIB_DES_SSID: - bcopy(sc->sc_d.np_ssid, pr->r_data, IEEE80211_NWID_LEN); - break; - case RAY_MIB_DES_PRIV_START: - *pr->r_data = sc->sc_d.np_priv_start; - break; - case RAY_MIB_DES_PRIV_JOIN: - *pr->r_data = sc->sc_d.np_priv_join; - break; - - default: - return (EINVAL); - break; - } - pr->r_failcause = 0; - pr->r_len = mib_sizes[pr->r_paramid]; - return (0); - } - - /* wait to be able to issue the command */ - rv = 0; - while (ray_cmd_is_running(sc, SCP_REPORTPARAMS) - || ray_cmd_is_scheduled(sc, SCP_REPORTPARAMS)) { - rv = tsleep(ray_report_params, 0|PCATCH, "cmd in use", 0); - if (rv) - return (rv); - if ((ifp->if_flags & IFF_RUNNING) == 0) { - pr->r_failcause = RAY_FAILCAUSE_EDEVSTOP; - return (EIO); - } - } - - pr->r_failcause = RAY_FAILCAUSE_WAITING; - sc->sc_repreq = pr; - ray_cmd_schedule(sc, SCP_REPORTPARAMS); - ray_cmd_check_scheduled(sc); - - while (pr->r_failcause == RAY_FAILCAUSE_WAITING) - (void)tsleep(ray_report_params, 0, "waiting cmd", 0); - wakeup(ray_report_params); - - return (0); -} -#else -static void ray_update_params(struct ray_softc *sc) {} -static void ray_update_params_done(struct ray_softc *sc, size_t ccs, u_int stat) {} - -static int ray_mcast_user(struct ray_softc *sc) {return (0);} -static void ray_mcast(struct ray_softc *sc, struct ray_comq_entry *com) {} -static void ray_mcast_done(struct ray_softc *sc, size_t ccs) {} -static int ray_promisc_user(struct ray_softc *sc) {return (0);} -static void ray_promisc(struct ray_softc *sc, struct ray_comq_entry *com) {} -static void ray_promisc_done(struct ray_softc *sc, size_t ccs) {} - - -static int ray_user_update_params(struct ray_softc *sc, struct ray_param_req *pr) {return (0);} -static int ray_user_report_params(struct ray_softc *sc, struct ray_param_req *pr) {return (0);} -#endif - -/* - * Return the error counters - */ -static int -ray_user_report_stats(struct ray_softc *sc, struct ray_stats_req *sr) -{ - struct ifnet *ifp; - - RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); - - ifp = &sc->arpcom.ac_if; - if ((ifp->if_flags & IFF_RUNNING) == 0) { - return (EIO); - } - - sr->rxoverflow = sc->sc_rxoverflow; - sr->rxcksum = sc->sc_rxcksum; - sr->rxhcksum = sc->sc_rxhcksum; - sr->rxnoise = sc->sc_rxnoise; + status = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status); + RAY_CCS_FREE(sc, ccs); + sc->sc_ccsinuse[RAY_CCS_INDEX(ccs)] = 0; + wakeup(ray_ccs_alloc); + RAY_DPRINTF(sc, RAY_DBG_CCS, "freed 0x%02x", RAY_CCS_INDEX(ccs)); - return (0); + return (status); } /****************************************************************************** |