int is_tx_buffer_empty(){ tx_frame_info* tx_mpdu = (tx_frame_info*) TX_PKT_BUF_TO_ADDR(tx_pkt_buf); if( ( tx_mpdu->state == TX_MPDU_STATE_TX_PENDING ) && ( is_cpu_low_ready() ) ){ return 1; } else { return 0; } }
inline void wlan_phy_set_tx_signal(u8 pkt_buf, u8 rate, u16 length) { Xil_Out32((u32*)(TX_PKT_BUF_TO_ADDR(pkt_buf) + PHY_TX_PKT_BUF_PHY_HDR_OFFSET), WLAN_TX_SIGNAL_CALC(rate, length)); return; }
/** * @brief Handles transmission of a wireless packet * * This function is called to transmit a new packet via the PHY. While the code does utilize the wlan_mac_dcf_hw core, * it bypasses any of the DCF-specific state in order to directly transmit the frame. This function should be called once per packet and will return * immediately following that transmission. It will not perform any DCF-like retransmissions. * * This function is called once per IPC_MBOX_TX_MPDU_READY message from CPU High. The IPC_MBOX_TX_MPDU_DONE message will be sent * back to CPU High when this function returns. * * @param u8 rx_pkt_buf * -Index of the Tx packet buffer containing the packet to transmit * @param u8 rate * -Index of PHY rate at which packet will be transmitted * @param u16 length * -Number of bytes in packet, including MAC header and FCS * @param wlan_mac_low_tx_details* low_tx_details * -Pointer to array of metadata entries to be created for each PHY transmission of this packet (eventually leading to TX_LOW log entries) * @return * -Transmission result */ int frame_transmit(u8 pkt_buf, u8 rate, u16 length, wlan_mac_low_tx_details* low_tx_details) { //This function manages the MAC_DCF_HW core. //return 0; //disable all Tx tx_frame_info* mpdu_info = (tx_frame_info*) (TX_PKT_BUF_TO_ADDR(pkt_buf)); u64 last_tx_timestamp; int curr_tx_pow; last_tx_timestamp = (u64)(mpdu_info->delay_accept) + (u64)(mpdu_info->timestamp_create); u32 mac_hw_status; //Write the SIGNAL field (interpreted by the PHY during Tx waveform generation) wlan_phy_set_tx_signal(pkt_buf, rate, length); unsigned char mpdu_tx_ant_mask = 0; switch(mpdu_info->params.phy.antenna_mode) { case TX_ANTMODE_SISO_ANTA: mpdu_tx_ant_mask |= 0x1; break; case TX_ANTMODE_SISO_ANTB: mpdu_tx_ant_mask |= 0x2; break; case TX_ANTMODE_SISO_ANTC: mpdu_tx_ant_mask |= 0x4; break; case TX_ANTMODE_SISO_ANTD: mpdu_tx_ant_mask |= 0x8; break; default: mpdu_tx_ant_mask = 0x1; break; } mpdu_info->num_tx_attempts = 1; curr_tx_pow = wlan_mac_low_dbm_to_gain_target(mpdu_info->params.phy.power); //wlan_mac_tx_ctrl_A_params(pktBuf, antMask, preTx_backoff_slots, preWait_postRxTimer1, preWait_postTxTimer1, postWait_postTxTimer2) wlan_mac_tx_ctrl_A_params(pkt_buf, mpdu_tx_ant_mask, 0, 0, 0, 0); //Set Tx Gains wlan_mac_tx_ctrl_A_gains(curr_tx_pow, curr_tx_pow, curr_tx_pow, curr_tx_pow); //Before we mess with any PHY state, we need to make sure it isn't actively //transmitting. For example, it may be sending an ACK when we get to this part of the code while(wlan_mac_get_status() & WLAN_MAC_STATUS_MASK_TX_PHY_ACTIVE){} //Submit the MPDU for transmission - this starts the MAC hardware's MPDU Tx state machine wlan_mac_tx_ctrl_A_start(1); wlan_mac_tx_ctrl_A_start(0); //Wait for the MPDU Tx to finish do{ if(low_tx_details != NULL){ low_tx_details[0].mpdu_phy_params.rate = mpdu_info->params.phy.rate; low_tx_details[0].mpdu_phy_params.power = mpdu_info->params.phy.power; low_tx_details[0].mpdu_phy_params.antenna_mode = mpdu_info->params.phy.antenna_mode; low_tx_details[0].chan_num = wlan_mac_low_get_active_channel(); low_tx_details[0].num_slots = 0; low_tx_details[0].cw = 0; } mac_hw_status = wlan_mac_get_status(); if( mac_hw_status & WLAN_MAC_STATUS_MASK_TX_A_DONE) { if( low_tx_details != NULL ){ low_tx_details[0].tx_start_delta = (u32)(get_tx_start_timestamp() - last_tx_timestamp); last_tx_timestamp = get_tx_start_timestamp(); } switch( mac_hw_status & WLAN_MAC_STATUS_MASK_TX_A_RESULT ){ case WLAN_MAC_STATUS_TX_A_RESULT_NONE: return 0; break; } } } while( mac_hw_status & WLAN_MAC_STATUS_MASK_TX_A_PENDING ); return -1; }
void wlan_mac_util_init( u32 type, u32 eth_dev_num ){ int Status; u32 i; u32 gpio_read; u32 queue_len; u64 timestamp; u32 log_size; tx_frame_info* tx_mpdu; // Initialize callbacks eth_rx_callback = (function_ptr_t)nullCallback; mpdu_rx_callback = (function_ptr_t)nullCallback; fcs_bad_rx_callback = (function_ptr_t)nullCallback; mpdu_tx_done_callback = (function_ptr_t)nullCallback; pb_u_callback = (function_ptr_t)nullCallback; pb_m_callback = (function_ptr_t)nullCallback; pb_d_callback = (function_ptr_t)nullCallback; uart_callback = (function_ptr_t)nullCallback; ipc_rx_callback = (function_ptr_t)nullCallback; check_queue_callback = (function_ptr_t)nullCallback; mpdu_tx_accept_callback = (function_ptr_t)nullCallback; wlan_mac_ipc_init(); for(i=0;i < NUM_TX_PKT_BUFS; i++){ tx_mpdu = (tx_frame_info*)TX_PKT_BUF_TO_ADDR(i); tx_mpdu->state = TX_MPDU_STATE_EMPTY; } tx_pkt_buf = 0; #ifdef _DEBUG_ xil_printf("locking tx_pkt_buf = %d\n", tx_pkt_buf); #endif if(lock_pkt_buf_tx(tx_pkt_buf) != PKT_BUF_MUTEX_SUCCESS){ warp_printf(PL_ERROR,"Error: unable to lock pkt_buf %d\n",tx_pkt_buf); } tx_mpdu = (tx_frame_info*)TX_PKT_BUF_TO_ADDR(tx_pkt_buf); tx_mpdu->state = TX_MPDU_STATE_TX_PENDING; //Initialize the central DMA (CDMA) driver XAxiCdma_Config *cdma_cfg_ptr; cdma_cfg_ptr = XAxiCdma_LookupConfig(XPAR_AXI_CDMA_0_DEVICE_ID); Status = XAxiCdma_CfgInitialize(&cdma_inst, cdma_cfg_ptr, cdma_cfg_ptr->BaseAddress); if (Status != XST_SUCCESS) { warp_printf(PL_ERROR,"Error initializing CDMA: %d\n", Status); } XAxiCdma_IntrDisable(&cdma_inst, XAXICDMA_XR_IRQ_ALL_MASK); Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID); gpio_timestamp_initialize(); if (Status != XST_SUCCESS) { warp_printf(PL_ERROR, "Error initializing GPIO\n"); return; } Status = XUartLite_Initialize(&UartLite, UARTLITE_DEVICE_ID); if (Status != XST_SUCCESS) { warp_printf(PL_ERROR, "Error initializing XUartLite\n"); return; } gpio_read = XGpio_DiscreteRead(&Gpio, GPIO_INPUT_CHANNEL); if(gpio_read&GPIO_MASK_DRAM_INIT_DONE){ xil_printf("DRAM SODIMM Detected\n"); if(memory_test()==0){ queue_dram_present(1); dram_present = 1; } else { queue_dram_present(0); dram_present = 0; } } else { queue_dram_present(0); dram_present = 0; timestamp = get_usec_timestamp(); while((get_usec_timestamp() - timestamp) < 100000){ if((XGpio_DiscreteRead(&Gpio, GPIO_INPUT_CHANNEL)&GPIO_MASK_DRAM_INIT_DONE)){ xil_printf("DRAM SODIMM Detected\n"); if(memory_test()==0){ queue_dram_present(1); dram_present = 1; } else { queue_dram_present(0); dram_present = 0; } break; } } } queue_len = queue_init(); if( dram_present ) { //The event_list lives in DRAM immediately following the queue payloads. if(MAX_EVENT_LOG == -1){ log_size = (DDR3_SIZE - queue_len); } else { log_size = min( (DDR3_SIZE - queue_len), MAX_EVENT_LOG ); } event_log_init( (void*)(DDR3_BASEADDR + queue_len), log_size ); } else { log_size = 0; } #ifdef USE_WARPNET_WLAN_EXP // Communicate the log size to WARPNet node_info_set_event_log_size( log_size ); #endif wlan_eth_init(); //Set direction of GPIO channels XGpio_SetDataDirection(&Gpio, GPIO_INPUT_CHANNEL, 0xFFFFFFFF); XGpio_SetDataDirection(&Gpio, GPIO_OUTPUT_CHANNEL, 0); Status = XTmrCtr_Initialize(&TimerCounterInst, TMRCTR_DEVICE_ID); if (Status != XST_SUCCESS) { xil_printf("XTmrCtr failed to initialize\n"); return; } //Set the handler for Timer XTmrCtr_SetHandler(&TimerCounterInst, timer_handler, &TimerCounterInst); //Enable interrupt of timer and auto-reload so it continues repeatedly XTmrCtr_SetOptions(&TimerCounterInst, TIMER_CNTR_FAST, XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION); XTmrCtr_SetOptions(&TimerCounterInst, TIMER_CNTR_SLOW, XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION); timer_running[TIMER_CNTR_FAST] = 0; timer_running[TIMER_CNTR_SLOW] = 0; // Get the type of node from the input parameter hw_info.type = type; hw_info.wn_exp_eth_device = eth_dev_num; #ifdef USE_WARPNET_WLAN_EXP // We cannot initialize WARPNet until after the lower CPU sends all the HW information to us through the IPC call warpnet_initialized = 0; #endif wlan_mac_ltg_sched_init(); }