[6319] | 1 | #include "xmbox.h" |
---|
| 2 | |
---|
| 3 | #include "wlan_mac_common.h" |
---|
| 4 | #include "wlan_mac_high.h" |
---|
| 5 | #include "wlan_mac_high_mailbox_util.h" |
---|
| 6 | #include "wlan_mac_mailbox_util.h" |
---|
| 7 | #include "wlan_platform_common.h" |
---|
| 8 | #include "wlan_platform_high.h" |
---|
| 9 | #include "wlan_mac_schedule.h" |
---|
| 10 | |
---|
| 11 | |
---|
| 12 | #define MAILBOX_RIT 0 /* mailbox receive interrupt threshold */ |
---|
| 13 | #define MAILBOX_SIT 0 /* mailbox send interrupt threshold */ |
---|
| 14 | |
---|
| 15 | static XMbox* xmbox_ptr; |
---|
| 16 | static platform_common_dev_info_t platform_common_dev_info; |
---|
| 17 | static platform_high_dev_info_t platform_high_dev_info; |
---|
| 18 | |
---|
| 19 | // IPC variables |
---|
| 20 | static wlan_ipc_msg_t ipc_msg_from_low; ///< IPC message from lower-level |
---|
| 21 | static u32 ipc_msg_from_low_payload[MAILBOX_MSG_MAX_NUM_WORDS]; ///< Buffer space for IPC message from lower-level |
---|
| 22 | |
---|
| 23 | void _mailbox_rx_watchdog(u32 timer_id); |
---|
| 24 | |
---|
| 25 | void wlan_mac_high_init_mailbox(){ |
---|
| 26 | |
---|
| 27 | xmbox_ptr = init_mailbox(); |
---|
| 28 | |
---|
| 29 | //Create IPC message to receive into |
---|
| 30 | ipc_msg_from_low.payload_ptr = &(ipc_msg_from_low_payload[0]); |
---|
| 31 | |
---|
| 32 | platform_common_dev_info = wlan_platform_common_get_dev_info(); |
---|
| 33 | platform_high_dev_info = wlan_platform_high_get_dev_info(); |
---|
| 34 | } |
---|
| 35 | |
---|
| 36 | /** |
---|
| 37 | * @brief WLAN MAC IPC receive |
---|
| 38 | * |
---|
| 39 | * IPC receive function that will poll the mailbox for as many messages as are |
---|
| 40 | * available and then call the CPU high IPC processing function on each message |
---|
| 41 | * |
---|
| 42 | * @param None |
---|
| 43 | * @return None |
---|
| 44 | */ |
---|
| 45 | void wlan_mac_high_ipc_rx(){ |
---|
| 46 | while (read_mailbox_msg(&ipc_msg_from_low) == IPC_MBOX_SUCCESS) { |
---|
| 47 | wlan_mac_high_process_ipc_msg(&ipc_msg_from_low, ipc_msg_from_low_payload); |
---|
| 48 | } |
---|
| 49 | } |
---|
| 50 | |
---|
| 51 | /*****************************************************************************/ |
---|
| 52 | /** |
---|
| 53 | * Setup mailbox interrupt |
---|
| 54 | * |
---|
| 55 | * @return int - Status: |
---|
| 56 | * WLAN_SUCCESS - Command completed successfully |
---|
| 57 | * WLAN_FAILURE - Command failed |
---|
| 58 | *****************************************************************************/ |
---|
| 59 | int setup_mailbox_interrupt() { |
---|
| 60 | int status; |
---|
| 61 | |
---|
| 62 | // Set Send / Receive threshold for interrupts |
---|
| 63 | XMbox_SetSendThreshold(xmbox_ptr, MAILBOX_SIT); |
---|
| 64 | XMbox_SetReceiveThreshold(xmbox_ptr, MAILBOX_RIT); |
---|
| 65 | |
---|
| 66 | // Connect interrupt handler |
---|
| 67 | status = wlan_platform_interrupt_connect(platform_high_dev_info.mailbox_int_id, (wlan_intr_handler_t)mailbox_int_handler, xmbox_ptr); |
---|
| 68 | |
---|
| 69 | if (status != WLAN_SUCCESS) { |
---|
| 70 | return WLAN_FAILURE; |
---|
| 71 | } |
---|
| 72 | |
---|
| 73 | // Enable interrupt |
---|
| 74 | XMbox_SetInterruptEnable(xmbox_ptr, XMB_IX_RTA); |
---|
| 75 | wlan_platform_interrupt_enable(platform_high_dev_info.mailbox_int_id); |
---|
| 76 | |
---|
| 77 | // Enable watchdog - checks for (unlikely but not impossible) mailbox messages received without |
---|
| 78 | // interrupt assertion |
---|
| 79 | wlan_mac_schedule_add_event(SCHEDULE_ID_COARSE, 200000, SCHEDULE_REPEAT_FOREVER, (void*)_mailbox_rx_watchdog); |
---|
| 80 | |
---|
| 81 | return WLAN_SUCCESS; |
---|
| 82 | } |
---|
| 83 | |
---|
| 84 | |
---|
| 85 | /*****************************************************************************/ |
---|
| 86 | /** |
---|
| 87 | * Mailbox interrupt handler |
---|
| 88 | * |
---|
| 89 | * @param callback_ref - Callback reference (set by interrupt framework) |
---|
| 90 | * |
---|
| 91 | *****************************************************************************/ |
---|
| 92 | void mailbox_int_handler(void* callback_ref){ |
---|
| 93 | u32 mask; |
---|
| 94 | XMbox* mbox_ptr = (XMbox *)callback_ref; |
---|
| 95 | |
---|
| 96 | #ifdef _ISR_PERF_MON_EN_ |
---|
| 97 | wlan_mac_set_dbg_hdr_out(ISR_PERF_MON_GPIO_MASK); |
---|
| 98 | #endif |
---|
| 99 | |
---|
| 100 | // First, we raise the receive threshold to its maximum value. The argument to the function |
---|
| 101 | // is a u32, but only the lower log2(FIFO Depth) bits are used |
---|
| 102 | XMbox_SetReceiveThreshold(xmbox_ptr, 0xFFFFFFFF); |
---|
| 103 | |
---|
| 104 | // Get the interrupt status |
---|
| 105 | mask = XMbox_GetInterruptStatus(mbox_ptr); |
---|
| 106 | |
---|
| 107 | // If this is a receive interrupt, then call the callback function |
---|
| 108 | if (mask & XMB_IX_RTA) { |
---|
| 109 | wlan_mac_high_ipc_rx(); |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | // It is technically possible that the mailbox could become full and |
---|
| 113 | // abandoned if the FIFO transitions from empty to completely full |
---|
| 114 | // at this part of the code before the following XMbox_ClearInterrupt |
---|
| 115 | // call. Under normal circumstanced, this is impossible. However, if |
---|
| 116 | // the debugger were to pause operation of the processor at this point, |
---|
| 117 | // it is conceivable that the bug could be exercised. The fix for this |
---|
| 118 | // event is the periodic call to the _mailbox_rx_watchdog() function. |
---|
| 119 | |
---|
| 120 | // Clear the interrupt |
---|
| 121 | // - Since only the XMB_IX_RTA interrupt was enabled in setup_mailbox_interrupt() |
---|
| 122 | // that is the only interrupt that will ever need to be cleared |
---|
| 123 | XMbox_ClearInterrupt(mbox_ptr, XMB_IX_RTA); |
---|
| 124 | |
---|
| 125 | // Drop the receive threshold to its correct value. The purpose of this is to avoid a race condition |
---|
| 126 | // that could occur if a reception occurs in between the call to wlan_mac_high_ipc_rx() and XMbox_ClearInterrupt(). |
---|
| 127 | // By lowering the threshold, we will force another interrupt in that scenario. |
---|
| 128 | XMbox_SetReceiveThreshold(xmbox_ptr, MAILBOX_RIT); |
---|
| 129 | |
---|
| 130 | #ifdef _ISR_PERF_MON_EN_ |
---|
| 131 | wlan_mac_clear_dbg_hdr_out(ISR_PERF_MON_GPIO_MASK); |
---|
| 132 | #endif |
---|
| 133 | } |
---|
| 134 | |
---|
| 135 | |
---|
| 136 | void _mailbox_rx_watchdog(u32 timer_id){ |
---|
| 137 | wlan_mac_high_ipc_rx(); |
---|
| 138 | } |
---|