source: ReferenceDesigns/w3_802.11/c/wlan_w3_high/w3_high.c

Last change on this file was 6319, checked in by chunter, 5 years ago

1.8.0 release wlan-mac-se

File size: 12.7 KB
Line 
1#include "wlan_mac_high_sw_config.h"
2
3#include "xil_cache.h"
4#include "wlan_platform_high.h"
5#include "w3_high.h"
6#include "w3_eth.h"
7#include "w3_uart.h"
8#include "w3_high_userio.h"
9#include "w3_userio_util.h"
10#include "w3_iic_eeprom.h"
11#include "w3_sw_intr.h"
12#include "w3_common.h"
13#include "wlan_platform_timer.h"
14#include "wlan_common_types.h"
15#include "wlan_platform_common.h"
16
17#include "wlan_mac_high.h"
18#include "wlan_mac_schedule.h"
19#include "wlan_exp_common.h"
20#include "wlan_exp_node.h"
21#include "wlan_exp_transport.h"
22#include "wlan_mac_queue.h"
23
24static const platform_high_dev_info_t w3_platform_high_dev_info = {
25        .aux_bram_baseaddr = AUX_BRAM_BASEADDR,
26        .aux_bram_size = AUX_BRAM_SIZE - PORTAL_ETH_BD_MEM_SIZE,
27        .dram_baseaddr = WLAN_EXP_ETH_BD_MEM_HIGHADDR + 1,
28        .dram_size = DRAM_SIZE - WLAN_EXP_ETH_BD_MEM_SIZE,
29        .cdma_dev_id = PLATFORM_DEV_ID_CDMA,
30        .mailbox_int_id = PLATFORM_INT_ID_MAILBOX,
31        .timer_dur_us = TIMER_DUR_US,
32};
33
34typedef struct _w3_node_info_t{
35    u64                      fpga_dna;                          // FPGA DNA value, unique ID per chip
36    s8                       wlan_max_tx_power_dbm;             // RF interface maximum transmit power
37    s8                       wlan_min_tx_power_dbm;             // RF interface minimum transmit power
38} __attribute__((__packed__)) _w3_node_info_t;
39static _w3_node_info_t w3_node_info;
40ASSERT_TYPE_SIZE(_w3_node_info_t, 10);
41
42int _init_wlan_exp_node_info();
43
44void wlan_platform_cpu_high_init() {
45
46    Xil_AssertSetCallback((Xil_AssertCallback)wlan_assert_print);
47
48    // Disable I and D cache
49    Xil_DCacheDisable();
50    Xil_ICacheDisable();
51
52    // Enable exceptions - exceptions *must* be enabled on MicroBlaze
53    //  to handle unaligned memory accesses
54    microblaze_enable_exceptions();
55
56    // Initialize HW platform
57    wlan_platform_common_init();
58
59    // Fill in node info struct
60    _init_wlan_exp_node_info();
61
62    return;
63
64}
65
66platform_high_dev_info_t wlan_platform_high_get_dev_info(){
67    return w3_platform_high_dev_info;
68}
69
70void wlan_platform_high_poll(){
71}
72
73int wlan_platform_high_init() {
74    int status;
75
76    status = wlan_platform_intc_init(PLATFORM_DEV_ID_INTC);
77
78    status |= wlan_timer_init(PLATFORM_DEV_ID_TIMER, TIMER_DUR_US*(TIMER_FREQ_HZ/1000000)); // 64 usec
79
80    status |= wlan_timer_setup_interrupt(PLATFORM_INT_ID_TIMER, wlan_mac_schedule_poll);
81
82
83    status |= w3_uart_init();
84    status |= w3_uart_setup_interrupt();
85
86    status |= w3_high_userio_init();
87    status |= w3_high_userio_setup_interrupt();
88
89    status |= w3_sw_intr_init();
90
91    // Initialize Ethernet in wlan_platform
92    status |= w3_wlan_platform_ethernet_init();
93
94    // Set stack protection addresses
95    // Set stack protection addresses
96    // Linker sets these variables at build time
97    extern int _stack_end; ///< Start of the stack (stack counts backwards)
98    extern int __stack; ///< End of the stack
99    mtshr(&__stack);
100    mtslr(&_stack_end);
101
102    return status;
103}
104
105void wlan_platform_free_queue_entry_notify(){
106#if WLAN_SW_CONFIG_ENABLE_ETH_BRIDGE
107    w3_wlan_platform_ethernet_free_queue_entry_notify();
108#endif
109}
110
111
112void wlan_platform_high_userio_disp_status(userio_disp_high_status_t status, int status_param){
113
114   static application_role_t application_role = APPLICATION_ROLE_UNKNOWN;
115
116   switch(status){
117
118       case USERIO_DISP_STATUS_IDENTIFY: {
119           blink_hex_display(25, 200000);
120       } break;
121
122       case USERIO_DISP_STATUS_APPLICATION_ROLE: {
123           application_role = (application_role_t)status_param;
124
125           if(application_role == APPLICATION_ROLE_AP){
126                // Set Periodic blinking of hex display (period of 500 with min of 2 and max of 400)
127                set_hex_pwm_period(500);
128                set_hex_pwm_min_max(2, 400);
129                enable_hex_pwm();
130           }
131       } break;
132
133       case USERIO_DISP_STATUS_MEMBER_LIST_UPDATE: {
134            if(application_role == APPLICATION_ROLE_AP){
135                write_hex_display_with_pwm((u8)status_param);
136            } else {
137                write_hex_display((u8)status_param);
138            }
139
140       } break;
141
142       case USERIO_DISP_STATUS_WLAN_EXP_CONFIGURE: {
143
144           if( status_param ){
145               set_hex_display_right_dp(1);
146           } else {
147               set_hex_display_right_dp(0);
148           }
149       } break;
150
151       case USERIO_DISP_STATUS_CPU_ERROR: {
152
153           u32 error_code = (u32)status_param;
154           if (status_param != WLAN_ERROR_CPU_STOP) {
155               // Print error message
156               xil_printf("\n\nERROR:  CPU is halting with error code: E%X\n\n", (error_code & 0xF));
157
158               // Set the error code on the hex display
159               set_hex_display_error_status(error_code & 0xF);
160
161               // Enter infinite loop blinking the hex display
162               blink_hex_display(0, 250000);
163            } else {
164                // Stop execution
165                while (1) {};
166            }
167
168       } break;
169
170       default:
171       break;
172   }
173
174
175   return;
176
177}
178
179#if WLAN_SW_CONFIG_ENABLE_WLAN_EXP
180int wlan_platform_wlan_exp_process_node_cmd(cmd_resp_hdr_t* cmd_hdr, eth_tx_queue_buffer_t* eth_tx_queue_buffer, u8* cmd_processed){
181
182    //
183    // IMPORTANT ENDIAN NOTES:
184    //     - command
185    //         - header - Already endian swapped by the framework (safe to access directly)
186    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the command)
187    //     - response
188    //         - header - Will be endian swapped by the framework (safe to write directly)
189    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the response)
190    //
191
192    u32 resp_sent = NO_RESP_SENT;
193    u32 cmd_id = CMD_TO_CMDID(cmd_hdr->cmd);
194
195    // Segment 0 length includes a fully formed command response header
196    //  because one was created with default values suitable for a responseless
197    //  acknowledgment.
198    cmd_resp_hdr_t* resp_hdr = (cmd_resp_hdr_t*)(eth_tx_queue_buffer->seg0
199                                                 + eth_tx_queue_buffer->seg0_len
200                                                 - sizeof(cmd_resp_hdr_t));
201
202    u32* cmd_args_32 = (u32*)((u8*)cmd_hdr + sizeof(cmd_resp_hdr_t));
203    u32* resp_args_32 = (u32*)((u8*)resp_hdr + sizeof(cmd_resp_hdr_t));
204    u32 resp_index = 0;
205
206    // NOTE: Response header cmd, length, and num_args fields have already been initialized.
207    //
208
209    *cmd_processed = 1;
210
211    switch(cmd_id){
212        default:
213            *cmd_processed = 0;
214        break;
215        //---------------------------------------------------------------------
216        case CMDID_DEV_EEPROM: {
217
218
219            // Read / Write values from / to EEPROM
220            //
221            // Write Message format:
222            //     cmd_args_32[0]      Command == CMD_PARAM_WRITE_VAL
223            //     cmd_args_32[1]      EEPROM (0 = ON_BOARD / 1 = FMC)
224            //     cmd_args_32[2]      Address
225            //     cmd_args_32[3]      Length (Number of u8 bytes to write)
226            //     cmd_args_32[4:]     Values to write (Length u32 values each containing a single byte to write)
227            // Response format:
228            //     resp_args_32[0]     Status
229            //
230            // Read Message format:
231            //     cmd_args_32[0]      Command == CMD_PARAM_READ_VAL
232            //     cmd_args_32[1]      EEPROM Device (1 = ON_BOARD / 0 = FMC)
233            //     cmd_args_32[2]      Address
234            //     cmd_args_32[3]      Length (number of u8 bytes to read)
235            // Response format:
236            //     resp_args_32[0]     Status
237            //     resp_args_32[1]     Length (Number of u8 bytes read)
238            //     resp_args_32[2:]    EEPROM values (Length u32 values each containing a single byte read)
239            //
240            #define EEPROM_BASEADDR                        XPAR_W3_IIC_EEPROM_ONBOARD_BASEADDR
241            #define FMC_EEPROM_BASEADDR                    XPAR_W3_IIC_EEPROM_FMC_BASEADDR
242
243            u32 eeprom_idx;
244            int eeprom_status;
245            u8 byte_to_write;
246            u32 status = CMD_PARAM_SUCCESS;
247            u32 msg_cmd = Xil_Ntohl(cmd_args_32[0]);
248            u32 eeprom_device = Xil_Ntohl(cmd_args_32[1]);
249            u32 eeprom_addr = (Xil_Ntohl(cmd_args_32[2]) & 0xFFFF);
250            u32 eeprom_length = Xil_Ntohl(cmd_args_32[3]);
251            u32 use_default_resp = WLAN_EXP_TRUE;
252            u32 eeprom_ba = EEPROM_BASEADDR;
253            u32 max_resp_len = wlan_exp_transport_get_max_pkt_words();
254
255            // Select EEPROM device
256            if (eeprom_device) {
257                eeprom_ba = EEPROM_BASEADDR;
258            } else {
259                #if FMC_EEPROM_BASEADDR
260                    eeprom_ba = FMC_EEPROM_BASEADDR;
261                #else
262                    wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "FMC EEPROM not supported\n");
263                    msg_cmd = CMD_PARAM_RSVD;
264                #endif
265            }
266
267            switch (msg_cmd) {
268                case CMD_PARAM_WRITE_VAL:
269                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Write EEPROM:\n");
270                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "  Addr: 0x%08x\n", eeprom_addr);
271                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "  Len:  %d\n", eeprom_length);
272
273                    // Don't bother if length is clearly bogus
274                    if(eeprom_length < max_resp_len) {
275                        for (eeprom_idx = 0; eeprom_idx < eeprom_length; eeprom_idx++) {
276                            // Endian swap payload and extract the byte to write
277                            byte_to_write = (Xil_Ntohl(cmd_args_32[eeprom_idx + 4]) & 0xFF);
278
279                            // Write the byte and break if there was an EEPROM failure
280                            eeprom_status = iic_eeprom_write_byte(eeprom_ba, (eeprom_addr + eeprom_idx), byte_to_write, XPAR_CPU_ID);
281
282                            if (eeprom_status == IIC_EEPROM_FAILURE) {
283                                wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "CMDID_DEV_EEPROM write failed at byte %d\n", eeprom_idx);
284                                status = CMD_PARAM_ERROR;
285                                break;
286                            }
287                        }
288                    } else {
289                        wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "CMDID_DEV_EEPROM write longer than %d bytes\n", max_resp_len);
290                        status = CMD_PARAM_ERROR;
291                    }
292                break;
293
294                case CMD_PARAM_READ_VAL:
295                    // There's a chicken and egg problem in this command trying to use the
296                    // wlan_exp_add_u32_resp_arg() utility. The first word, status, might
297                    // become CMD_PARAM_ERROR as we are well into reading bytes from the
298                    // EEPROM. To use the wlan_exp_add_u32_resp_arg() function, we need to
299                    // know the final value of the first word before writing any other words
300                    // to the response. We will simply leave the "old" resp_index method of
301                    // writing a response.
302                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Read EEPROM:\n");
303                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "  Addr: 0x%08x\n", eeprom_addr);
304                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "  Len:  %d\n", eeprom_length);
305
306                    if (eeprom_length < max_resp_len) {
307                        // Don't set the default response
308                        use_default_resp = WLAN_EXP_FALSE;
309
310                        for (eeprom_idx = 0; eeprom_idx < eeprom_length; eeprom_idx++) {
311                            // Read the byte and break if there was an EEPROM failure
312                            eeprom_status = iic_eeprom_read_byte(eeprom_ba, (eeprom_addr + eeprom_idx), XPAR_CPU_ID);
313
314                            if (eeprom_status == IIC_EEPROM_FAILURE) {
315                                wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "CMDID_DEV_EEPROM write failed at byte %d\n", eeprom_idx);
316                                status = CMD_PARAM_ERROR;
317                                break;
318                            }
319
320                            // Add the byte read and Endian swap the payload
321                            //     - This modified the output Ethernet packet but does not update the resp_index variable
322                            resp_args_32[resp_index + eeprom_idx + 2] = Xil_Htonl(eeprom_status & 0xFF);
323                        }
324
325                        // Add length argument to response
326                        resp_args_32[resp_index++] = Xil_Htonl(status);
327                        resp_args_32[resp_index++] = Xil_Htonl(eeprom_idx);
328                        resp_index        += eeprom_idx;                       // Update response index for all EEPROM bytes
329                        resp_hdr->length  += (resp_index * sizeof(resp_args_32));
330                        eth_tx_queue_buffer->seg0_len += (resp_index * sizeof(u32));
331                        resp_hdr->num_u32_args = resp_index;
332
333                    } else {
334                        wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "CMDID_DEV_EEPROM read longer than %d bytes\n", max_resp_len);
335                        status = CMD_PARAM_ERROR;
336                    }
337                break;
338
339                case CMD_PARAM_RSVD:
340                    status = CMD_PARAM_ERROR;
341                break;
342
343                default:
344                    wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
345                    status = CMD_PARAM_ERROR;
346                break;
347            }
348
349            if (use_default_resp) {
350                // Send default response
351                wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, status);
352            }
353
354        }
355
356        break;
357
358    }
359
360    return resp_sent;
361
362}
363#endif
364
365int wlan_platform_high_copy_info(u8* dest){
366    memcpy(dest, &w3_node_info, sizeof(_w3_node_info_t));
367    return sizeof(_w3_node_info_t);
368}
369
370int _init_wlan_exp_node_info(){
371
372    wlan_mac_hw_info_t hw_info = wlan_platform_get_hw_info();
373
374    xil_printf("Initializing node Serial Number : %s-%05d\n", hw_info.serial_number_prefix, hw_info.serial_number);
375
376    //FIXME: Did I get the endianness right on this?
377    w3_node_info.fpga_dna = (((u64)w3_eeprom_read_fpga_dna(EEPROM_BASEADDR, 1)) << 32) + (u64)w3_eeprom_read_fpga_dna(EEPROM_BASEADDR, 0);
378    w3_node_info.wlan_max_tx_power_dbm = TX_POWER_MAX_DBM;
379    w3_node_info.wlan_min_tx_power_dbm = TX_POWER_MIN_DBM;
380    return WLAN_SUCCESS;
381}
Note: See TracBrowser for help on using the repository browser.