[6319] | 1 | /** @file wlan_mac_common.c |
---|
| 2 | * @brief Common Code |
---|
| 3 | * |
---|
| 4 | * This contains code common to both CPU_LOW and CPU_HIGH. |
---|
| 5 | * |
---|
| 6 | * @copyright Copyright 2013-2019, Mango Communications. All rights reserved. |
---|
| 7 | * Distributed under the Mango Communications Reference Design License |
---|
| 8 | * See LICENSE.txt included in the design archive or |
---|
| 9 | * at http://mangocomm.com/802.11/license |
---|
| 10 | * |
---|
| 11 | * This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11) |
---|
| 12 | */ |
---|
| 13 | |
---|
| 14 | /***************************** Include Files *********************************/ |
---|
| 15 | |
---|
| 16 | #include "stdlib.h" |
---|
| 17 | #include "string.h" |
---|
| 18 | |
---|
| 19 | #include "xil_io.h" |
---|
| 20 | #include "xstatus.h" |
---|
| 21 | #include "xparameters.h" |
---|
| 22 | |
---|
| 23 | #include "wlan_platform_common.h" |
---|
| 24 | #include "wlan_mac_common.h" |
---|
| 25 | #include "wlan_mac_802_11_defs.h" |
---|
| 26 | |
---|
| 27 | /*********************** Global Variable Definitions *************************/ |
---|
| 28 | |
---|
| 29 | extern int __malloc_sbrk_base; ///< Internal malloc variable in .data |
---|
| 30 | extern int __malloc_trim_threshold; ///< Internal malloc variable in .data |
---|
| 31 | extern int __malloc_av_; ///< Internal malloc variable in .data |
---|
| 32 | |
---|
| 33 | |
---|
| 34 | /*************************** Variable Definitions ****************************/ |
---|
| 35 | |
---|
| 36 | static wlan_mac_hw_info_t mac_hw_info; |
---|
| 37 | |
---|
| 38 | |
---|
| 39 | /*************************** Functions Prototypes ****************************/ |
---|
| 40 | |
---|
| 41 | |
---|
| 42 | /******************************** Functions **********************************/ |
---|
| 43 | |
---|
| 44 | /** |
---|
| 45 | * @brief Initialize Malloc |
---|
| 46 | * |
---|
| 47 | * Dynamic memory allocation through malloc uses metadata in the data section |
---|
| 48 | * of the elf binary. This metadata is not reset upon software reset (i.e., when a |
---|
| 49 | * user presses the reset button on the hardware). This will cause failures on |
---|
| 50 | * subsequent boots because this metadata has not be reset back to its original |
---|
| 51 | * state at the first boot. |
---|
| 52 | * |
---|
| 53 | * This function explicitly overwrites the relevant pieces of the data section |
---|
| 54 | * with a good default state for malloc. The initial values of the variables |
---|
| 55 | * __malloc_sbrk_base, __malloc_trim_threshold, and __malloc_av__ can be found |
---|
| 56 | * here: https://github.com/Xilinx/newlib/blob/xsdk_14.4/newlib/libc/stdlib/mallocr.c |
---|
| 57 | * |
---|
| 58 | * @param None |
---|
| 59 | * @return None |
---|
| 60 | * |
---|
| 61 | * @note This function should be the first thing called after boot. If it is |
---|
| 62 | * called after other parts have the code have started dynamic memory access, |
---|
| 63 | * there will be unpredictable results on software reset. |
---|
| 64 | */ |
---|
| 65 | void wlan_mac_common_malloc_init(){ |
---|
| 66 | u32 i, val; |
---|
| 67 | u32* malloc_sbrk_base_ptr; |
---|
| 68 | u32* malloc_trim_threshold_ptr; |
---|
| 69 | u32* malloc_av_ptr; |
---|
| 70 | |
---|
| 71 | malloc_sbrk_base_ptr = (u32*)&__malloc_sbrk_base; |
---|
| 72 | malloc_trim_threshold_ptr = (u32*)&__malloc_trim_threshold; |
---|
| 73 | malloc_av_ptr = (u32*)&__malloc_av_; |
---|
| 74 | |
---|
| 75 | malloc_sbrk_base_ptr[0] = 0xFFFFFFFF; |
---|
| 76 | |
---|
| 77 | malloc_trim_threshold_ptr[0] = 0x00020000; |
---|
| 78 | |
---|
| 79 | malloc_av_ptr[0] = 0; |
---|
| 80 | malloc_av_ptr[1] = 0; |
---|
| 81 | |
---|
| 82 | val = 0; |
---|
| 83 | for(i=2; i<258; i+=2){ |
---|
| 84 | malloc_av_ptr[i] = (u32)((char*)(&malloc_av_ptr[2*val+2])) - 2*sizeof(size_t); |
---|
| 85 | malloc_av_ptr[i+1] = malloc_av_ptr[i]; |
---|
| 86 | val++; |
---|
| 87 | } |
---|
| 88 | } |
---|
| 89 | |
---|
| 90 | |
---|
| 91 | /*****************************************************************************/ |
---|
| 92 | /** |
---|
| 93 | * Null Callback |
---|
| 94 | * |
---|
| 95 | * This function will always return WLAN_SUCCESS and should be used to initialize |
---|
| 96 | * callbacks. All input parameters will be ignored. |
---|
| 97 | * |
---|
| 98 | * @param param - Void pointer for parameters |
---|
| 99 | * |
---|
| 100 | * @return int - Status: |
---|
| 101 | * WLAN_SUCCESS - Command completed successfully |
---|
| 102 | *****************************************************************************/ |
---|
| 103 | int wlan_null_callback(void* param) { |
---|
| 104 | return WLAN_SUCCESS; |
---|
| 105 | } |
---|
| 106 | |
---|
| 107 | |
---|
| 108 | |
---|
| 109 | /*****************************************************************************/ |
---|
| 110 | /** |
---|
| 111 | * Verify channel is supported |
---|
| 112 | * |
---|
| 113 | * @param channel - Channel to verify |
---|
| 114 | * |
---|
| 115 | * @return int - Channel supported? |
---|
| 116 | * WLAN_SUCCESS - Channel supported |
---|
| 117 | * WLAN_FAILURE - Channel not supported |
---|
| 118 | *****************************************************************************/ |
---|
| 119 | int wlan_verify_channel(u32 channel) { |
---|
| 120 | int return_value; |
---|
| 121 | |
---|
| 122 | // The 802.11 reference design allows a subset of 2.4 and 5 GHz channels |
---|
| 123 | // Channel number follows 802.11 conventions: |
---|
| 124 | // https://en.wikipedia.org/wiki/List_of_WLAN_channels |
---|
| 125 | // |
---|
| 126 | #if 1 |
---|
| 127 | switch (channel) { |
---|
| 128 | // 2.4GHz channels |
---|
| 129 | case 1: |
---|
| 130 | case 2: |
---|
| 131 | case 3: |
---|
| 132 | case 4: |
---|
| 133 | case 5: |
---|
| 134 | case 6: |
---|
| 135 | case 7: |
---|
| 136 | case 8: |
---|
| 137 | case 9: |
---|
| 138 | case 10: |
---|
| 139 | case 11: |
---|
| 140 | // 5GHz channels |
---|
| 141 | case 36: |
---|
| 142 | case 40: |
---|
| 143 | case 44: |
---|
| 144 | case 48: |
---|
| 145 | return_value = WLAN_SUCCESS; |
---|
| 146 | break; |
---|
| 147 | default: |
---|
| 148 | return_value = WLAN_FAILURE; |
---|
| 149 | break; |
---|
| 150 | } |
---|
| 151 | #else |
---|
| 152 | switch (channel) { |
---|
| 153 | // 2.4GHz channels |
---|
| 154 | case 1: |
---|
| 155 | case 2: |
---|
| 156 | case 3: |
---|
| 157 | case 4: |
---|
| 158 | case 5: |
---|
| 159 | case 6: |
---|
| 160 | case 7: |
---|
| 161 | case 8: |
---|
| 162 | case 9: |
---|
| 163 | case 10: |
---|
| 164 | case 11: |
---|
| 165 | // 5GHz channels |
---|
| 166 | case 36: // 5180 MHz |
---|
| 167 | case 38: // 5190 MHz |
---|
| 168 | case 40: // 5200 MHz |
---|
| 169 | case 44: // 5220 MHz |
---|
| 170 | case 46: // 5230 MHz |
---|
| 171 | case 48: // 5240 MHz |
---|
| 172 | case 52: // 5260 MHz |
---|
| 173 | case 54: // 5270 MHz |
---|
| 174 | case 56: // 5280 MHz |
---|
| 175 | case 60: // 5300 MHz |
---|
| 176 | case 62: // 5310 MHz |
---|
| 177 | case 64: // 5320 MHz |
---|
| 178 | case 100: // 5500 MHz |
---|
| 179 | case 102: // 5510 MHz |
---|
| 180 | case 104: // 5520 MHz |
---|
| 181 | case 108: // 5540 MHz |
---|
| 182 | case 110: // 5550 MHz |
---|
| 183 | case 112: // 5560 MHz |
---|
| 184 | case 116: // 5580 MHz |
---|
| 185 | case 118: // 5590 MHz |
---|
| 186 | case 120: // 5600 MHz |
---|
| 187 | case 124: // 5620 MHz |
---|
| 188 | case 126: // 5630 MHz |
---|
| 189 | case 128: // 5640 MHz |
---|
| 190 | case 132: // 5660 MHz |
---|
| 191 | case 134: // 5670 MHz |
---|
| 192 | case 136: // 5680 MHz |
---|
| 193 | case 140: // 5700 MHz |
---|
| 194 | case 142: // 5710 MHz |
---|
| 195 | case 144: // 5720 MHz |
---|
| 196 | case 149: // 5745 MHz |
---|
| 197 | case 151: // 5755 MHz |
---|
| 198 | case 153: // 5765 MHz |
---|
| 199 | case 157: // 5785 MHz |
---|
| 200 | case 159: // 5795 MHz |
---|
| 201 | case 161: // 5805 MHz |
---|
| 202 | case 165: // 5825 MHz |
---|
| 203 | case 172: // 5860 MHz |
---|
| 204 | case 174: // 5870 MHz |
---|
| 205 | case 175: // 5875 MHz |
---|
| 206 | case 176: // 5880 MHz |
---|
| 207 | case 177: // 5885 MHz |
---|
| 208 | case 178: // 5890 MHz |
---|
| 209 | return_value = WLAN_SUCCESS; |
---|
| 210 | break; |
---|
| 211 | default: |
---|
| 212 | xil_printf("ERROR (wlan_verify_channel): Channel %d invalid\n", channel); |
---|
| 213 | return_value = WLAN_FAILURE; |
---|
| 214 | break; |
---|
| 215 | } |
---|
| 216 | #endif |
---|
| 217 | |
---|
| 218 | return return_value; |
---|
| 219 | } |
---|
| 220 | |
---|
| 221 | |
---|
| 222 | /*****************************************************************************/ |
---|
| 223 | /** |
---|
| 224 | * Initialize the MAC Hardware Info |
---|
| 225 | * |
---|
| 226 | * This function will initialize the MAC hardware information structure for |
---|
| 227 | * the CPU based on information contained in the EEPROM and the wlan_exp_type |
---|
| 228 | * provided. This function should only be called after the EEPROM has been |
---|
| 229 | * initialized. |
---|
| 230 | * |
---|
| 231 | * @param None |
---|
| 232 | * |
---|
| 233 | *****************************************************************************/ |
---|
| 234 | void init_mac_hw_info() { |
---|
| 235 | mac_hw_info = wlan_platform_get_hw_info(); |
---|
| 236 | } |
---|
| 237 | |
---|
| 238 | time_hr_min_sec_t wlan_mac_time_to_hr_min_sec(u64 time) { |
---|
| 239 | time_hr_min_sec_t time_hr_min_sec; |
---|
| 240 | u64 time_sec; |
---|
| 241 | u32 remainder; |
---|
| 242 | |
---|
| 243 | time_sec = time / 1e6; |
---|
| 244 | remainder = time_sec % 3600; |
---|
| 245 | |
---|
| 246 | time_hr_min_sec.hr = time_sec / 3600; |
---|
| 247 | time_hr_min_sec.min = remainder / 60; |
---|
| 248 | time_hr_min_sec.sec = remainder % 60; |
---|
| 249 | |
---|
| 250 | return time_hr_min_sec; |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | /*****************************************************************************/ |
---|
| 254 | /** |
---|
| 255 | * Common Packet Contructors |
---|
| 256 | * |
---|
| 257 | * Control packets need to be created by both CPU_HIGH and CPU_LOW, so their |
---|
| 258 | * constructors are placed here in the common MAC framework. |
---|
| 259 | * |
---|
| 260 | *****************************************************************************/ |
---|
| 261 | int wlan_create_rts_frame(u8* pkt, |
---|
| 262 | u8* address_ra, |
---|
| 263 | u8* address_ta, |
---|
| 264 | u16 duration) { |
---|
| 265 | mac_header_80211_RTS* rts_header; |
---|
| 266 | |
---|
| 267 | if(pkt == NULL) return WLAN_FAILURE; |
---|
| 268 | |
---|
| 269 | rts_header = (mac_header_80211_RTS*)(pkt); |
---|
| 270 | |
---|
| 271 | rts_header->frame_control_1 = MAC_FRAME_CTRL1_SUBTYPE_RTS; |
---|
| 272 | rts_header->frame_control_2 = 0; |
---|
| 273 | rts_header->duration_id = duration; |
---|
| 274 | memcpy(rts_header->address_ra, address_ra, MAC_ADDR_LEN); |
---|
| 275 | memcpy(rts_header->address_ta, address_ta, MAC_ADDR_LEN); |
---|
| 276 | |
---|
| 277 | //Include FCS in packet size (MAC accounts for FCS, even though the PHY calculates it) |
---|
| 278 | return (sizeof(mac_header_80211_RTS)+WLAN_PHY_FCS_NBYTES); |
---|
| 279 | } |
---|
| 280 | |
---|
| 281 | int wlan_create_cts_frame(u8* pkt, |
---|
| 282 | u8* address_ra, |
---|
| 283 | u16 duration) { |
---|
| 284 | mac_header_80211_CTS* cts_header; |
---|
| 285 | |
---|
| 286 | if(pkt == NULL) return WLAN_FAILURE; |
---|
| 287 | |
---|
| 288 | cts_header = (mac_header_80211_CTS*)(pkt); |
---|
| 289 | |
---|
| 290 | cts_header->frame_control_1 = MAC_FRAME_CTRL1_SUBTYPE_CTS; |
---|
| 291 | cts_header->frame_control_2 = 0; |
---|
| 292 | cts_header->duration_id = duration; |
---|
| 293 | memcpy(cts_header->address_ra, address_ra, MAC_ADDR_LEN); |
---|
| 294 | |
---|
| 295 | //Include FCS in packet size (MAC accounts for FCS, even though the PHY calculates it) |
---|
| 296 | return (sizeof(mac_header_80211_CTS)+WLAN_PHY_FCS_NBYTES); |
---|
| 297 | } |
---|
| 298 | |
---|
| 299 | int wlan_create_ack_frame(void* pkt, |
---|
| 300 | u8* address_ra) { |
---|
| 301 | mac_header_80211_ACK* ack_header; |
---|
| 302 | |
---|
| 303 | if(pkt == NULL) return WLAN_FAILURE; |
---|
| 304 | |
---|
| 305 | ack_header = (mac_header_80211_ACK*)(pkt); |
---|
| 306 | |
---|
| 307 | ack_header->frame_control_1 = MAC_FRAME_CTRL1_SUBTYPE_ACK; |
---|
| 308 | ack_header->frame_control_2 = 0; |
---|
| 309 | ack_header->duration_id = 0; |
---|
| 310 | memcpy(ack_header->address_ra, address_ra, MAC_ADDR_LEN); |
---|
| 311 | |
---|
| 312 | //Include FCS in packet size (MAC accounts for FCS, even though the PHY calculates it) |
---|
| 313 | return (sizeof(mac_header_80211_ACK)+WLAN_PHY_FCS_NBYTES); |
---|
| 314 | } |
---|
| 315 | |
---|
| 316 | |
---|
| 317 | // Many Xilinx drivers use Xil_Assert to validate inputs |
---|
| 318 | // By default a failed assertion will halt the CPU quietly |
---|
| 319 | // This function can be assigned via Xil_AssertSetCallback() to print |
---|
| 320 | // the file/line number of a failing assertion before the CPU halts |
---|
| 321 | void wlan_assert_print(const char *FilenamePtr, int LineNumber) { |
---|
| 322 | xil_printf("ASSERT: File Name: %s ", FilenamePtr); |
---|
| 323 | xil_printf("Line Number: %d\r\n", LineNumber); |
---|
| 324 | } |
---|
| 325 | |
---|
| 326 | /*****************************************************************************/ |
---|
| 327 | /** |
---|
| 328 | * Get the MAC Hardware Info |
---|
| 329 | * |
---|
| 330 | * Return the MAC hardware information structure. This should only be used |
---|
| 331 | * after the structure is initialized. |
---|
| 332 | * |
---|
| 333 | * @return wlan_mac_hw_info_t * - Pointer to HW info structure |
---|
| 334 | * |
---|
| 335 | *****************************************************************************/ |
---|
| 336 | wlan_mac_hw_info_t* get_mac_hw_info() { return &mac_hw_info; } |
---|
| 337 | u8* get_mac_hw_addr_wlan() { return mac_hw_info.hw_addr_wlan; } |
---|
| 338 | u8* get_mac_hw_addr_wlan_exp() { return mac_hw_info.hw_addr_wlan_exp; } |
---|
| 339 | |
---|