diff options
Diffstat (limited to 'sys/dev/ray/if_ray.c')
-rw-r--r-- | sys/dev/ray/if_ray.c | 787 |
1 files changed, 539 insertions, 248 deletions
diff --git a/sys/dev/ray/if_ray.c b/sys/dev/ray/if_ray.c index fe3af87..0b5822e 100644 --- a/sys/dev/ray/if_ray.c +++ b/sys/dev/ray/if_ray.c @@ -82,10 +82,9 @@ * Ad-hoc and infra-structure modes * ================================ * - * At present only the ad-hoc mode is tested. - * - * I have received an AP from Raylink and will be working on - * infrastructure mode. + * The driver supports ad-hoc mode for V4 firmware and infrastructure + * mode for V5 firmware. V5 firmware in ad-hoc mode is untested and should + * work. * * The Linux driver also seems to have the capability to act as an AP. * I wonder what facilities the "AP" can provide within a driver? We can @@ -93,36 +92,25 @@ * power saving etc. is easy. * * - * Packet framing/encapsulation - * ================================ + * Packet framing/encapsulation/translation + * ======================================== * - * Currently we only support the Webgear encapsulation + * Currently we support the Webgear encapsulation: * 802.11 header <net/if_ieee80211.h>struct ieee80211_frame * 802.3 header <net/ethernet.h>struct ether_header - * 802.2 LLC header - * 802.2 SNAP header + * IP/ARP payload * - * We should support whatever packet types the following drivers have - * if_wi.c FreeBSD, RFC1042 - * if_ray.c NetBSD Webgear, RFC1042 - * rayctl.c Linux Webgear, RFC1042 - * also whatever we can divine from the NDC Access points and Kanda's boxes. - * - * Most drivers appear to have a RFC1042 framing. The incoming packet is + * and RFC1042 encapsulation of IP datagrams (translation): * 802.11 header <net/if_ieee80211.h>struct ieee80211_frame * 802.2 LLC header * 802.2 SNAP header + * 802.3 Ethertype + * IP/ARP payload * - * This is translated to - * 802.3 header <net/ethernet.h>struct ether_header - * 802.2 LLC header - * 802.2 SNAP header - * - * Linux seems to look at the SNAP org_code and do some framings - * for IPX and APPLEARP on that. This just may be how Linux does IPX - * and NETATALK. Need to see how FreeBSD does these. - * - * Translation should be selected via if_media stuff or link types. + * Framing should be selected via if_media stuff or link types but + * is currently hardcoded to: + * V4 encapsulation + * V5 translation * * * Authentication @@ -141,23 +129,34 @@ */ /* + * ***check all XXX_INFRA code - reassoc not done well at all! * ***watchdog to catch screwed up removals? * ***error handling of RAY_COM_RUNQ * ***error handling of ECF command completions * ***can't seem to create a n/w that Win95 wants to see. - * ***need decent association code + * ***remove panic in ray_com_ecf by re-quing or timeout + * ***use new ioctl stuff - probably need to change RAY_COM_FCHKRUNNING things? + * consider user doing: + * ifconfig ray0 192.168.200.38 -bssid "freed" + * ifconfig ray0 192.168.200.38 -bssid "fred" + * here the second one would be missed in this code + * check that v5 needs timeouts on ecf commands * write up driver structure in comments above * UPDATE_PARAMS seems to return via an interrupt - maybe the timeout * is needed for wrong values? - * havenet needs checking again * proper setting of mib_hop_seq_len with country code for v4 firmware * best done with raycontrol? - * more translations - * might be able to autodetect them - * spinning in ray_com_ecf * countrycode setting is broken I think * userupdate should trap and do via startjoin etc. * fragmentation when rx level drops? + * v5 might not need download + * defaults are as documented apart from hop_seq_length + * settings are sane for ad-hoc not infra + * + * driver state + * most state is implied by the sequence of commands in the runq + * but in fact any of the rx and tx path that uses variables + * in the sc_c are potentially going to get screwed? * * infra mode stuff * proper handling of the basic rate set - see the manual @@ -166,6 +165,8 @@ * need to consider WEP * acting as ap - should be able to get working from the manual * need to finish RAY_ECMD_REJOIN_DONE + * finish authenitcation code, it doesn't handle errors/timeouts/ + * REJOIN etc. * * ray_nw_param * promisc in here too? - done @@ -205,6 +206,7 @@ #define XXX_ACTING_AP 0 #define XXX_INFRA 0 #define RAY_DEBUG ( \ + /* RAY_DBG_AUTH | */ \ /* RAY_DBG_SUBR | */ \ /* RAY_DBG_BOOTPARAM | */ \ /* RAY_DBG_STARTJOIN | */ \ @@ -212,7 +214,7 @@ /* RAY_DBG_IOCTL | */ \ /* RAY_DBG_MBUF | */ \ /* RAY_DBG_RX | */ \ - /* RAY_DBG_CM | */ \ + /* RAY_DBG_CM | */ \ /* RAY_DBG_COM | */ \ /* RAY_DBG_STOP | */ \ /* RAY_DBG_CTL | */ \ @@ -259,6 +261,7 @@ #include <net/if_arp.h> #include <net/if_dl.h> #include <net/if_ieee80211.h> +#include <net/if_llc.h> #include <machine/limits.h> @@ -292,26 +295,29 @@ static int ray_detach (device_t); static void ray_init (void *xsc); static int ray_init_user (struct ray_softc *sc); static void ray_init_assoc (struct ray_softc *sc, struct ray_comq_entry *com); -static void ray_init_assoc_done (struct ray_softc *sc, size_t ccs); +static void ray_init_assoc_done (struct ray_softc *sc, u_int8_t status, size_t ccs); +static void ray_init_auth (struct ray_softc *sc, struct ray_comq_entry *com); +static int ray_init_auth_send (struct ray_softc *sc, u_int8_t *dst, int sequence); +static void ray_init_auth_done (struct ray_softc *sc, u_int8_t status); static void ray_init_download (struct ray_softc *sc, struct ray_comq_entry *com); -static void ray_init_download_done (struct ray_softc *sc, size_t ccs); +static void ray_init_download_done (struct ray_softc *sc, u_int8_t status, size_t ccs); static void ray_init_download_v4 (struct ray_softc *sc, struct ray_comq_entry *com); static void ray_init_download_v5 (struct ray_softc *sc, struct ray_comq_entry *com); static void ray_init_mcast (struct ray_softc *sc, struct ray_comq_entry *com); static void ray_init_sj (struct ray_softc *sc, struct ray_comq_entry *com); -static void ray_init_sj_done (struct ray_softc *sc, size_t ccs); +static void ray_init_sj_done (struct ray_softc *sc, u_int8_t status, size_t ccs); static void ray_intr (void *xsc); static void ray_intr_ccs (struct ray_softc *sc, u_int8_t cmd, u_int8_t status, size_t ccs); static void ray_intr_rcs (struct ray_softc *sc, u_int8_t cmd, size_t ccs); static void ray_intr_updt_errcntrs (struct ray_softc *sc); static int ray_ioctl (struct ifnet *ifp, u_long command, caddr_t data); 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 void ray_mcast_done (struct ray_softc *sc, u_int8_t status, size_t ccs); static int ray_mcast_user (struct ray_softc *sc); static int ray_probe (device_t); static void ray_promisc (struct ray_softc *sc, struct ray_comq_entry *com); static void ray_repparams (struct ray_softc *sc, struct ray_comq_entry *com); -static void ray_repparams_done (struct ray_softc *sc, size_t ccs); +static void ray_repparams_done (struct ray_softc *sc, u_int8_t status, size_t ccs); static int ray_repparams_user (struct ray_softc *sc, struct ray_param_req *pr); static int ray_repstats_user (struct ray_softc *sc, struct ray_stats_req *sr); static int ray_res_alloc_am (struct ray_softc *sc); @@ -323,16 +329,18 @@ static void ray_rx_ctl (struct ray_softc *sc, struct mbuf *m0); static void ray_rx_data (struct ray_softc *sc, struct mbuf *m0, u_int8_t siglev, u_int8_t antenna); static void ray_rx_mgt (struct ray_softc *sc, struct mbuf *m0); static void ray_rx_mgt_auth (struct ray_softc *sc, struct mbuf *m0); +static void ray_rx_mgt_beacon (struct ray_softc *sc, struct mbuf *m0); +static void ray_rx_mgt_info (struct ray_softc *sc, struct mbuf *m0, struct ieee80211_information *elements); static void ray_rx_update_cache (struct ray_softc *sc, u_int8_t *src, u_int8_t siglev, u_int8_t antenna); static void ray_stop (struct ray_softc *sc, struct ray_comq_entry *com); static int ray_stop_user (struct ray_softc *sc); static void ray_tx (struct ifnet *ifp); -static void ray_tx_done (struct ray_softc *sc, size_t ccs); +static void ray_tx_done (struct ray_softc *sc, u_int8_t status, size_t ccs); static void ray_tx_timo (void *xsc); static int ray_tx_send (struct ray_softc *sc, size_t ccs, int pktlen, u_int8_t *dst); static size_t ray_tx_wrhdr (struct ray_softc *sc, size_t bufp, u_int8_t type, u_int8_t fc1, u_int8_t *addr1, u_int8_t *addr2, u_int8_t *addr3); static void ray_upparams (struct ray_softc *sc, struct ray_comq_entry *com); -static void ray_upparams_done (struct ray_softc *sc, size_t ccs); +static void ray_upparams_done (struct ray_softc *sc, u_int8_t status, size_t ccs); static int ray_upparams_user (struct ray_softc *sc, struct ray_param_req *pr); static void ray_watchdog (struct ifnet *ifp); static u_int8_t ray_tx_best_antenna (struct ray_softc *sc, u_int8_t *dst); @@ -583,7 +591,7 @@ ray_detach(device_t dev) * then clean the runq. */ sc->sc_gone = 1; - sc->sc_havenet = 0; + sc->sc_c.np_havenet = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); @@ -762,7 +770,7 @@ ray_init(void *xsc) static int ray_init_user(struct ray_softc *sc) { - struct ray_comq_entry *com[5]; + struct ray_comq_entry *com[6]; int error, ncom; RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); @@ -773,14 +781,21 @@ ray_init_user(struct ray_softc *sc) * init_download - download the network to the card * init_mcast - reset multicast list * init_sj - find or start a BSS + * init_auth - authenticate with a ESSID if needed * init_assoc - associate with a ESSID if needed * - * They are only actually executed if the card is not running + * They are only actually executed if the card is not running. + * We may enter this routine from a simple change of IP + * address and do not need to get the card to do these things. + * However, we cannot perform the check here as there may be + * commands in the runq that change the IFF_RUNNING state of + * the interface. */ ncom = 0; com[ncom++] = RAY_COM_MALLOC(ray_init_download, RAY_COM_FCHKRUNNING); com[ncom++] = RAY_COM_MALLOC(ray_init_mcast, RAY_COM_FCHKRUNNING); com[ncom++] = RAY_COM_MALLOC(ray_init_sj, RAY_COM_FCHKRUNNING); + com[ncom++] = RAY_COM_MALLOC(ray_init_auth, RAY_COM_FCHKRUNNING); com[ncom++] = RAY_COM_MALLOC(ray_init_assoc, RAY_COM_FCHKRUNNING); /* @@ -811,14 +826,8 @@ ray_init_download(struct ray_softc *sc, struct ray_comq_entry *com) RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); - /* - * If card already running we don't need to download. - */ - if ((com->c_flags & RAY_COM_FCHKRUNNING) && - (ifp->if_flags & IFF_RUNNING)) { - ray_com_runq_done(sc); - return; - } + /* If the card already running we might not need to download */ + RAY_COM_CHKRUNNING(sc, com, ifp); /* * Reset instance variables @@ -842,16 +851,22 @@ ray_init_download(struct ray_softc *sc, struct ray_comq_entry *com) sc->sc_d.np_def_txrate = RAY_MIB_BASIC_RATE_SET_DEFAULT; sc->sc_d.np_encrypt = 0; - sc->sc_d.np_net_type = RAY_MIB_NET_TYPE_DEFAULT; bzero(sc->sc_d.np_ssid, IEEE80211_NWID_LEN); - strncpy(sc->sc_d.np_ssid, RAY_MIB_SSID_DEFAULT, IEEE80211_NWID_LEN); + if (sc->sc_version == RAY_ECFS_BUILD_4) { + sc->sc_d.np_net_type = RAY_MIB_NET_TYPE_V4; + strncpy(sc->sc_d.np_ssid, RAY_MIB_SSID_V4, IEEE80211_NWID_LEN); + sc->sc_d.np_ap_status = RAY_MIB_AP_STATUS_V4; + sc->sc_d.np_framing = RAY_FRAMING_ENCAPSULATION; + } else { + sc->sc_d.np_net_type = RAY_MIB_NET_TYPE_V5; + strncpy(sc->sc_d.np_ssid, RAY_MIB_SSID_V5, IEEE80211_NWID_LEN); + sc->sc_d.np_ap_status = RAY_MIB_AP_STATUS_V5; + sc->sc_d.np_framing = RAY_FRAMING_TRANSLATION; + } sc->sc_d.np_priv_start = RAY_MIB_PRIVACY_MUST_START_DEFAULT; sc->sc_d.np_priv_join = RAY_MIB_PRIVACY_CAN_JOIN_DEFAULT; - sc->sc_d.np_ap_status = RAY_MIB_AP_STATUS_DEFAULT; sc->sc_d.np_promisc = !!(ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)); - sc->framing = SC_FRAMING_WEBGEAR; - /* XXX this is a hack whilst I transition the code. The instance * XXX variables above should be set somewhere else. This is needed for * XXX start_join */ @@ -890,37 +905,37 @@ ray_init_download_v4(struct ray_softc *sc, struct ray_comq_entry *com) MIB4(mib_net_type) = com->c_desired.np_net_type; MIB4(mib_ap_status) = com->c_desired.np_ap_status; bcopy(com->c_desired.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; + MIB4(mib_scan_mode) = RAY_MIB_SCAN_MODE_V4; + MIB4(mib_apm_mode) = RAY_MIB_APM_MODE_V4; 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_frag_thresh), RAY_MIB_FRAG_THRESH_V4); 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_dtim_interval) = RAY_MIB_DTIM_INTERVAL_V4; + MIB4(mib_max_retry) = RAY_MIB_MAX_RETRY_V4; + MIB4(mib_ack_timo) = RAY_MIB_ACK_TIMO_V4; + MIB4(mib_sifs) = RAY_MIB_SIFS_V4; + MIB4(mib_difs) = RAY_MIB_DIFS_V4; MIB4(mib_pifs) = RAY_MIB_PIFS_V4; - PUT2(MIB4(mib_rts_thresh), RAY_MIB_RTS_THRESH_DEFAULT); + PUT2(MIB4(mib_rts_thresh), RAY_MIB_RTS_THRESH_V4); 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_assoc_timo) = RAY_MIB_ASSOC_TIMO_V4; + MIB4(mib_adhoc_scan_cycle) = RAY_MIB_ADHOC_SCAN_CYCLE_V4; + MIB4(mib_infra_scan_cycle) = RAY_MIB_INFRA_SCAN_CYCLE_V4; MIB4(mib_infra_super_scan_cycle) - = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT; + = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_V4; MIB4(mib_promisc) = com->c_desired.np_promisc; - PUT2(MIB4(mib_uniq_word), RAY_MIB_UNIQ_WORD_DEFAULT); + PUT2(MIB4(mib_uniq_word), RAY_MIB_UNIQ_WORD_V4); 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_roam_low_snr_thresh) = RAY_MIB_ROAM_LOW_SNR_THRESH_V4; + MIB4(mib_low_snr_count) = RAY_MIB_LOW_SNR_COUNT_V4; MIB4(mib_infra_missed_beacon_count) - = RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT; + = RAY_MIB_INFRA_MISSED_BEACON_COUNT_V4; 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; + = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_V4; + MIB4(mib_country_code) = RAY_MIB_COUNTRY_CODE_V4; + MIB4(mib_hop_seq) = RAY_MIB_HOP_SEQ_V4; 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; @@ -930,8 +945,8 @@ ray_init_download_v4(struct ray_softc *sc, struct ray_comq_entry *com) 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; + MIB4(mib_test_min_chan) = RAY_MIB_TEST_MIN_CHAN_DEFAULT; + MIB4(mib_test_max_chan) = RAY_MIB_TEST_MAX_CHAN_DEFAULT; #undef MIB4 SRAM_WRITE_REGION(sc, RAY_HOST_TO_ECF_BASE, @@ -953,37 +968,37 @@ ray_init_download_v5(struct ray_softc *sc, struct ray_comq_entry *com) MIB5(mib_net_type) = com->c_desired.np_net_type; MIB5(mib_ap_status) = com->c_desired.np_ap_status; bcopy(com->c_desired.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; + MIB5(mib_scan_mode) = RAY_MIB_SCAN_MODE_V5; + MIB5(mib_apm_mode) = RAY_MIB_APM_MODE_V5; 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_frag_thresh), RAY_MIB_FRAG_THRESH_V5); 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_dtim_interval) = RAY_MIB_DTIM_INTERVAL_V5; + MIB5(mib_max_retry) = RAY_MIB_MAX_RETRY_V5; + MIB5(mib_ack_timo) = RAY_MIB_ACK_TIMO_V5; + MIB5(mib_sifs) = RAY_MIB_SIFS_V5; + MIB5(mib_difs) = RAY_MIB_DIFS_V5; MIB5(mib_pifs) = RAY_MIB_PIFS_V5; - PUT2(MIB5(mib_rts_thresh), RAY_MIB_RTS_THRESH_DEFAULT); + PUT2(MIB5(mib_rts_thresh), RAY_MIB_RTS_THRESH_V5); 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_assoc_timo) = RAY_MIB_ASSOC_TIMO_V5; + MIB5(mib_adhoc_scan_cycle) = RAY_MIB_ADHOC_SCAN_CYCLE_V5; + MIB5(mib_infra_scan_cycle) = RAY_MIB_INFRA_SCAN_CYCLE_V5; MIB5(mib_infra_super_scan_cycle) - = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_DEFAULT; + = RAY_MIB_INFRA_SUPER_SCAN_CYCLE_V5; MIB5(mib_promisc) = com->c_desired.np_promisc; - PUT2(MIB5(mib_uniq_word), RAY_MIB_UNIQ_WORD_DEFAULT); + PUT2(MIB5(mib_uniq_word), RAY_MIB_UNIQ_WORD_V5); 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_roam_low_snr_thresh) = RAY_MIB_ROAM_LOW_SNR_THRESH_V5; + MIB5(mib_low_snr_count) = RAY_MIB_LOW_SNR_COUNT_V5; MIB5(mib_infra_missed_beacon_count) - = RAY_MIB_INFRA_MISSED_BEACON_COUNT_DEFAULT; + = RAY_MIB_INFRA_MISSED_BEACON_COUNT_V5; 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; + = RAY_MIB_ADHOC_MISSED_BEACON_COUNT_V5; + MIB5(mib_country_code) = RAY_MIB_COUNTRY_CODE_V5; + MIB5(mib_hop_seq) = RAY_MIB_HOP_SEQ_V5; 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); @@ -993,8 +1008,8 @@ ray_init_download_v5(struct ray_softc *sc, struct ray_comq_entry *com) 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_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) = com->c_desired.np_priv_start; MIB5(mib_privacy_can_join) = com->c_desired.np_priv_join; @@ -1010,11 +1025,13 @@ ray_init_download_v5(struct ray_softc *sc, struct ray_comq_entry *com) * Download completion routine */ static void -ray_init_download_done(struct ray_softc *sc, size_t ccs) +ray_init_download_done(struct ray_softc *sc, u_int8_t status, size_t ccs) { RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); RAY_COM_CHECK(sc, ccs); + RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */ + ray_com_ecf_done(sc); } @@ -1029,14 +1046,8 @@ ray_init_mcast(struct ray_softc *sc, struct ray_comq_entry *com) RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); RAY_MAP_CM(sc); - /* - * If card is already running we don't need to reset the list - */ - if ((com->c_flags & RAY_COM_FCHKRUNNING) && - (ifp->if_flags & IFF_RUNNING)) { - ray_com_runq_done(sc); - return; - } + /* If the card already running we might not need to reset the list */ + RAY_COM_CHKRUNNING(sc, com, ifp); /* * Kick the card @@ -1060,16 +1071,15 @@ ray_init_sj(struct ray_softc *sc, struct ray_comq_entry *com) RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); RAY_MAP_CM(sc); + /* If the card already running we might not need to start the n/w */ + RAY_COM_CHKRUNNING(sc, com, ifp); + /* - * If card already running we don't need to start the n/w. + * Set up the right start or join command and determine + * whether we should tell the card about a change in operating + * parameters. */ - if ((com->c_flags & RAY_COM_FCHKRUNNING) && - (ifp->if_flags & IFF_RUNNING)) { - ray_com_runq_done(sc); - return; - } - - sc->sc_havenet = 0; + sc->sc_c.np_havenet = 0; if (sc->sc_d.np_net_type == RAY_MIB_NET_TYPE_ADHOC) ray_ccs_fill(sc, com->c_ccs, RAY_CMD_START_NET); else @@ -1107,7 +1117,7 @@ ray_init_sj(struct ray_softc *sc, struct ray_comq_entry *com) * Complete start command or intermediate step in assoc command */ static void -ray_init_sj_done(struct ray_softc *sc, size_t ccs) +ray_init_sj_done(struct ray_softc *sc, u_int8_t status, size_t ccs) { struct ifnet *ifp = &sc->arpcom.ac_if; @@ -1115,12 +1125,16 @@ ray_init_sj_done(struct ray_softc *sc, size_t ccs) RAY_MAP_CM(sc); RAY_COM_CHECK(sc, ccs); + RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */ + /* * Read back network parameters that the ECF sets */ SRAM_READ_REGION(sc, ccs, &sc->sc_c.p_1, sizeof(struct ray_cmd_net)); - /* Adjust values for buggy build 4 */ + /* Adjust values for buggy firmware */ + if (sc->sc_c.np_inited == 0x55) + sc->sc_c.np_inited = 0; 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) @@ -1144,7 +1158,8 @@ ray_init_sj_done(struct ray_softc *sc, size_t ccs) * we check to see if packets have been queued. */ if (SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_cmd) == RAY_CMD_START_NET) { - sc->sc_havenet = 1; + sc->sc_c.np_havenet = 1; + sc->sc_c.np_framing = sc->sc_d.np_framing; ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; } @@ -1153,28 +1168,121 @@ ray_init_sj_done(struct ray_softc *sc, size_t ccs) } /* - * Runq entry to starting an association with an access point + * Runq entry to authenticate with an access point or another station */ static void -ray_init_assoc(struct ray_softc *sc, struct ray_comq_entry *com) +ray_init_auth(struct ray_softc *sc, struct ray_comq_entry *com) { struct ifnet *ifp = &sc->arpcom.ac_if; - RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN | RAY_DBG_AUTH, ""); + + /* If card already running we might not need to authenticate */ + RAY_COM_CHKRUNNING(sc, com, ifp); /* - * Don't do anything if we are not in a managed network + * XXX Don't do anything if we are not in a managed network + * + * XXX V4 adhoc does not need this, V5 adhoc unknown */ if (sc->sc_c.np_net_type != RAY_MIB_NET_TYPE_INFRA) { ray_com_runq_done(sc); return; } +/* + * XXX_AUTH need to think of run queue when doing auths from request i.e. would + * XXX_AUTH need to have auth at top of runq? + * XXX_AUTH ditto for sending any auth response packets...what about timeouts? + */ + + /* + * Kick the card + */ +/* XXX_AUTH check exit status and retry or fail as we can't associate without this */ + ray_init_auth_send(sc, sc->sc_c.np_bss_id, IEEE80211_AUTH_OPEN_REQUEST); +} + +/* + * Build and send an authentication packet + * + * If an error occurs, returns 1 else returns 0. + */ +static int +ray_init_auth_send(struct ray_softc *sc, u_int8_t *dst, int sequence) +{ + size_t ccs, bufp; + int pktlen = 0; + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN | RAY_DBG_AUTH, ""); + + /* Get a control block */ + if (ray_ccs_tx(sc, &ccs, &bufp)) { + RAY_RECERR(sc, "could not obtain a ccs"); + return (1); + } + + /* Fill the header in */ + bufp = ray_tx_wrhdr(sc, bufp, + IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_AUTH, + IEEE80211_FC1_DIR_NODS, + dst, + sc->arpcom.ac_enaddr, + sc->sc_c.np_bss_id); + + /* Add algorithm number */ + SRAM_WRITE_1(sc, bufp + pktlen++, IEEE80211_AUTH_ALG_OPEN); + SRAM_WRITE_1(sc, bufp + pktlen++, 0); + + /* Add sequence number */ + SRAM_WRITE_1(sc, bufp + pktlen++, sequence); + SRAM_WRITE_1(sc, bufp + pktlen++, 0); + + /* Add status code */ + SRAM_WRITE_1(sc, bufp + pktlen++, 0); + SRAM_WRITE_1(sc, bufp + pktlen++, 0); + pktlen += sizeof(struct ieee80211_frame); + + return (ray_tx_send(sc, ccs, pktlen, dst)); +} + +/* + * Complete authentication runq + */ +static void +ray_init_auth_done(struct ray_softc *sc, u_int8_t status) +{ + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN | RAY_DBG_AUTH, ""); + + if (status != IEEE80211_STATUS_SUCCESS) + RAY_RECERR(sc, "authentication failed with status %d", status); +/* + * XXX_AUTH retry? if not just recall ray_init_auth_send and dont clear runq? + * XXX_AUTH association requires that authenitcation is successful + * XXX_AUTH before we associate, and the runq is the only way to halt the + * XXX_AUTH progress of associate. + * XXX_AUTH In this case I might not need the RAY_AUTH_NEEDED state + */ + ray_com_runq_done(sc); +} + +/* + * Runq entry to starting an association with an access point + */ +static void +ray_init_assoc(struct ray_softc *sc, struct ray_comq_entry *com) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); + + /* If the card already running we might not need to associate */ + RAY_COM_CHKRUNNING(sc, com, ifp); + /* - * If card already running we don't need to associate. + * Don't do anything if we are not in a managed network */ - if ((com->c_flags & RAY_COM_FCHKRUNNING) && - (ifp->if_flags & IFF_RUNNING)) { + if (sc->sc_c.np_net_type != RAY_MIB_NET_TYPE_INFRA) { ray_com_runq_done(sc); return; } @@ -1190,13 +1298,15 @@ ray_init_assoc(struct ray_softc *sc, struct ray_comq_entry *com) * Complete association */ static void -ray_init_assoc_done(struct ray_softc *sc, size_t ccs) +ray_init_assoc_done(struct ray_softc *sc, u_int8_t status, size_t ccs) { struct ifnet *ifp = &sc->arpcom.ac_if; RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); RAY_COM_CHECK(sc, ccs); + RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */ + /* * Hurrah! The network is now active. * @@ -1204,7 +1314,8 @@ ray_init_assoc_done(struct ray_softc *sc, size_t ccs) * packets. Just before we return from the interrupt context * we check to see if packets have been queued. */ - sc->sc_havenet = 1; + sc->sc_c.np_havenet = 1; + sc->sc_c.np_framing = sc->sc_d.np_framing; ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -1321,6 +1432,7 @@ ray_tx(struct ifnet *ifp) struct ray_softc *sc = ifp->if_softc; struct mbuf *m0, *m; struct ether_header *eh; + struct llc *llc; size_t ccs, bufp; int pktlen, len; @@ -1336,15 +1448,18 @@ ray_tx(struct ifnet *ifp) RAY_RECERR(sc, "cannot transmit - not running"); return; } - if (!sc->sc_havenet) { + if (!sc->sc_c.np_havenet) { RAY_RECERR(sc, "cannot transmit - no network"); return; } if (!RAY_ECF_READY(sc)) { /* Can't assume that the ECF is busy because of this driver */ - RAY_RECERR(sc, "cannot transmit - ECF busy"); - sc->tx_timerh = timeout(ray_tx_timo, sc, RAY_TX_TIMEOUT); - return; + if ((sc->tx_timerh.callout == NULL) || + (!callout_active(sc->tx_timerh.callout))) { + sc->tx_timerh = + timeout(ray_tx_timo, sc, RAY_TX_TIMEOUT); + return; + } } else untimeout(ray_tx_timo, sc, sc->tx_timerh); @@ -1361,14 +1476,13 @@ ray_tx(struct ifnet *ifp) /* * Get the mbuf and process it - we have to remember to free the - * ccs if there are any errors + * ccs if there are any errors. */ IF_DEQUEUE(&ifp->if_snd, m0); if (m0 == NULL) { RAY_CCS_FREE(sc, ccs); return; } - eh = mtod(m0, struct ether_header *); pktlen = m0->m_pkthdr.len; if (pktlen > ETHER_MAX_LEN - ETHER_CRC_LEN) { @@ -1379,8 +1493,17 @@ ray_tx(struct ifnet *ifp) return; } + m0 = m_pullup(m0, sizeof(struct ether_header)); + if (m0 == NULL) { + RAY_RECERR(sc, "could not pullup ether"); + RAY_CCS_FREE(sc, ccs); + ifp->if_oerrors++; + return; + } + eh = mtod(m0, struct ether_header *); + /* - * Write the header according to network type etc. + * Write the 802.11 header according to network type etc. */ if (sc->sc_c.np_net_type == RAY_MIB_NET_TYPE_ADHOC) bufp = ray_tx_wrhdr(sc, bufp, @@ -1406,29 +1529,39 @@ ray_tx(struct ifnet *ifp) eh->ether_shost); /* - * Translation - capability as described earlier - * - * Remove/modify/addto the 802.3 and 802.2 headers as needed. - * - * We've pulled up the mbuf for you. + * Framing * + * Add to the mbuf. */ - if (m0->m_len < sizeof(struct ether_header)) - m0 = m_pullup(m0, sizeof(struct ether_header)); - if (m0 == NULL) { - RAY_RECERR(sc, "could not pullup ether"); - RAY_CCS_FREE(sc, ccs); - ifp->if_oerrors++; - return; - } - switch (sc->framing) { + switch (sc->sc_c.np_framing) { - case SC_FRAMING_WEBGEAR: + case RAY_FRAMING_ENCAPSULATION: /* Nice and easy - nothing! (just add an 802.11 header) */ break; + case RAY_FRAMING_TRANSLATION: + /* + * Drop the first address in the ethernet header and + * write an LLC and SNAP header over the second. + */ + m_adj(m0, ETHER_ADDR_LEN); + if (m0 == NULL) { + RAY_RECERR(sc, "could not get space for 802.2 header"); + RAY_CCS_FREE(sc, ccs); + ifp->if_oerrors++; + return; + } + llc = mtod(m0, struct llc *); + llc->llc_dsap = LLC_SNAP_LSAP; + llc->llc_ssap = LLC_SNAP_LSAP; + llc->llc_control = LLC_UI; + llc->llc_un.type_snap.org_code[0] = 0; + llc->llc_un.type_snap.org_code[1] = 0; + llc->llc_un.type_snap.org_code[2] = 0; + break; + default: - RAY_RECERR(sc, "unknown framing type %d", sc->framing); + RAY_RECERR(sc, "unknown framing type %d", sc->sc_c.np_framing); RAY_CCS_FREE(sc, ccs); ifp->if_oerrors++; m_freem(m0); @@ -1441,6 +1574,7 @@ ray_tx(struct ifnet *ifp) ifp->if_oerrors++; return; } + RAY_MBUF_DUMP(sc, RAY_DBG_TX, m0, "framed packet"); /* * Copy the mbuf to the buffer in common memory @@ -1531,13 +1665,13 @@ ray_tx_wrhdr(struct ray_softc *sc, size_t bufp, u_int8_t type, u_int8_t fc1, u_i static int ray_tx_send(struct ray_softc *sc, size_t ccs, int pktlen, u_int8_t *dst) { - int i = 0; + int i = 0; RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_TX, ""); RAY_MAP_CM(sc); while (!RAY_ECF_READY(sc)) { - DELAY(RAY_ECF_SPIN_DELAY); + DELAY(RAY_ECF_SPIN_DELAY); if (++i > RAY_ECF_SPIN_TRIES) { RAY_RECERR(sc, "ECF busy, dropping packet"); RAY_CCS_FREE(sc, ccs); @@ -1546,7 +1680,7 @@ ray_tx_send(struct ray_softc *sc, size_t ccs, int pktlen, u_int8_t *dst) } if (i != 0) RAY_RECERR(sc, "spun %d times", i); - + SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_len, pktlen); SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_antenna, ray_tx_best_antenna(sc, dst)); @@ -1599,20 +1733,13 @@ found: * Transmit now complete so clear ccs and network flags. */ static void -ray_tx_done(struct ray_softc *sc, size_t ccs) +ray_tx_done(struct ray_softc *sc, u_int8_t status, size_t ccs) { struct ifnet *ifp = &sc->arpcom.ac_if; - char *ss[] = RAY_CCS_STATUS_STRINGS; - u_int8_t status; RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_TX, ""); - RAY_MAP_CM(sc); - status = SRAM_READ_FIELD_1(sc, ccs, ray_cmd, c_status); - if (status != RAY_CCS_STATUS_COMPLETE) { - RAY_RECERR(sc, "tx completed but status is %s", ss[status]); - ifp->if_oerrors++; - } + RAY_CCSERR(sc, status, if_oerrors); RAY_CCS_FREE(sc, ccs); ifp->if_timer = 0; @@ -1784,7 +1911,9 @@ ray_rx_data(struct ray_softc *sc, struct mbuf *m0, u_int8_t siglev, u_int8_t ant struct ifnet *ifp = &sc->arpcom.ac_if; struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *); struct ether_header *eh; - u_int8_t *sa, *da, *ra, *ta; + struct llc *llc; + u_int8_t *sa = NULL, *da = NULL, *ra = NULL, *ta = NULL; + int trim = 0; RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_RX, ""); @@ -1819,37 +1948,47 @@ ray_rx_data(struct ray_softc *sc, struct mbuf *m0, u_int8_t siglev, u_int8_t ant } /* - * Obtain the .11 addresses. Packets may come via APs so the - * MAC addresses of the source/destination may be different - * from the node that actually sent us the packet. + * Parse the To DS and From DS fields to determine the length + * of the 802.11 header for use later on. + * + * Additionally, furtle out the right destination and + * source MAC addresses for the packet. Packets may come via + * APs so the MAC addresses of the immediate node may be + * different from the node that actually sent us the packet. + * + * da destination address of final recipient + * sa source address of orginator + * ra receiver address of immediate recipient + * ta transmitter address of immediate orginator * - * XXX At present this information is unused, although it is - * XXX available for translation routines to use. + * Address matching is performed on da or sa with the AP or + * BSSID in ra and ta. */ + RAY_MBUF_DUMP(sc, RAY_DBG_RX, m0, "(1) packet before framing"); switch (header->i_fc[1] & IEEE80211_FC1_DIR_MASK) { case IEEE80211_FC1_DIR_NODS: - da = header->i_addr1; - sa = header->i_addr2; - ra = ta = NULL; + da = ra = header->i_addr1; + sa = ta = header->i_addr2; + trim = sizeof(struct ieee80211_frame); RAY_DPRINTF(sc, RAY_DBG_RX, "from %6D to %6D", sa, ":", da, ":"); break; case IEEE80211_FC1_DIR_FROMDS: - da = header->i_addr1; + da = ra = header->i_addr1; ta = header->i_addr2; sa = header->i_addr3; - ra = NULL; + trim = sizeof(struct ieee80211_frame); RAY_DPRINTF(sc, RAY_DBG_RX, "ap %6D from %6D to %6D", ta, ":", sa, ":", da, ":"); break; case IEEE80211_FC1_DIR_TODS: ra = header->i_addr1; - sa = header->i_addr2; + sa = ta = header->i_addr2; da = header->i_addr3; - ta = NULL; + trim = sizeof(struct ieee80211_frame); RAY_DPRINTF(sc, RAY_DBG_RX, "from %6D to %6D ap %6D", sa, ":", da, ":", ra, ":"); break; @@ -1859,36 +1998,85 @@ ray_rx_data(struct ray_softc *sc, struct mbuf *m0, u_int8_t siglev, u_int8_t ant ta = header->i_addr2; da = header->i_addr3; sa = (u_int8_t *)header+1; + trim = sizeof(struct ieee80211_frame) + ETHER_ADDR_LEN; RAY_DPRINTF(sc, RAY_DBG_RX, "from %6D to %6D ap %6D to %6D", sa, ":", da, ":", ta, ":", ra, ":"); break; } /* - * Translation - capability as described earlier + * Framing * - * Each case must remove the 802.11 header and leave an 802.3 - * header in the mbuf copy addresses as needed. + * Each case must leave an Ethernet header and adjust trim. */ - RAY_MBUF_DUMP(sc, RAY_DBG_RX, m0, "DATA packet before framing"); - switch (sc->framing) { + switch (sc->sc_c.np_framing) { - case SC_FRAMING_WEBGEAR: - /* Nice and easy - just trim the 802.11 header */ - m_adj(m0, sizeof(struct ieee80211_frame)); + case RAY_FRAMING_ENCAPSULATION: + /* A NOP as the Ethernet header is in the packet */ + break; + + case RAY_FRAMING_TRANSLATION: + /* Check that we have an LLC and SNAP sequence */ + llc = (struct llc *)((u_int8_t *)header + trim); + if (llc->llc_dsap == LLC_SNAP_LSAP && + llc->llc_ssap == LLC_SNAP_LSAP && + llc->llc_control == LLC_UI && + llc->llc_un.type_snap.org_code[0] == 0 && + llc->llc_un.type_snap.org_code[1] == 0 && + llc->llc_un.type_snap.org_code[2] == 0) { + /* + * This is not magic. RFC1042 header is 8 + * bytes, with the last two bytes being the + * ether type. So all we need is another + * ETHER_ADDR_LEN bytes to write the + * destination into. + */ + trim -= ETHER_ADDR_LEN; + eh = (struct ether_header *)((u_int8_t *)header + trim); + + /* + * Copy carefully to avoid mashing the MAC + * addresses. The address layout in the .11 header + * does make sense, honest, but it is a pain. + * + * NODS da sa no risk + * FROMDS da ta sa sa then da + * DSTODS ra ta da sa sa then da + * TODS ra sa da da then sa + */ + if (sa > da) { + /* Copy sa first */ + bcopy(sa, eh->ether_shost, ETHER_ADDR_LEN); + bcopy(da, eh->ether_dhost, ETHER_ADDR_LEN); + } else { + /* Copy da first */ + bcopy(da, eh->ether_dhost, ETHER_ADDR_LEN); + bcopy(sa, eh->ether_shost, ETHER_ADDR_LEN); + } + + } else { + + /* Assume RAY_FRAMING_ENCAPSULATION */ + RAY_RECERR(sc, + "got encapsulated packet but in translation mode"); + + } break; default: - RAY_RECERR(sc, "unknown framing type %d", sc->framing); + RAY_RECERR(sc, "unknown framing type %d", sc->sc_c.np_framing); ifp->if_ierrors++; m_freem(m0); return; } + RAY_MBUF_DUMP(sc, RAY_DBG_RX, m0, "(2) packet after framing"); /* * Finally, do a bit of house keeping before sending the packet * up the stack. */ + m_adj(m0, trim); + RAY_MBUF_DUMP(sc, RAY_DBG_RX, m0, "(3) packet after trimming"); ifp->if_ipackets++; ray_rx_update_cache(sc, header->i_addr2, siglev, antenna); eh = mtod(m0, struct ether_header *); @@ -1944,6 +2132,7 @@ ray_rx_mgt(struct ray_softc *sc, struct mbuf *m0) case IEEE80211_FC0_SUBTYPE_BEACON: RAY_DPRINTF(sc, RAY_DBG_MGT, "BEACON MGT packet"); + ray_rx_mgt_beacon(sc, m0); break; case IEEE80211_FC0_SUBTYPE_AUTH: @@ -1996,71 +2185,160 @@ ray_rx_mgt(struct ray_softc *sc, struct mbuf *m0) } /* - * Deal with AUTH management packet types + * Deal with BEACON management packet types + * XXX furtle anything interesting out + * XXX Note that there are rules governing what beacons to read + * XXX see 8802 S7.2.3, S11.1.2.3 + * XXX is this actually useful? */ static void -ray_rx_mgt_auth(struct ray_softc *sc, struct mbuf *m0) +ray_rx_mgt_beacon(struct ray_softc *sc, struct mbuf *m0) { struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *); - ieee80211_mgt_auth_t auth = (u_int8_t *)(header+1); - size_t ccs, bufp; - int pktlen; + ieee80211_mgt_beacon_t beacon = (u_int8_t *)(header+1); + struct ieee80211_information elements; + + u_int64_t *timestamp; RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_MGT, ""); - RAY_MAP_CM(sc); - switch (IEEE80211_AUTH_ALGORITHM(auth)) { - - case IEEE80211_AUTH_ALG_OPEN: - RAY_RECERR(sc, "open system authentication request"); - if (IEEE80211_AUTH_TRANSACTION(auth) == 1) { + timestamp = (u_int64_t *)beacon; - /* XXX see sys/dev/awi/awk.c:awi_{recv|send}_auth */ +RAY_DPRINTF(sc, RAY_DBG_MGT, "timestamp\t0x%x", *timestamp); +RAY_DPRINTF(sc, RAY_DBG_MGT, "interval\t\t0x%x", IEEE80211_BEACON_INTERVAL(beacon)); +RAY_DPRINTF(sc, RAY_DBG_MGT, "capability\t0x%x", IEEE80211_BEACON_CAPABILITY(beacon)); - /* - * Send authentication response if possible. If - * we are out of CCSs we don't to anything, the - * other end will try again. - */ - if (ray_ccs_tx(sc, &ccs, &bufp)) { - return; - } -RAY_DPRINTF(sc, RAY_DBG_MGT, "bufp %x", bufp); + ray_rx_mgt_info(sc, m0, &elements); - bufp = ray_tx_wrhdr(sc, bufp, - IEEE80211_FC0_TYPE_MGT | - IEEE80211_FC0_SUBTYPE_AUTH, - IEEE80211_FC1_DIR_NODS, - header->i_addr2, - header->i_addr1, - header->i_addr3); +} - for (pktlen = 0; pktlen < 6; pktlen++) - SRAM_WRITE_1(sc, bufp+pktlen, 0); - pktlen += sizeof(struct ieee80211_frame); - SRAM_WRITE_1(sc, bufp+2, 2); +static void +ray_rx_mgt_info(struct ray_softc *sc, struct mbuf *m0, struct ieee80211_information *elements) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *); + ieee80211_mgt_beacon_t beacon = (u_int8_t *)(header+1); + ieee80211_mgt_beacon_t bp, be; + int len; -RAY_DPRINTF(sc, RAY_DBG_MGT, "dump start %x", bufp-pktlen+6); -RAY_DHEX8(sc, RAY_DBG_MGT, bufp-pktlen+6, pktlen, "AUTH MGT response to Open System request"); - (void)ray_tx_send(sc, ccs, pktlen, header->i_addr2); + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_MGT, ""); - } else if (IEEE80211_AUTH_TRANSACTION(auth) == 2) { + bp = beacon + 12; + be = mtod(m0, u_int8_t *) + m0->m_len; + + while (bp < be) { + len = *(bp + 1); + RAY_DPRINTF(sc, RAY_DBG_MGT, "id 0x%02x length %d", *bp, len); - /* - * XXX probably need a lot more than this - * XXX like initiating an auth sequence - */ - if (IEEE80211_AUTH_STATUS(auth) != - IEEE80211_STATUS_SUCCESS) - RAY_RECERR(sc, - "authentication failed with status %d", - IEEE80211_AUTH_STATUS(auth)); + switch (*bp) { + + case IEEE80211_ELEMID_SSID: + if (len > IEEE80211_NWID_LEN) { + RAY_RECERR(sc, "bad SSD length: %d from %6D", + len, header->i_addr2, ":"); + } + strncpy(elements->ssid, bp + 2, len); + elements->ssid[len] = 0; + RAY_DPRINTF(sc, RAY_DBG_MGT, + "beacon ssid %s", elements->ssid); + break; + + case IEEE80211_ELEMID_RATES: + RAY_DPRINTF(sc, RAY_DBG_MGT, "rates"); + break; + + case IEEE80211_ELEMID_FHPARMS: + elements->fh.dwell = bp[2] + (bp[3] << 8); + elements->fh.set = bp[4]; + elements->fh.pattern = bp[5]; + elements->fh.index = bp[6]; + RAY_DPRINTF(sc, RAY_DBG_MGT, + "fhparams dwell\t0x%04x", elements->fh.dwell); + RAY_DPRINTF(sc, RAY_DBG_MGT, + "fhparams set\t0x%02x", elements->fh.set); + RAY_DPRINTF(sc, RAY_DBG_MGT, + "fhparams pattern\t0x%02x", elements->fh.pattern); + RAY_DPRINTF(sc, RAY_DBG_MGT, + "fhparams index\t0x%02x", elements->fh.index); + break; + + case IEEE80211_ELEMID_DSPARMS: + RAY_RECERR(sc, "got direct sequence params!"); + break; + case IEEE80211_ELEMID_CFPARMS: + RAY_DPRINTF(sc, RAY_DBG_MGT, "cfparams"); + break; + + case IEEE80211_ELEMID_TIM: + elements->tim.count = bp[2]; + elements->tim.period = bp[3]; + elements->tim.bitctl = bp[4]; + RAY_DPRINTF(sc, RAY_DBG_MGT, + "tim count\t0x%02x", elements->tim.count); + RAY_DPRINTF(sc, RAY_DBG_MGT, + "tim period\t0x%02x", elements->tim.period); + RAY_DPRINTF(sc, RAY_DBG_MGT, + "tim bitctl\t0x%02x", elements->tim.bitctl); +#if RAY_DEBUG & RAY_DBG_MGT + { + int i; + for (i = 5; i < len + 1; i++) + RAY_DPRINTF(sc, RAY_DBG_MGT, + "tim pvt[%03d]\t0x%02x", i-5, bp[i]); + } +#endif (RAY_DEBUG & RAY_DBG_MGT) + break; + + case IEEE80211_ELEMID_IBSSPARMS: + elements->ibss.atim = bp[2] + (bp[3] << 8); + RAY_DPRINTF(sc, RAY_DBG_MGT, + "ibssparams atim\t0x%02x", elements->ibss.atim); + break; + + case IEEE80211_ELEMID_CHALLENGE: + RAY_DPRINTF(sc, RAY_DBG_MGT, "challenge"); + break; + + default: + RAY_RECERR(sc, "reserved MGT element id 0x%x", *bp); + ifp->if_ierrors++;break; } + bp += bp[1] + 2; + } +} + +/* + * Deal with AUTH management packet types + */ +static void +ray_rx_mgt_auth(struct ray_softc *sc, struct mbuf *m0) +{ + struct ieee80211_frame *header = mtod(m0, struct ieee80211_frame *); + ieee80211_mgt_auth_t auth = (u_int8_t *)(header+1); + + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_AUTH, ""); + + switch (IEEE80211_AUTH_ALGORITHM(auth)) { + + case IEEE80211_AUTH_ALG_OPEN: + RAY_DPRINTF(sc, RAY_DBG_AUTH, + "open system authentication sequence number %d", + IEEE80211_AUTH_TRANSACTION(auth)); + if (IEEE80211_AUTH_TRANSACTION(auth) == + IEEE80211_AUTH_OPEN_REQUEST) { + +/* XXX_AUTH use ray_init_auth_send */ + + } else if (IEEE80211_AUTH_TRANSACTION(auth) == + IEEE80211_AUTH_OPEN_RESPONSE) + ray_init_auth_done(sc, IEEE80211_AUTH_STATUS(auth)); break; case IEEE80211_AUTH_ALG_SHARED: - RAY_RECERR(sc, "shared key authentication request"); + RAY_RECERR(sc, + "shared key authentication sequence number %d", + IEEE80211_AUTH_TRANSACTION(auth)); break; default: @@ -2268,38 +2546,38 @@ ray_intr_ccs(struct ray_softc *sc, u_int8_t cmd, u_int8_t status, size_t ccs) case RAY_CMD_DOWNLOAD_PARAMS: RAY_DPRINTF(sc, RAY_DBG_COM, "START_PARAMS"); - ray_init_download_done(sc, ccs); + ray_init_download_done(sc, status, ccs); break; case RAY_CMD_UPDATE_PARAMS: RAY_DPRINTF(sc, RAY_DBG_COM, "UPDATE_PARAMS"); - ray_upparams_done(sc, ccs); + ray_upparams_done(sc, status, ccs); break; case RAY_CMD_REPORT_PARAMS: RAY_DPRINTF(sc, RAY_DBG_COM, "REPORT_PARAMS"); - ray_repparams_done(sc, ccs); + ray_repparams_done(sc, status, ccs); break; case RAY_CMD_UPDATE_MCAST: RAY_DPRINTF(sc, RAY_DBG_COM, "UPDATE_MCAST"); - ray_mcast_done(sc, ccs); + ray_mcast_done(sc, status, ccs); break; case RAY_CMD_START_NET: case RAY_CMD_JOIN_NET: RAY_DPRINTF(sc, RAY_DBG_COM, "START|JOIN_NET"); - ray_init_sj_done(sc, ccs); + ray_init_sj_done(sc, status, ccs); break; case RAY_CMD_TX_REQ: RAY_DPRINTF(sc, RAY_DBG_COM, "TX_REQ"); - ray_tx_done(sc, ccs); + ray_tx_done(sc, status, ccs); break; case RAY_CMD_START_ASSOC: RAY_DPRINTF(sc, RAY_DBG_COM, "START_ASSOC"); - ray_init_assoc_done(sc, ccs); + ray_init_assoc_done(sc, status, ccs); break; case RAY_CMD_UPDATE_APM: @@ -2345,12 +2623,12 @@ ray_intr_rcs(struct ray_softc *sc, u_int8_t cmd, size_t rcs) case RAY_ECMD_REJOIN_DONE: RAY_DPRINTF(sc, RAY_DBG_RX, "REJOIN_DONE"); - sc->sc_havenet = 1; /* XXX Should not be here but in function */ + sc->sc_c.np_havenet = 1; /* XXX Should not be here but in function */ break; case RAY_ECMD_ROAM_START: RAY_DPRINTF(sc, RAY_DBG_RX, "ROAM_START"); - sc->sc_havenet = 0; /* XXX Should not be here but in function */ + sc->sc_c.np_havenet = 0; /* XXX Should not be here but in function */ break; case RAY_ECMD_JAPAN_CALL_SIGNAL: @@ -2461,11 +2739,13 @@ ray_mcast(struct ray_softc *sc, struct ray_comq_entry *com) * Complete the multicast filter list update */ static void -ray_mcast_done(struct ray_softc *sc, size_t ccs) +ray_mcast_done(struct ray_softc *sc, u_int8_t status, size_t ccs) { - RAY_DPRINTF(sc, RAY_DBG_SUBR, ""); + RAY_DPRINTF(sc, RAY_DBG_SUBR | RAY_DBG_STARTJOIN, ""); RAY_COM_CHECK(sc, ccs); + RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */ + ray_com_ecf_done(sc); } @@ -2597,6 +2877,12 @@ ray_repparams_user(struct ray_softc *sc, struct ray_param_req *pr) case RAY_MIB_DES_PROMISC: *pr->r_data = sc->sc_d.np_promisc; break; + case RAY_MIB_CUR_FRAMING: + *pr->r_data = sc->sc_c.np_framing; + break; + case RAY_MIB_DES_FRAMING: + *pr->r_data = sc->sc_d.np_framing; + break; default: return (EINVAL); @@ -2653,7 +2939,7 @@ ray_repparams(struct ray_softc *sc, struct ray_comq_entry *com) * Complete the parameter reporting */ static void -ray_repparams_done(struct ray_softc *sc, size_t ccs) +ray_repparams_done(struct ray_softc *sc, u_int8_t status, size_t ccs) { struct ray_comq_entry *com; @@ -2661,6 +2947,8 @@ ray_repparams_done(struct ray_softc *sc, size_t ccs) RAY_MAP_CM(sc); RAY_COM_CHECK(sc, ccs); + RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */ + com = TAILQ_FIRST(&sc->sc_comq); com->c_pr->r_failcause = SRAM_READ_FIELD_1(sc, ccs, ray_cmd_report, c_failcause); @@ -2697,7 +2985,7 @@ ray_repstats_user(struct ray_softc *sc, struct ray_stats_req *sr) static int ray_upparams_user(struct ray_softc *sc, struct ray_param_req *pr) { - struct ray_comq_entry *com[3]; + struct ray_comq_entry *com[4]; int error, ncom, todo; #define RAY_UPP_SJ 0x1 #define RAY_UPP_PARAMS 0x2 @@ -2771,6 +3059,7 @@ ray_upparams_user(struct ray_softc *sc, struct ray_param_req *pr) } if (todo & RAY_UPP_SJ) { com[ncom++] = RAY_COM_MALLOC(ray_init_sj, 0); + com[ncom++] = RAY_COM_MALLOC(ray_init_auth, 0); com[ncom++] = RAY_COM_MALLOC(ray_init_assoc, 0); } @@ -2815,7 +3104,7 @@ ray_upparams(struct ray_softc *sc, struct ray_comq_entry *com) * Complete the parameter update, note that promisc finishes up here too */ static void -ray_upparams_done(struct ray_softc *sc, size_t ccs) +ray_upparams_done(struct ray_softc *sc, u_int8_t status, size_t ccs) { struct ray_comq_entry *com; @@ -2823,6 +3112,8 @@ ray_upparams_done(struct ray_softc *sc, size_t ccs) RAY_MAP_CM(sc); RAY_COM_CHECK(sc, ccs); + RAY_CCSERR(sc, status, if_oerrors); /* XXX error counter */ + com = TAILQ_FIRST(&sc->sc_comq); switch (SRAM_READ_FIELD_1(sc, ccs, ray_cmd_update, c_paramid)) { @@ -3038,7 +3329,7 @@ ray_com_ecf(struct ray_softc *sc, struct ray_comq_entry *com) RAY_MAP_CM(sc); while (!RAY_ECF_READY(sc)) { - DELAY(RAY_ECF_SPIN_DELAY); + DELAY(RAY_ECF_SPIN_DELAY); if (++i > RAY_ECF_SPIN_TRIES) RAY_PANIC(sc, "spun too long"); } @@ -3288,7 +3579,7 @@ ray_ccs_tx(struct ray_softc *sc, size_t *ccsp, size_t *bufpp) SRAM_WRITE_FIELD_2(sc, ccs, ray_cmd_tx, c_bufp, bufp); SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_tx_rate, sc->sc_c.np_def_txrate); - SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_apm_mode, 0); /* XXX_APM */ + SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_tx, c_apm_mode, 0); bufp += sizeof(struct ray_tx_phy_header); *ccsp = ccs; @@ -3344,7 +3635,7 @@ ray_res_alloc_am(struct ray_softc *sc) #if RAY_DEBUG & (RAY_DBG_CM | RAY_DBG_BOOTPARAM) { - u_long flags; + u_long flags; u_int32_t offset; CARD_GET_RES_FLAGS(device_get_parent(sc->dev), sc->dev, SYS_RES_MEMORY, sc->am_rid, &flags); |