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 | |
---|