/* Maria project {{{ * * Copyright (C) 2007 Spidcom * * <<>> * * }}} */ /** * \file mac/pbproc/src/fsm_tx_data.c * \brief FSM TX data part. * \ingroup mac_pbproc */ #include "common/std.h" #include "inc/context.h" #include "inc/fc.h" #include "inc/fsm_top.h" #include "inc/fsm_handle_fc.h" #include "inc/prep_mpdu.h" #include "inc/pbproc.h" #include "inc/fsm_tx_data.h" void pbproc_ftda_init (pbproc_t *ctx) { dbg_assert (ctx); ctx->fsm.states[PBPROC_FSM_STATE_TX_WAIT_ACCESS_CONF].rx_fc_cb = pbproc_ftda__tx_wait_access_conf__rx_fc; ctx->fsm.states[PBPROC_FSM_STATE_TX_WAIT_ACCESS_CONF].access_cb = pbproc_ftda__tx_wait_access_conf__access; ctx->fsm.states[PBPROC_FSM_STATE_TX_WAIT_ACCESS_CONF].access_conf_cb = pbproc_ftda__tx_wait_access_conf__access_conf; ctx->fsm.states[PBPROC_FSM_STATE_TX_WAIT_SACKD].rx_fc_cb = pbproc_ftda__tx_wait_sackd__rx_fc; ctx->fsm.states[PBPROC_FSM_STATE_TX_WAIT_SACKD].access_cb = pbproc_ftda__tx_wait_sackd__access; ctx->fsm.states[PBPROC_FSM_STATE_TX_WAIT_TX_END].pbdma_cb = pbproc_ftda__tx_wait_tx_end__pbdma; ctx->fsm.states[PBPROC_FSM_STATE_TX_BURST].access_cb = pbproc_ftda__tx_burst__access; } void ARCH_ILRAM pbproc_ftda__handle (pbproc_t *ctx) { dbg_claim (ctx); if (PHY_FC_MODE_IS_HYBRID (ctx->prep_mpdu.fc_mode)) phy_tx_fc10 (ctx->phy, ctx->prep_mpdu.tx_date, ctx->prep_mpdu.fc10); phy_pbdma_start (ctx->phy, ctx->prep_mpdu.bypass_aes, ctx->prep_mpdu.nek, ctx->prep_mpdu.pb_nb_total, ctx->prep_mpdu.main_seg_nb, ctx->prep_mpdu.wack ? 0 : ctx->prep_mpdu.main_seg_nb, &ctx->prep_mpdu.head->phy_pb, NULL, false); if (ctx->prep_mpdu.mod == PHY_MOD_TM) phy_set_tonemap (ctx->phy, 0, ctx->prep_mpdu.tonemap); phy_tx_param (ctx->phy, ctx->prep_mpdu.fc_mode, false, ctx->prep_mpdu.mod, ctx->prep_mpdu.fecrate, ctx->prep_mpdu.pb_size, ctx->prep_mpdu.gil, 0); bool prp = ctx->access.prp && !ctx->prep_mpdu.rts_cts; phy_tx_frame (ctx->phy, ctx->prep_mpdu.tx_date, true, prp, ctx->prep_mpdu.fc_av.words); if (prp) { ca_access_vcs_restart (ctx->ca, ctx->prep_mpdu.tx_date, ctx->times[ctx->access.hybrid].eifs_tck, PBPROC_ANTICIP_TCK, true); } pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_TX_WAIT_ACCESS_CONF); } void ARCH_ILRAM pbproc_ftda__tx_wait_access_conf__rx_fc (pbproc_t *ctx, u32 rx_date, const pbproc_fc_t *fc_av) { dbg_claim (ctx); /* Update backoff. */ pbproc_backoff_lost (ctx); /* Handle FC. */ pbproc_fhfc_handle_fc (ctx, rx_date, fc_av); /* Now, we have time, cancel transmission. */ pbproc_prep_mpdu_cancel (ctx); } void ARCH_ILRAM pbproc_ftda__tx_wait_access_conf__access (pbproc_t *ctx) { dbg_claim (ctx); pbproc_prep_mpdu_cancel (ctx); pbproc_ftop__idle__access (ctx); } void ARCH_ILRAM pbproc_ftda__tx_wait_access_conf__access_conf (pbproc_t *ctx) { dbg_claim (ctx); /* Start DMA. */ phy_tx_prepare (ctx->phy); /* Chain remaining PB. */ pbproc_prep_mpdu_chain (ctx); if (ctx->prep_mpdu.burst) { /* Burst. */ phy_pbdma_update (ctx->phy, ctx->prep_mpdu.main_seg_nb, 0); ca_access_program (ctx->ca, ctx->prep_mpdu.tx_date + ctx->prep_mpdu.flp_tck, PBPROC_ANTICIP_TCK); pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_TX_BURST); } else { if (ctx->prep_mpdu.wack) { /* With ACK. */ phy_pbdma_update (ctx->phy, ctx->prep_mpdu.main_seg_nb, 0); ca_backoff_deferred (ctx->ca, phy_access_backoff_slot_count (ctx->phy) - 2); ca_access_vcs_restart (ctx->ca, ctx->prep_mpdu.tx_date + ctx->prep_mpdu.flp_tck, ctx->times[ctx->access.hybrid].eifs_tck, PBPROC_ANTICIP_TCK, true); phy_rx_activate (ctx->phy, false, ctx->prep_mpdu.tx_date + ctx->prep_mpdu.flp_tck, true); pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_TX_WAIT_SACKD); } else { /* Without ACK. */ phy_pbdma_update (ctx->phy, ctx->prep_mpdu.main_seg_nb, ctx->prep_mpdu.pb_nb_total); ca_access_hold (ctx->ca); pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_TX_WAIT_TX_END); } } } void ARCH_ILRAM pbproc_ftda__tx_wait_sackd__rx_fc (pbproc_t *ctx, u32 rx_date, const pbproc_fc_t *fc_av) { pbproc_times_t *times; dbg_claim (ctx); times = &ctx->times[ctx->access.hybrid]; pbproc_prep_mpdu_t *prep = &ctx->prep_mpdu; /* Is it our SACK. */ if (fc_av && fc_av->generic.dt_av == PBPROC_FC_DT_SACK && fc_av->generic.access == false && fc_av->generic.snid == ctx->alloc.snid && fc_av->sack.dtei == prep->stei && less_mod2p32 (rx_date, ctx->prep_mpdu.tx_date + ctx->prep_mpdu.flp_tck + MAC_TOLERANCE_TCK)) { phy_rx_prepare_short (ctx->phy); /* Set MFS FSM response. */ pbproc_prep_mpdu_fsm_response (ctx, fc_av->sack.mfs_rsp_data, fc_av->sack.mfs_rsp_mgmt); /* Handle SACKD. */ if (fc_av->sack.sackt0 == PBPROC_FC_SACKT_MIXED) { pbproc_prep_mpdu_ack_bitmap ( ctx, fc_av->sack.sacki, 0, PBPROC_FC_SACK_SACKI_BITS - (MAC_LID_IS_PLID (prep->main_mfs->common.lid) ? 4 : 0)); } else if (fc_av->sack.sackt0 == PBPROC_FC_SACKT_MIXED_COMPRESSED) { u32 si[3]; si[0] = fc_av->sack.sacki[0]; si[1] = fc_av->sack.sacki[1]; si[2] = fc_av->sack.sacki_last; pbproc_prep_mpdu_ack_encoded ( ctx, si, PBPROC_FC_SACK_SACKI_BITS - (MAC_LID_IS_PLID (prep->main_mfs->common.lid) ? 4 : 0)); } else if (fc_av->sack.sackt0 == PBPROC_FC_SACKT_NOT_RECEIVED) { pbproc_prep_mpdu_cancel (ctx); } else { uint sacki = fc_av->sack.sacki[0] & 0xf; if (sacki == PBPROC_FC_SACKI_UNIFORM_ALL_OK) pbproc_prep_mpdu_ack_all (ctx); else pbproc_prep_mpdu_cancel (ctx); } /* Next. */ if (!ctx->access.cfp) { ca_backoff_success (ctx->ca); ca_access_vcs_restart (ctx->ca, rx_date, times->pre_fcs_tck + MAC_CIFS_TCK, PBPROC_ANTICIP_TCK, false); pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE); } else { //handle_access (); } } else { /* Not our SACK, may contain our SACKD. */ #if 0 if (our sackd) { if (!ctx->access.cfp) ca_backoff_success (ctx->ca); } else #endif { pbproc_prep_mpdu_cancel (ctx); ctx->stats.data_fail++; } pbproc_fhfc_handle_fc (ctx, rx_date, fc_av); } } void ARCH_ILRAM pbproc_ftda__tx_wait_sackd__access (pbproc_t *ctx) { dbg_claim (ctx); pbproc_prep_mpdu_cancel (ctx); ctx->stats.data_fail++; pbproc_ftop__idle__access (ctx); } void ARCH_ILRAM pbproc_ftda__tx_wait_tx_end__pbdma (pbproc_t *ctx) { pbproc_times_t *times; dbg_claim (ctx); times = &ctx->times[ctx->access.hybrid]; pbproc_prep_mpdu_ack_all (ctx); ca_backoff_success (ctx->ca); uint sack_tck = !ctx->access.mfs->beacon ? times->pre_fcs_tck + MAC_CIFS_TCK : 0; ca_access_vcs_restart (ctx->ca, ctx->prep_mpdu.tx_date + ctx->prep_mpdu.flp_tck, sack_tck, PBPROC_ANTICIP_TCK, false); pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE); } void ARCH_ILRAM pbproc_ftda__tx_burst__access (pbproc_t *ctx) { dbg_claim (ctx); // TODO pbproc_prep_mpdu_burst_next (ctx); pbproc_ftda__handle (ctx); }