523 | | {{{ |
524 | | #!c |
525 | | |
526 | | }}} |
527 | | |
528 | | ---- |
529 | | }}} |
| 526 | Next, we need to change the {{{frame_receive()}}} function of the to deal with two potential kinds of receptions: |
| 527 | |
| 528 | 1. If we are a STA, we could expect to receive a token offer from the AP. If we do, we should respond with a token response before the AP times out on the offer. After sending the token response, we know that we have entered a token reservation period so we should allow the transmission of new MPDUs and set the {{{reservation_ts_end}}} variable to represent the time when our token reservation period ends. |
| 529 | 2. If we are an AP, we could expect to receive a token response from other STAs. If we do, we need to let the {{{token_new_reservation()}}} context know that we did. Note in a previous change that {{{token_new_reservation()}}} actively looks for a {{{POLL_MAC_STATUS_TOKEN_OFFER_ACCEPTED}}} flag to be returned from the receive context. We should raise this flag. |
| 530 | |
| 531 | The following function is a drop-in replacement to the existing {{{frame_receive function}}} that implements the above behavior: |
| 532 | |
| 533 | {{{ |
| 534 | #!c |
| 535 | |
| 536 | u32 frame_receive(u8 rx_pkt_buf, phy_rx_details* phy_details){ |
| 537 | //This function is called after a good SIGNAL field is detected by either PHY (OFDM or DSSS) |
| 538 | //It is the responsibility of this function to wait until a sufficient number of bytes have been received |
| 539 | // before it can start to process those bytes. When this function is called the eventual checksum status is |
| 540 | // unknown. The packet contents can be provisionally processed (e.g. prepare an ACK for fast transmission), |
| 541 | // but post-reception actions must be conditioned on the eventual FCS status (good or bad). |
| 542 | // |
| 543 | // Note: The timing of this function is critical for correct operation of the 802.11 DCF. It is not |
| 544 | // safe to add large delays to this function (e.g. xil_printf or usleep) |
| 545 | // |
| 546 | //Two primary job responsibilities of this function: |
| 547 | // (1): Prepare outgoing ACK packets and instruct the MAC_DCF_HW core whether or not to send ACKs |
| 548 | // (2): Pass up MPDUs (FCS valid or invalid) to CPU_HIGH |
| 549 | |
| 550 | u8 unicast_to_me; |
| 551 | mac_header_80211* rx_header; |
| 552 | mac_frame_custom_token* rx_token_frame; |
| 553 | u8 ctrl_tx_gain; |
| 554 | u32 tx_length; |
| 555 | u32 return_value = 0; |
| 556 | u32 mac_hw_status; |
| 557 | wlan_ipc_msg ipc_msg_to_high_start; |
| 558 | ipc_token_new_reservation ipc_payload_start; |
| 559 | |
| 560 | ipc_msg_to_high_start.msg_id = IPC_MBOX_MSG_ID(IPC_MBOX_TOKEN_NEW_RESERVATION); |
| 561 | |
| 562 | if( (sizeof(u32)*(sizeof(ipc_token_new_reservation)/sizeof(u32))) == sizeof(ipc_token_new_reservation) ){ |
| 563 | ipc_msg_to_high_start.num_payload_words = (sizeof(ipc_token_new_reservation)/sizeof(u32)); |
| 564 | } else { |
| 565 | ipc_msg_to_high_start.num_payload_words = (sizeof(ipc_token_new_reservation)/sizeof(u32)) + 1; |
| 566 | } |
| 567 | |
| 568 | ipc_msg_to_high_start.payload_ptr = (u32*)(&ipc_payload_start); |
| 569 | |
| 570 | rx_frame_info* mpdu_info; |
| 571 | void* pkt_buf_addr = (void *)RX_PKT_BUF_TO_ADDR(rx_pkt_buf); |
| 572 | |
| 573 | mpdu_info = (rx_frame_info*)pkt_buf_addr; |
| 574 | |
| 575 | rx_header = (mac_header_80211*)((void*)(pkt_buf_addr + PHY_RX_PKT_BUF_MPDU_OFFSET)); |
| 576 | |
| 577 | //Wait until the PHY has written enough bytes so that the first address field can be processed |
| 578 | while(wlan_mac_get_last_byte_index() < MAC_HW_LASTBYTE_TOKEN){ |
| 579 | }; |
| 580 | |
| 581 | unicast_to_me = wlan_addr_eq(rx_header->address_1, eeprom_addr); |
| 582 | |
| 583 | if(unicast_to_me && (rx_header->frame_control_1 == MAC_FRAME_CTRL1_SUBTYPE_TOKEN_OFFER)){ |
| 584 | //Received a token offer |
| 585 | rx_token_frame = (mac_frame_custom_token*)rx_header; |
| 586 | |
| 587 | //Set up a Token Response |
| 588 | //wlan_mac_tx_ctrl_B_params(pktBuf, antMask, req_zeroNAV, preWait_postRxTimer1, preWait_postRxTimer2, postWait_postTxTimer1) |
| 589 | wlan_mac_tx_ctrl_B_params(TX_PKT_BUF_TOKEN, 0x1, 0, 1, 0, 0); |
| 590 | |
| 591 | //ACKs are transmitted with a nominal Tx power used for all control packets |
| 592 | ctrl_tx_gain = wlan_mac_low_dbm_to_gain_target(15); |
| 593 | wlan_mac_tx_ctrl_B_gains(ctrl_tx_gain, ctrl_tx_gain, ctrl_tx_gain, ctrl_tx_gain); |
| 594 | |
| 595 | //Construct the token response frame in the dedicated Tx pkt buf |
| 596 | tx_length = wlan_create_token_response_frame((void*)(TX_PKT_BUF_TO_ADDR(TX_PKT_BUF_TOKEN) + PHY_TX_PKT_BUF_MPDU_OFFSET), |
| 597 | rx_token_frame->address_ta, |
| 598 | eeprom_addr, |
| 599 | 0, |
| 600 | rx_token_frame->res_duration_usec); //TODO: Calculate appropriate duration |
| 601 | |
| 602 | |
| 603 | //Write the SIGNAL field for the ACK |
| 604 | wlan_phy_set_tx_signal(TX_PKT_BUF_TOKEN, WLAN_PHY_RATE_BPSK12, tx_length); |
| 605 | |
| 606 | mpdu_info->state = wlan_mac_dcf_hw_rx_finish(); |
| 607 | |
| 608 | if(mpdu_info->state == RX_MPDU_STATE_FCS_GOOD){ |
| 609 | |
| 610 | memcpy( ipc_payload_start.addr, rx_token_frame->address_ra, 6 ); |
| 611 | ipc_payload_start.res_duration = rx_token_frame->res_duration_usec; |
| 612 | ipc_mailbox_write_msg(&ipc_msg_to_high_start); |
| 613 | |
| 614 | wlan_mac_tx_ctrl_B_start(1); |
| 615 | wlan_mac_tx_ctrl_B_start(0); |
| 616 | |
| 617 | do{ |
| 618 | mac_hw_status = wlan_mac_get_status(); |
| 619 | |
| 620 | if( (mac_hw_status & WLAN_MAC_STATUS_MASK_TX_B_STATE) == WLAN_MAC_STATUS_TX_B_STATE_DO_TX ) { |
| 621 | break; |
| 622 | } |
| 623 | } while(mac_hw_status & WLAN_MAC_STATUS_MASK_TX_B_PENDING); |
| 624 | |
| 625 | //Since this is our reservation period, we are now allowed to transmit |
| 626 | in_reservation = 1; |
| 627 | reservation_ts_end = get_usec_timestamp() + ((u64)rx_token_frame->res_duration_usec); |
| 628 | wlan_mac_low_enable_new_mpdu_tx(); |
| 629 | } |
| 630 | } else if(unicast_to_me && (rx_header->frame_control_1 == MAC_FRAME_CTRL1_SUBTYPE_TOKEN_RESPONSE)) { |
| 631 | //Received a token offer |
| 632 | rx_token_frame = (mac_frame_custom_token*)rx_header; |
| 633 | |
| 634 | if(rx_token_frame->res_duration_usec != 0){ |
| 635 | mpdu_info->state = wlan_mac_dcf_hw_rx_finish(); |
| 636 | if(mpdu_info->state == RX_MPDU_STATE_FCS_GOOD){ |
| 637 | return_value |= POLL_MAC_STATUS_TOKEN_OFFER_ACCEPTED; |
| 638 | } |
| 639 | } |
| 640 | } else { |
| 641 | mpdu_info->state = wlan_mac_dcf_hw_rx_finish(); //Blocks until reception is complete |
| 642 | } |
| 643 | |
| 644 | mpdu_info->flags = 0; |
| 645 | mpdu_info->phy_details = *phy_details; |
| 646 | mpdu_info->channel = wlan_mac_low_get_active_channel(); |
| 647 | mpdu_info->timestamp = get_rx_start_timestamp(); |
| 648 | |
| 649 | |
| 650 | mpdu_info->ant_mode = wlan_phy_rx_get_active_rx_ant(); |
| 651 | |
| 652 | mpdu_info->rf_gain = wlan_phy_rx_get_agc_RFG(mpdu_info->ant_mode); |
| 653 | mpdu_info->bb_gain = wlan_phy_rx_get_agc_BBG(mpdu_info->ant_mode); |
| 654 | mpdu_info->rx_power = wlan_mac_low_calculate_rx_power(wlan_phy_rx_get_pkt_rssi(mpdu_info->ant_mode), wlan_phy_rx_get_agc_RFG(mpdu_info->ant_mode)); |
| 655 | |
| 656 | if(mpdu_info->state == RX_MPDU_STATE_FCS_GOOD){ |
| 657 | green_led_index = (green_led_index + 1) % NUM_LEDS; |
| 658 | userio_write_leds_green(USERIO_BASEADDR, (1<<green_led_index)); |
| 659 | } else { |
| 660 | red_led_index = (red_led_index + 1) % NUM_LEDS; |
| 661 | userio_write_leds_red(USERIO_BASEADDR, (1<<red_led_index)); |
| 662 | } |
| 663 | |
| 664 | //Unlock the pkt buf mutex before passing the packet up |
| 665 | // If this fails, something has gone horribly wrong |
| 666 | if(unlock_pkt_buf_rx(rx_pkt_buf) != PKT_BUF_MUTEX_SUCCESS){ |
| 667 | xil_printf("Error: unable to unlock RX pkt_buf %d\n", rx_pkt_buf); |
| 668 | wlan_mac_low_send_exception(EXC_MUTEX_RX_FAILURE); |
| 669 | } else { |
| 670 | wlan_mac_low_frame_ipc_send(); |
| 671 | //Find a free packet buffer and begin receiving packets there (blocks until free buf is found) |
| 672 | wlan_mac_low_lock_empty_rx_pkt_buf(); |
| 673 | } |
| 674 | |
| 675 | //Unblock the PHY post-Rx (no harm calling this if the PHY isn't actually blocked) |
| 676 | wlan_mac_dcf_hw_unblock_rx_phy(); |
| 677 | |
| 678 | return return_value; |
| 679 | |
| 680 | } |
| 681 | }}} |
| 682 | |
| 683 | ---- |
| 684 | |
| 685 | |