1 /** @file wifi-sdio.c
2 *
3 * @brief This file provides WLAN Card related API
4 *
5 * Copyright 2008-2024 NXP
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
11 #include <mlan_api.h>
12
13 #include <mlan_sdio_api.h>
14
15 #if (CONFIG_XZ_DECOMPRESSION)
16 #include <xz.h>
17 #include <decompress.h>
18 #endif /* CONFIG_XZ_DECOMPRESSION */
19
20 /* Additional WMSDK header files */
21 #include <wmerrno.h>
22 #include <osa.h>
23 #include <wm_utils.h>
24 #include <mlan_fw.h>
25 #include "wifi-sdio.h"
26 #include "wifi-internal.h"
27 #include "sdio.h"
28 #include "firmware_dnld.h"
29 #include "fwdnld_sdio.h"
30
31 #define SDIO_COMMAND_RESPONSE_WAIT_MS 20000
32
33 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
34 SDK_ALIGN(uint8_t rx_bufs[SDIO_MP_AGGR_DEF_PKT_LIMIT][2 * DATA_BUFFER_SIZE], BOARD_SDMMC_DATA_BUFFER_ALIGN_SIZE);
35
36 static size_t num_sg = 0;
37 #endif
38
39 /* Buffer pointers to point to command and, command response buffer */
40 static uint8_t ctrl_cmd_buf[WIFI_FW_CMDBUF_SIZE];
41 #if CONFIG_FW_VDLL
42 static uint8_t vdll_cmd_buf[WIFI_FW_CMDBUF_SIZE] = {0};
43 #endif
44 static int seqnum;
45 // static int pm_handle;
46
47 /*
48 * Used to authorize the SDIO interrupt handler to accept the incoming
49 * packet from the SDIO interface. If this flag is set a semaphore is
50 * signalled.
51 */
52 bool g_txrx_flag;
53
54 int mlan_subsys_init(void);
55 int mlan_subsys_deinit(void);
56 void set_ioport_inmlan(t_u32 port);
57
58 static t_u8 txportno;
59
60 static t_u32 last_cmd_sent, fw_init_cfg;
61
62 OSA_MUTEX_HANDLE_DEFINE(txrx_mutex);
63 #if CONFIG_WIFI_IND_RESET
64 OSA_MUTEX_HANDLE_DEFINE(ind_reset_mutex);
65 #endif
66 OSA_SEMAPHORE_HANDLE_DEFINE(sdio_command_resp_sem);
67
68 #if CONFIG_TX_RX_ZERO_COPY
69 extern void net_tx_zerocopy_process_cb(void *destAddr, void *srcAddr, uint32_t len);
70 #endif
71
72 static struct
73 {
74 /* Where the cmdresp/event should be dispached depends on its value */
75 /* int special; */
76 /* Default queue where the cmdresp/events will be sent */
77 osa_msgq_handle_t event_queue;
78 #if CONFIG_P2P
79 /* Special queue on which only cmdresp will be sent based on
80 * value in special */
81 osa_msgq_handle_t special_queue;
82 #endif /* CONFIG_P2P */
83 int (*wifi_low_level_input)(const uint8_t interface, const uint8_t *buffer, const uint16_t len);
84 } bus;
85
86 /* fixme: This structure is not present in mlan and can be removed later */
87 typedef MLAN_PACK_START struct
88 {
89 t_u16 size;
90 t_u16 pkttype;
91 HostCmd_DS_COMMAND hostcmd;
92 } MLAN_PACK_END SDIOPkt;
93
94 static SDIOPkt *sdiopkt = (SDIOPkt *)outbuf;
95
96 void wrapper_wlan_cmd_11n_cfg(HostCmd_DS_COMMAND *cmd);
97
98 static uint32_t dev_value1 = -1;
99 uint8_t dev_mac_addr[MLAN_MAC_ADDR_LENGTH];
100 uint8_t dev_mac_addr_uap[MLAN_MAC_ADDR_LENGTH];
101 static uint8_t dev_fw_ver_ext[MLAN_MAX_VER_STR_LEN];
102
wifi_send_fw_data(t_u8 * data,t_u32 txlen)103 static mlan_status wifi_send_fw_data(t_u8 *data, t_u32 txlen)
104 {
105 t_u32 tx_blocks = 0, buflen = 0;
106 uint32_t resp;
107 bool ret;
108 #if CONFIG_WIFI_FW_DEBUG
109 int ret_cb;
110 #endif
111
112 if (data == NULL || txlen == 0)
113 return MLAN_STATUS_FAILURE;
114
115 w_pkt_d("Data TX SIG: Driver=>FW, len %d", txlen);
116
117 calculate_sdio_write_params(txlen, &tx_blocks, &buflen);
118
119 #if CONFIG_WIFI_IO_DEBUG
120 (void)PRINTF("%s: txportno = %d mlan_adap->mp_wr_bitmap: %x\n\r", __func__, txportno, mlan_adap->mp_wr_bitmap);
121 #endif /* CONFIG_WIFI_IO_DEBUG */
122 /* Check if the port is available */
123 if (!((1U << txportno) & mlan_adap->mp_wr_bitmap))
124 {
125 /*
126 * fixme: This condition is triggered in legacy as well as
127 * this new code. Check this out later.
128 */
129 #if CONFIG_WIFI_IO_DEBUG
130 wifi_io_e(
131 "txportno out of sync txportno "
132 "= (%d) mp_wr_bitmap = (0x%x)",
133 txportno, mlan_adap->mp_wr_bitmap);
134 #endif /* CONFIG_WIFI_IO_DEBUG */
135 return MLAN_STATUS_RESOURCE;
136 }
137 else
138 {
139 /* Mark the port number we will use */
140 mlan_adap->mp_wr_bitmap &= ~(1U << txportno);
141 }
142
143 /* send CMD53 */
144 ret = sdio_drv_write(mlan_adap->ioport + txportno, 1, tx_blocks, buflen, data, &resp);
145
146 txportno++;
147 if (txportno == mlan_adap->mp_end_port)
148 {
149 #if defined(SD8801)
150 txportno = 1;
151 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
152 txportno = 0;
153 #endif
154 }
155
156 if (ret == false)
157 {
158 wifi_io_e("sdio_drv_write failed (%d)", ret);
159 #if CONFIG_WIFI_FW_DEBUG
160 wifi_sdio_reg_dbg(NULL);
161 if (wm_wifi.wifi_usb_mount_cb != NULL)
162 {
163 ret_cb = wm_wifi.wifi_usb_mount_cb();
164 if (ret_cb == WM_SUCCESS)
165 wifi_dump_firmware_info(NULL);
166 else
167 wifi_e("USB mounting failed");
168 }
169 else
170 wifi_e("USB mount callback is not registered");
171 #endif
172 return MLAN_STATUS_RESOURCE;
173 }
174 return MLAN_STATUS_SUCCESS;
175 }
176
wifi_sdio_lock(void)177 int wifi_sdio_lock(void)
178 {
179 return OSA_MutexLock((osa_mutex_handle_t)txrx_mutex, osaWaitForever_c);
180 }
181
wifi_sdio_unlock(void)182 void wifi_sdio_unlock(void)
183 {
184 (void)OSA_MutexUnlock((osa_mutex_handle_t)txrx_mutex);
185 }
186
187 #if CONFIG_WIFI_IND_RESET
wifi_ind_reset_lock(void)188 int wifi_ind_reset_lock(void)
189 {
190 return OSA_MutexLock((osa_mutex_handle_t)ind_reset_mutex, osaWaitForever_c);
191 }
192
wifi_ind_reset_unlock(void)193 void wifi_ind_reset_unlock(void)
194 {
195 (void)OSA_MutexUnlock((osa_mutex_handle_t)ind_reset_mutex);
196 }
197 #endif
198
199 #if CONFIG_WIFI_IND_RESET
200 static bool ind_reset_in_progress = false;
201
wifi_ind_reset_in_progress(void)202 bool wifi_ind_reset_in_progress(void)
203 {
204 return ind_reset_in_progress;
205 }
206
wifi_ind_reset_start(void)207 void wifi_ind_reset_start(void)
208 {
209 ind_reset_in_progress = true;
210 }
211
wifi_ind_reset_stop(void)212 void wifi_ind_reset_stop(void)
213 {
214 ind_reset_in_progress = false;
215 }
216 #endif
217
wifi_sdio_get_command_resp_sem(unsigned long wait)218 static int wifi_sdio_get_command_resp_sem(unsigned long wait)
219 {
220 return OSA_SemaphoreWait((osa_semaphore_handle_t)sdio_command_resp_sem, wait);
221 }
222
wifi_sdio_put_command_resp_sem(void)223 static int wifi_sdio_put_command_resp_sem(void)
224 {
225 return OSA_SemaphorePost((osa_semaphore_handle_t)sdio_command_resp_sem);
226 }
227
wifi_sdio_wait_for_cmdresp()228 static void wifi_sdio_wait_for_cmdresp()
229 {
230 /* Wait max 20 sec for the command response */
231 int ret = wifi_sdio_get_command_resp_sem(SDIO_COMMAND_RESPONSE_WAIT_MS);
232 if (ret != WM_SUCCESS)
233 {
234 /* assert as command flow cannot work anymore */
235 assert(0);
236 }
237 }
238
wifi_get_device_value1(void)239 uint32_t wifi_get_device_value1(void)
240 {
241 return dev_value1;
242 }
243
wifi_get_device_mac_addr(wifi_mac_addr_t * mac_addr)244 int wifi_get_device_mac_addr(wifi_mac_addr_t *mac_addr)
245 {
246 (void)memcpy(mac_addr->mac, dev_mac_addr, MLAN_MAC_ADDR_LENGTH);
247 return WM_SUCCESS;
248 }
249
wifi_get_device_uap_mac_addr(wifi_mac_addr_t * mac_addr_uap)250 int wifi_get_device_uap_mac_addr(wifi_mac_addr_t *mac_addr_uap)
251 {
252 (void)memcpy(mac_addr_uap->mac, dev_mac_addr_uap, MLAN_MAC_ADDR_LENGTH);
253 return WM_SUCCESS;
254 }
255
wifi_get_device_firmware_version_ext(wifi_fw_version_ext_t * fw_ver_ext)256 int wifi_get_device_firmware_version_ext(wifi_fw_version_ext_t *fw_ver_ext)
257 {
258 (void)memcpy((void *)fw_ver_ext->version_str, (const void *)dev_fw_ver_ext, MLAN_MAX_VER_STR_LEN);
259 return WM_SUCCESS;
260 }
261
262 /* Initializes the driver struct */
wlan_init_struct(void)263 static int wlan_init_struct(void)
264 {
265 osa_status_t status;
266
267 status = OSA_MutexCreate((osa_mutex_handle_t)txrx_mutex);
268 if (status != KOSA_StatusSuccess)
269 {
270 return -WM_FAIL;
271 }
272 #if CONFIG_WIFI_IND_RESET
273 status = OSA_MutexCreate((osa_mutex_handle_t)ind_reset_mutex);
274 if (status != KOSA_StatusSuccess)
275 {
276 return -WM_FAIL;
277 }
278 #endif
279
280 status = OSA_SemaphoreCreateBinary((osa_semaphore_handle_t)sdio_command_resp_sem);
281 if (status != KOSA_StatusSuccess)
282 {
283 return -WM_FAIL;
284 }
285
286 return WM_SUCCESS;
287 }
288
wlan_deinit_struct(void)289 static int wlan_deinit_struct(void)
290 {
291 osa_status_t status;
292
293 status = OSA_MutexDestroy((osa_mutex_handle_t)txrx_mutex);
294 if (status != KOSA_StatusSuccess)
295 {
296 wifi_io_e("%s mutex deletion error %d", __FUNCTION__, status);
297 return -WM_FAIL;
298 }
299 #if CONFIG_WIFI_IND_RESET
300 status = OSA_MutexDestroy((osa_mutex_handle_t)ind_reset_mutex);
301 if (status != KOSA_StatusSuccess)
302 {
303 wifi_io_e("%s mutex deletion error %d", __FUNCTION__, status);
304 return -WM_FAIL;
305 }
306 #endif
307 status = OSA_SemaphoreDestroy((osa_semaphore_handle_t)sdio_command_resp_sem);
308 if (status != KOSA_StatusSuccess)
309 {
310 wifi_io_e("%s mutex deletion error %d", __FUNCTION__, status);
311 return -WM_FAIL;
312 }
313
314 (void)memset(dev_mac_addr, 0, sizeof(dev_mac_addr));
315 (void)memset(dev_fw_ver_ext, 0, sizeof(dev_fw_ver_ext));
316
317 return WM_SUCCESS;
318 }
319
raw_process_pkt_hdrs(void * pbuf,t_u32 payloadlen,t_u8 interface)320 int raw_process_pkt_hdrs(void *pbuf, t_u32 payloadlen, t_u8 interface)
321 {
322 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[interface];
323 SDIOPkt *sdiohdr = (SDIOPkt *)pbuf;
324 TxPD *ptxpd = (TxPD *)(void *)((uint8_t *)pbuf + INTF_HEADER_LEN);
325
326 ptxpd->bss_type = interface;
327 ptxpd->bss_num = GET_BSS_NUM(pmpriv);
328 ptxpd->tx_pkt_offset = 0x14; /* we'll just make this constant */
329 ptxpd->tx_pkt_length = (t_u16)(payloadlen - ptxpd->tx_pkt_offset - INTF_HEADER_LEN);
330 ptxpd->tx_pkt_type = 0xE5;
331 ptxpd->tx_control = 0;
332 ptxpd->priority = 0;
333 ptxpd->flags = 0;
334 ptxpd->pkt_delay_2ms = 0;
335
336 #if CONFIG_WPA_SUPP
337 if (pmpriv->tx_seq_num == 0)
338 {
339 pmpriv->tx_seq_num++;
340 }
341 ptxpd->tx_token_id = pmpriv->tx_seq_num++;
342 ptxpd->flags |= MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS;
343 #endif
344
345 sdiohdr->size = (t_u16)(payloadlen + ptxpd->tx_pkt_offset + INTF_HEADER_LEN);
346
347 return (int)(ptxpd->tx_pkt_offset + INTF_HEADER_LEN);
348 }
349
350 /*
351 * fixme: mlan_sta_tx.c can be used directly here. This functionality is
352 * already present there.
353 */
354 /* SDIO TxPD PAYLOAD | 4 | 22 | payload | */
355
process_pkt_hdrs(void * pbuf,t_u32 payloadlen,t_u8 interface,t_u8 tid,t_u32 tx_control)356 void process_pkt_hdrs(void *pbuf, t_u32 payloadlen, t_u8 interface, t_u8 tid, t_u32 tx_control)
357 {
358 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[interface];
359 #if CONFIG_FW_VDLL
360 mlan_adapter *pmadapter = pmpriv->adapter;
361 #endif
362 SDIOPkt *sdiohdr = (SDIOPkt *)pbuf;
363 TxPD *ptxpd = (TxPD *)(void *)((uint8_t *)pbuf + INTF_HEADER_LEN);
364
365 ptxpd->bss_type = interface;
366 ptxpd->bss_num = GET_BSS_NUM(pmpriv);
367 ptxpd->tx_pkt_offset = 0x16; /* we'll just make this constant */
368 ptxpd->tx_pkt_length = (t_u16)(payloadlen - ptxpd->tx_pkt_offset - INTF_HEADER_LEN);
369 ptxpd->tx_control = tx_control;
370 ptxpd->priority = tid;
371 ptxpd->flags = 0;
372
373 if (ptxpd->tx_pkt_type == 0xe5U)
374 {
375 ptxpd->tx_pkt_offset = 0x14; /* Override for special frame */
376 }
377
378 ptxpd->pkt_delay_2ms = 0;
379
380 sdiohdr->size = (t_u16)payloadlen;
381
382 #if CONFIG_FW_VDLL
383 while (pmadapter->vdll_in_progress == MTRUE)
384 {
385 OSA_TimeDelay(50);
386 }
387 #endif
388 }
389
process_pkt_hdrs_flags(void * pbuf,t_u8 flags)390 void process_pkt_hdrs_flags(void *pbuf, t_u8 flags)
391 {
392 TxPD *ptxpd = (TxPD *)((uint8_t *)pbuf + INTF_HEADER_LEN);
393 ptxpd->flags = flags;
394 }
395
bus_register_event_queue(osa_msgq_handle_t event_queue)396 int bus_register_event_queue(osa_msgq_handle_t event_queue)
397 {
398 if (bus.event_queue != NULL)
399 {
400 return -WM_FAIL;
401 }
402
403 bus.event_queue = event_queue;
404
405 return WM_SUCCESS;
406 }
407
bus_deregister_event_queue(void)408 void bus_deregister_event_queue(void)
409 {
410 if (bus.event_queue != NULL)
411 {
412 bus.event_queue = NULL;
413 }
414 }
415
bus_register_data_input_function(int (* wifi_low_level_input)(const uint8_t interface,const uint8_t * buffer,const uint16_t len))416 int bus_register_data_input_function(int (*wifi_low_level_input)(const uint8_t interface,
417 const uint8_t *buffer,
418 const uint16_t len))
419 {
420 if (bus.wifi_low_level_input != NULL)
421 {
422 return -WM_FAIL;
423 }
424
425 bus.wifi_low_level_input = wifi_low_level_input;
426
427 return WM_SUCCESS;
428 }
429
bus_deregister_data_input_funtion(void)430 void bus_deregister_data_input_funtion(void)
431 {
432 bus.wifi_low_level_input = NULL;
433 }
434
435 #if CONFIG_P2P
bus_register_special_queue(osa_msgq_handle_t special_queue)436 int bus_register_special_queue(osa_msgq_handle_t special_queue)
437 {
438 if (bus.special_queue)
439 return -WM_FAIL;
440 bus.special_queue = special_queue;
441 return WM_SUCCESS;
442 }
443
bus_deregister_special_queue()444 void bus_deregister_special_queue()
445 {
446 if (bus.special_queue)
447 bus.special_queue = NULL;
448 }
449 #endif
450
451 void wifi_get_mac_address_from_cmdresp(const HostCmd_DS_COMMAND *resp, uint8_t *mac_addr);
452 void wifi_get_firmware_ver_ext_from_cmdresp(const HostCmd_DS_COMMAND *resp, uint8_t *fw_ver_ext);
453 void wifi_get_value1_from_cmdresp(const HostCmd_DS_COMMAND *resp, uint32_t *dev_value1);
454
455 #if CONFIG_FW_VDLL
wlan_handle_event_packet(t_u8 * pmbuf)456 static mlan_status wlan_handle_event_packet(t_u8 *pmbuf)
457 {
458 t_u16 evttype = wlan_le16_to_cpu(*(t_u16 *)pmbuf);
459 mlan_status status = MLAN_STATUS_SUCCESS;
460
461 #if CONFIG_FW_VDLL_DEBUG
462 wevt_d("Event %x", evttype);
463 #endif
464
465 switch (evttype)
466 {
467 case EVENT_VDLL_IND:
468 {
469 status = wlan_process_vdll_event((mlan_private *)mlan_adap->priv[0], pmbuf);
470 break;
471 }
472 default:
473 wevt_d("Unhandled pre Queue event %x", evttype);
474 break;
475 }
476
477 return status;
478 }
479 #endif
480
wlan_handle_cmd_resp_packet(t_u8 * pmbuf)481 static mlan_status wlan_handle_cmd_resp_packet(t_u8 *pmbuf)
482 {
483 HostCmd_DS_GEN *cmdresp;
484 t_u32 cmdtype;
485 int bss_type;
486
487 cmdresp = (HostCmd_DS_GEN *)(void *)(pmbuf + INTF_HEADER_LEN); /* size + pkttype=4 */
488 cmdtype = cmdresp->command & HostCmd_CMD_ID_MASK;
489
490 bss_type = HostCmd_GET_BSS_TYPE(cmdresp->seq_num);
491
492 if ((cmdresp->command & 0xf000) != 0x8000)
493 {
494 wifi_io_d("cmdresp->command = (0x%x)", cmdresp->command);
495 }
496
497 /* Do not process response of wlan firmware shutdown command
498 *
499 * This is required to flush out any previous response
500 * from the wlan_deinit() which might have been called
501 * prior to this.
502 *
503 */
504 if ((cmdresp->command & 0x00ff) == HostCmd_CMD_FUNC_SHUTDOWN)
505 {
506 return MLAN_STATUS_SUCCESS;
507 }
508
509 if ((cmdresp->command & 0x0fffU) != last_cmd_sent)
510 {
511 wifi_io_d("cmdresp->command = (0x%x) last_cmd_sent = (0x%x)", cmdresp->command, last_cmd_sent);
512 }
513
514 if (cmdresp->result != 0U)
515 {
516 wifi_io_d("cmdresp->result = (0x%x)", cmdresp->result);
517 }
518
519 wifi_io_d("Resp : (0x%x)", cmdtype);
520 switch (cmdtype)
521 {
522 case HostCmd_CMD_FUNC_INIT:
523 case HostCmd_CMD_MAC_CONTROL:
524 case HostCmd_CMD_CFG_DATA:
525 break;
526 case HostCmd_CMD_MAC_REG_ACCESS:
527 wifi_get_value1_from_cmdresp((HostCmd_DS_COMMAND *)(void *)cmdresp, &dev_value1);
528 break;
529 case HostCmd_CMD_802_11_MAC_ADDRESS:
530 if (bss_type == MLAN_BSS_TYPE_UAP)
531 {
532 wifi_get_mac_address_from_cmdresp((HostCmd_DS_COMMAND *)(void *)cmdresp, dev_mac_addr_uap);
533 }
534 else
535 {
536 wifi_get_mac_address_from_cmdresp((HostCmd_DS_COMMAND *)(void *)cmdresp, dev_mac_addr);
537 }
538 break;
539 #ifdef OTP_CHANINFO
540 case HostCmd_CMD_CHAN_REGION_CFG:
541 (void)wlan_ret_chan_region_cfg((mlan_private *)mlan_adap->priv[0], (HostCmd_DS_COMMAND *)(void *)cmdresp,
542 NULL);
543 break;
544 #endif
545 case HostCmd_CMD_GET_HW_SPEC:
546 (void)wlan_ret_get_hw_spec((mlan_private *)mlan_adap->priv[0], (HostCmd_DS_COMMAND *)(void *)cmdresp, NULL);
547 break;
548 case HostCmd_CMD_VERSION_EXT:
549 wifi_get_firmware_ver_ext_from_cmdresp((HostCmd_DS_COMMAND *)(void *)cmdresp, dev_fw_ver_ext);
550 break;
551 #if CONFIG_11N
552 case HostCmd_CMD_11N_CFG:
553 case HostCmd_CMD_AMSDU_AGGR_CTRL:
554 break;
555 #endif
556 case HostCmd_CMD_FUNC_SHUTDOWN:
557 break;
558 #ifdef WLAN_LOW_POWER_ENABLE
559 case HostCmd_CMD_LOW_POWER_MODE:
560 break;
561 #endif
562 case HostCmd_CMD_ED_MAC_MODE:
563 case HostCmd_CMD_CHANNEL_TRPC_CONFIG:
564 break;
565 case HostCmd_CMD_RECONFIGURE_TX_BUFF:
566 break;
567 #if CONFIG_EXTERNAL_BLE_COEX
568 case HostCmd_CMD_ROBUST_COEX:
569 break;
570 #endif
571 default:
572 wifi_io_d("Unimplemented Resp : (0x%x)", cmdtype);
573 #if CONFIG_WIFI_IO_DUMP
574 dump_hex(cmdresp, cmdresp->size);
575 #endif
576 break;
577 }
578
579 wifi_sdio_put_command_resp_sem();
580
581 return MLAN_STATUS_SUCCESS;
582 }
583
584 /*
585 * Accepts event and command packets. Redirects them to queues if
586 * registered. If queues are not registered (as is the case during
587 * initialization then the packet is given to lower layer cmd/event
588 * handling part.
589 */
wlan_decode_rx_packet(t_u8 * pmbuf,t_u32 upld_type)590 static mlan_status wlan_decode_rx_packet(t_u8 *pmbuf, t_u32 upld_type)
591 {
592 if (upld_type == MLAN_TYPE_DATA)
593 {
594 return MLAN_STATUS_FAILURE;
595 }
596
597 if (upld_type == MLAN_TYPE_CMD)
598 {
599 wifi_io_d(" --- Rx: Cmd Response ---");
600 }
601 else
602 {
603 wifi_io_d(" --- Rx: EVENT Response ---");
604 }
605
606 SDIOPkt *sdiopkt = (SDIOPkt *)(void *)pmbuf;
607
608 #if CONFIG_FW_VDLL
609 if (upld_type == MLAN_TYPE_EVENT && (wlan_le16_to_cpu(sdiopkt->hostcmd.command) == EVENT_VDLL_IND))
610 {
611 #if CONFIG_FW_VDLL_DEBUG
612 dump_hex(pmbuf, sdiopkt->size);
613 #endif
614 return wlan_handle_event_packet(pmbuf + INTF_HEADER_LEN);
615 }
616 #endif
617 #if CONFIG_CSI
618 if (upld_type == MLAN_TYPE_EVENT && (wlan_le16_to_cpu(sdiopkt->hostcmd.command) == EVENT_CSI))
619 {
620 csi_save_data_to_local_buff((t_u8 *)pmbuf + 8);
621 }
622 #endif
623
624 #if CONFIG_P2P
625 t_u8 *cmdBuf;
626 #endif /* CONFIG_P2P */
627 osa_status_t status;
628 struct bus_message msg;
629
630 #if CONFIG_P2P
631 if (bus.special_queue != NULL && upld_type == MLAN_TYPE_CMD)
632 {
633 msg.data = OSA_MemoryAllocate(sdiopkt->size);
634 if (!msg.data)
635 {
636 wifi_io_e("Buffer allocation failed");
637 return MLAN_STATUS_FAILURE;
638 }
639
640 msg.event = upld_type;
641 cmdBuf = pmbuf;
642 cmdBuf = cmdBuf + INTF_HEADER_LEN;
643 (void)memcpy((void *)msg.data, (const void *)cmdBuf, sdiopkt->size);
644
645 status = OSA_MsgQPut(bus.special_queue, &msg);
646
647 if (status != KOSA_StatusSuccess)
648 {
649 wifi_io_e("Failed to send response on Queue");
650 if (upld_type != MLAN_TYPE_CMD)
651 wifi_free_eventbuf(msg.data);
652 return MLAN_STATUS_FAILURE;
653 }
654 }
655 else
656 #endif /* CONFIG_P2P */
657 if ((fw_init_cfg == 0U) && (bus.event_queue != NULL))
658 {
659 if (upld_type == MLAN_TYPE_CMD)
660 {
661 msg.data = wifi_mem_malloc_cmdrespbuf();
662 }
663 else
664 {
665 msg.data = wifi_malloc_eventbuf((size_t)sdiopkt->size);
666 }
667
668 if (msg.data == MNULL)
669 {
670 wifi_io_e("[fail] Buffer alloc: T: %d S: %d", upld_type, sdiopkt->size);
671 return MLAN_STATUS_FAILURE;
672 }
673
674 msg.event = (uint16_t)upld_type;
675 (void)memcpy((void *)msg.data, (const void *)pmbuf, sdiopkt->size);
676
677 #if CONFIG_WMM
678 if (upld_type == MLAN_TYPE_EVENT && sdiopkt->hostcmd.command == EVENT_TX_DATA_PAUSE)
679 {
680 wifi_handle_event_data_pause(msg.data);
681 wifi_free_eventbuf(msg.data);
682 return MLAN_STATUS_SUCCESS;
683 }
684 #endif
685 status = OSA_MsgQPut(bus.event_queue, &msg);
686
687 if (status != KOSA_StatusSuccess)
688 {
689 wifi_io_e("Failed to send response on Queue");
690 return MLAN_STATUS_FAILURE;
691 }
692 }
693 else
694 {
695 /* No queues registered yet. Use local handling */
696 if (upld_type == MLAN_TYPE_CMD)
697 {
698 (void)wlan_handle_cmd_resp_packet(pmbuf);
699 }
700 }
701
702 return MLAN_STATUS_SUCCESS;
703 }
704
705 #if 0
706 static t_u32 get_ioport(void)
707 {
708 return mlan_adap->ioport;
709 }
710 #endif
711
wlan_read_rcv_packet(t_u32 port,t_u32 rxlen,t_u32 rx_blocks,t_u32 * type,bool aggr)712 static t_u8 *wlan_read_rcv_packet(t_u32 port, t_u32 rxlen, t_u32 rx_blocks, t_u32 *type, bool aggr)
713 {
714 t_u32 blksize = MLAN_SDIO_BLOCK_SIZE;
715 uint32_t resp;
716 int ret;
717 #if CONFIG_SDIO_MULTI_PORT_RX_AGGR
718 int i = 0;
719
720 while (true)
721 {
722 /* addr = 0 fn = 1 */
723 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
724 if (aggr == true)
725 {
726 ret = sdio_drv_read_mb(port, 1, rx_blocks, blksize);
727 }
728 else
729 {
730 ret = sdio_drv_read(port, 1, rx_blocks, blksize, inbuf, &resp);
731 }
732 #else
733 {
734 ret = sdio_drv_read(port, 1, rx_blocks, blksize, inbuf, &resp);
735 }
736 #endif
737 if (aggr && !ret)
738 {
739 PRINTF("sdio mp cmd53 read failed: %d ioport=0x%x retry=%d\r\n", ret, port, i);
740 i++;
741 if (sdio_drv_creg_write(HOST_TO_CARD_EVENT_REG, 1, HOST_TERM_CMD53, &resp) == false)
742 {
743 wifi_d("Set Term cmd53 failed\r\n");
744 }
745 if (i > MAX_READ_IOMEM_RETRY)
746 {
747 wifi_io_e("sdio_drv_read failed (%d)", ret);
748 #if CONFIG_WIFI_FW_DEBUG
749 wifi_sdio_reg_dbg(NULL);
750 if (wm_wifi.wifi_usb_mount_cb != NULL)
751 {
752 ret = wm_wifi.wifi_usb_mount_cb();
753 if (ret == WM_SUCCESS)
754 {
755 wifi_dump_firmware_info(NULL);
756 }
757 else
758 {
759 wifi_e("USB mounting failed");
760 }
761 }
762 else
763 {
764 wifi_e("USB mount callback is not registered");
765 }
766 #endif
767 return NULL;
768 } /* if (i > MAX_READ_IOMEM_RETRY) */
769 continue;
770 } /* if (aggr && !ret) */
771 break;
772 } /* while(true) */
773 #else
774 /* addr = 0 fn = 1 */
775 ret = sdio_drv_read(port, 1, rx_blocks, blksize, inbuf, &resp);
776 if (!ret)
777 {
778 wifi_io_e("sdio_drv_read failed (%d)", ret);
779 #if CONFIG_WIFI_FW_DEBUG
780 wifi_sdio_reg_dbg(NULL);
781 if (wm_wifi.wifi_usb_mount_cb != NULL)
782 {
783 ret = wm_wifi.wifi_usb_mount_cb();
784 if (ret == WM_SUCCESS)
785 {
786 wifi_dump_firmware_info(NULL);
787 }
788 else
789 {
790 wifi_e("USB mounting failed");
791 }
792 }
793 else
794 {
795 wifi_e("USB mount callback is not registered");
796 }
797
798 #endif
799 return NULL;
800 }
801 #endif
802
803 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
804 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
805 if ((aggr == false) && (port & (CMD_PORT_SLCT | MLAN_SDIO_BYTE_MODE_MASK)))
806 #endif
807 #endif
808 {
809 SDIOPkt *insdiopkt = (SDIOPkt *)(void *)inbuf;
810 *type = insdiopkt->pkttype;
811
812 #if CONFIG_WIFI_IO_DUMP
813 if (insdiopkt->pkttype != 0)
814 {
815 (void)PRINTF("wlan_read_rcv_packet: DUMP:");
816 dump_hex((t_u8 *)inbuf, rx_blocks * blksize);
817 }
818 #endif /* CONFIG_WIFI_IO_DUMP */
819 }
820
821 return inbuf;
822 }
823
wlan_get_next_seq_num(void)824 static int wlan_get_next_seq_num(void)
825 {
826 /* No need to increase seqnum as all cmds in RT uses seqnum 0 for STA and
827 * 4096 for uAP */
828 /* seqnum++; */
829 return seqnum;
830 }
831
832 void wifi_prepare_set_cal_data_cmd(HostCmd_DS_COMMAND *cmd, int seq_number);
_wlan_set_cal_data(void)833 static void _wlan_set_cal_data(void)
834 {
835 t_u32 tx_blocks = 4, buflen = MLAN_SDIO_BLOCK_SIZE;
836 uint32_t resp;
837
838 wifi_sdio_lock();
839
840 (void)memset(outbuf, 0, SDIO_OUTBUF_LEN);
841
842 /* sdiopkt = outbuf */
843 wifi_prepare_set_cal_data_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
844
845 sdiopkt->pkttype = MLAN_TYPE_CMD;
846 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
847
848 last_cmd_sent = HostCmd_CMD_CFG_DATA;
849
850 /* send CMD53 to write the command to get mac address */
851 #if defined(SD8801)
852 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
853 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
854 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
855 #endif
856
857 wifi_sdio_unlock();
858
859 wifi_sdio_wait_for_cmdresp();
860 }
861
862 void wifi_prepare_reconfigure_tx_buf_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
863
wlan_reconfigure_tx_buffers(void)864 static void wlan_reconfigure_tx_buffers(void)
865 {
866 t_u32 tx_blocks = 4, buflen = MLAN_SDIO_BLOCK_SIZE;
867 uint32_t resp;
868
869 wifi_sdio_lock();
870
871 (void)memset(outbuf, 0, SDIO_OUTBUF_LEN);
872
873 /* sdiopkt = outbuf */
874 wifi_prepare_reconfigure_tx_buf_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
875 sdiopkt->pkttype = MLAN_TYPE_CMD;
876 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
877
878 last_cmd_sent = HostCmd_CMD_RECONFIGURE_TX_BUFF;
879
880 /* send CMD53 to write the command to get mac address */
881 #if defined(SD8801)
882 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
883 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
884 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
885 #endif
886
887 wifi_sdio_unlock();
888
889 wifi_sdio_wait_for_cmdresp();
890 }
891
892 void wifi_prepare_get_mac_addr_cmd(HostCmd_DS_COMMAND *cmd, int seq_number);
893 #ifdef OTP_CHANINFO
894 void wifi_prepare_get_channel_region_cfg_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
895 #endif
896 void wifi_prepare_get_hw_spec_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
897
898 #ifdef OTP_CHANINFO
wlan_get_channel_region_cfg(void)899 static void wlan_get_channel_region_cfg(void)
900 {
901 uint32_t tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
902 uint32_t resp;
903
904 wifi_sdio_lock();
905
906 (void)memset(outbuf, 0, buflen);
907
908 /* sdiopkt = outbuf */
909 wifi_prepare_get_channel_region_cfg_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
910
911 sdiopkt->pkttype = MLAN_TYPE_CMD;
912 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
913
914 last_cmd_sent = HostCmd_CMD_CHAN_REGION_CFG;
915 #if defined(SD8801)
916 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
917 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
918 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
919 #endif
920
921 wifi_sdio_unlock();
922
923 wifi_sdio_wait_for_cmdresp();
924
925 }
926 #endif
927
wlan_get_hw_spec(void)928 static void wlan_get_hw_spec(void)
929 {
930 uint32_t tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
931 uint32_t resp;
932
933 wifi_sdio_lock();
934
935 (void)memset(outbuf, 0, buflen);
936 /* sdiopkt = outbuf */
937 wifi_prepare_get_hw_spec_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
938
939 sdiopkt->pkttype = MLAN_TYPE_CMD;
940 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
941
942 last_cmd_sent = HostCmd_CMD_GET_HW_SPEC;
943 #if defined(SD8801)
944 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
945 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
946 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
947 #endif
948
949 wifi_sdio_unlock();
950
951 wifi_sdio_wait_for_cmdresp();
952
953 }
954
wlan_get_mac_addr_sta(void)955 static void wlan_get_mac_addr_sta(void)
956 {
957 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
958 uint32_t resp;
959
960 wifi_sdio_lock();
961
962 (void)memset(outbuf, 0, buflen);
963
964 /* sdiopkt = outbuf */
965 wifi_prepare_get_mac_addr_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
966
967 sdiopkt->pkttype = MLAN_TYPE_CMD;
968 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
969
970 last_cmd_sent = HostCmd_CMD_802_11_MAC_ADDRESS;
971
972 /* send CMD53 to write the command to get mac address */
973 #if defined(SD8801)
974 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
975 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
976 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
977 #endif
978
979 wifi_sdio_unlock();
980
981 wifi_sdio_wait_for_cmdresp();
982
983 }
984
wlan_get_mac_addr_uap(void)985 static void wlan_get_mac_addr_uap(void)
986 {
987 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
988 uint32_t resp;
989 t_u16 seq_number = 0;
990
991 wifi_sdio_lock();
992
993 (void)memset(outbuf, 0, buflen);
994 seq_number = HostCmd_SET_SEQ_NO_BSS_INFO(0 /* seq_num */, 0 /* bss_num */, MLAN_BSS_TYPE_UAP);
995
996 /* sdiopkt = outbuf */
997 wifi_prepare_get_mac_addr_cmd(&sdiopkt->hostcmd, seq_number);
998
999 sdiopkt->pkttype = MLAN_TYPE_CMD;
1000 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1001
1002 last_cmd_sent = HostCmd_CMD_802_11_MAC_ADDRESS;
1003
1004 /* send CMD53 to write the command to get mac address */
1005 #if defined(SD8801)
1006 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1007 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1008 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1009 #endif
1010
1011 wifi_sdio_unlock();
1012
1013 wifi_sdio_wait_for_cmdresp();
1014
1015 }
1016
1017 void wifi_prepare_get_fw_ver_ext_cmd(HostCmd_DS_COMMAND *cmd, int seq_number, int version_str_sel);
wlan_get_fw_ver_ext(int version_str_sel)1018 static void wlan_get_fw_ver_ext(int version_str_sel)
1019 {
1020 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1021 uint32_t resp;
1022
1023 wifi_sdio_lock();
1024
1025 (void)memset(outbuf, 0, buflen);
1026
1027 /* sdiopkt = outbuf */
1028 wifi_prepare_get_fw_ver_ext_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num(), version_str_sel);
1029
1030 sdiopkt->pkttype = MLAN_TYPE_CMD;
1031 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1032
1033 last_cmd_sent = HostCmd_CMD_VERSION_EXT;
1034
1035 /* send CMD53 to write the command to get mac address */
1036 #if defined(SD8801)
1037 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1038 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1039 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1040 #endif
1041
1042 wifi_sdio_unlock();
1043
1044 wifi_sdio_wait_for_cmdresp();
1045
1046 }
1047
1048 void wifi_prepare_get_value1(HostCmd_DS_COMMAND *cmd, int seq_number);
1049
wlan_get_value_1(void)1050 static void wlan_get_value_1(void)
1051 {
1052 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1053 uint32_t resp;
1054
1055 wifi_sdio_lock();
1056
1057 (void)memset(outbuf, 0, buflen);
1058
1059 /* sdiopkt = outbuf */
1060 wifi_prepare_get_value1(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1061
1062 sdiopkt->pkttype = MLAN_TYPE_CMD;
1063 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1064
1065 last_cmd_sent = HostCmd_CMD_MAC_REG_ACCESS;
1066
1067 #if defined(SD8801)
1068 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1069 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1070 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1071 #endif
1072
1073 wifi_sdio_unlock();
1074
1075 wifi_sdio_wait_for_cmdresp();
1076
1077 }
1078
1079 void wifi_prepare_set_mac_addr_cmd(HostCmd_DS_COMMAND *cmd, int seq_number);
_wlan_set_mac_addr(void)1080 static void _wlan_set_mac_addr(void)
1081 {
1082 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1083 uint32_t resp;
1084
1085 wifi_sdio_lock();
1086
1087 (void)memset(outbuf, 0, buflen);
1088
1089 /* sdiopkt = outbuf */
1090 wifi_prepare_set_mac_addr_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1091
1092 sdiopkt->pkttype = MLAN_TYPE_CMD;
1093 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1094
1095 last_cmd_sent = HostCmd_CMD_802_11_MAC_ADDRESS;
1096
1097 /* send CMD53 to write the command to get mac address */
1098 #if defined(SD8801)
1099 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1100 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1101 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1102 #endif
1103
1104 wifi_sdio_unlock();
1105
1106 wifi_sdio_wait_for_cmdresp();
1107 }
1108
1109 #if CONFIG_11N
wlan_set_11n_cfg(void)1110 static void wlan_set_11n_cfg(void)
1111 {
1112 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1113 uint32_t resp;
1114
1115 wifi_sdio_lock();
1116
1117 (void)memset(outbuf, 0, SDIO_OUTBUF_LEN);
1118
1119 wrapper_wlan_cmd_11n_cfg(&sdiopkt->hostcmd);
1120 /* sdiopkt = outbuf */
1121 sdiopkt->hostcmd.seq_num = (t_u16)wlan_get_next_seq_num();
1122 sdiopkt->pkttype = MLAN_TYPE_CMD;
1123 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1124
1125 last_cmd_sent = HostCmd_CMD_11N_CFG;
1126
1127 #if defined(SD8801)
1128 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1129 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1130 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1131 #endif
1132
1133 wifi_sdio_unlock();
1134
1135 wifi_sdio_wait_for_cmdresp();
1136 }
1137
1138 #if CONFIG_ENABLE_AMSDU_RX
1139 void wifi_prepare_enable_amsdu_cmd(HostCmd_DS_COMMAND *cmd, int seq_number);
wlan_enable_amsdu(void)1140 static void wlan_enable_amsdu(void)
1141 {
1142 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1143 uint32_t resp;
1144
1145 wifi_sdio_lock();
1146
1147 (void)memset(outbuf, 0, buflen);
1148
1149 /* sdiopkt = outbuf */
1150 wifi_prepare_enable_amsdu_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1151
1152 sdiopkt->pkttype = MLAN_TYPE_CMD;
1153 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1154
1155 last_cmd_sent = HostCmd_CMD_AMSDU_AGGR_CTRL;
1156
1157 #if defined(SD8801)
1158 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1159 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1160 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1161 #endif
1162
1163 wifi_sdio_unlock();
1164
1165 wifi_sdio_wait_for_cmdresp();
1166
1167 }
1168 #endif /* CONFIG_ENABLE_AMSDU_RX */
1169 #endif /* CONFIG_11N */
1170
wlan_cmd_shutdown(void)1171 static void wlan_cmd_shutdown(void)
1172 {
1173 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1174 uint32_t resp;
1175
1176 (void)memset(outbuf, 0, buflen);
1177
1178 /* sdiopkt = outbuf */
1179 sdiopkt->hostcmd.command = HostCmd_CMD_FUNC_SHUTDOWN;
1180 sdiopkt->hostcmd.size = (t_u16)S_DS_GEN;
1181 sdiopkt->hostcmd.seq_num = (t_u16)wlan_get_next_seq_num();
1182 sdiopkt->hostcmd.result = 0;
1183
1184 sdiopkt->pkttype = MLAN_TYPE_CMD;
1185 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1186
1187 last_cmd_sent = HostCmd_CMD_FUNC_SHUTDOWN;
1188
1189 (void)sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1190 }
1191
1192 void wlan_prepare_mac_control_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
wlan_set_mac_ctrl(void)1193 static void wlan_set_mac_ctrl(void)
1194 {
1195 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1196 uint32_t resp;
1197
1198 wifi_sdio_lock();
1199
1200 (void)memset(outbuf, 0, buflen);
1201
1202 /* sdiopkt = outbuf */
1203 wlan_prepare_mac_control_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1204
1205 sdiopkt->pkttype = MLAN_TYPE_CMD;
1206 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1207
1208 last_cmd_sent = HostCmd_CMD_MAC_CONTROL;
1209
1210 /* send CMD53 to write the command to set mac control */
1211 #if defined(SD8801)
1212 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1213 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1214 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1215 #endif
1216
1217 wifi_sdio_unlock();
1218
1219 wifi_sdio_wait_for_cmdresp();
1220
1221 }
1222
wlan_cmd_init(void)1223 static void wlan_cmd_init(void)
1224 {
1225 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1226 uint32_t resp;
1227
1228 wifi_sdio_lock();
1229
1230 (void)memset(outbuf, 0, buflen);
1231
1232 /* sdiopkt = outbuf */
1233 sdiopkt->hostcmd.command = HostCmd_CMD_FUNC_INIT;
1234 sdiopkt->hostcmd.size = (t_u16)S_DS_GEN;
1235 sdiopkt->hostcmd.seq_num = (t_u16)wlan_get_next_seq_num();
1236 sdiopkt->hostcmd.result = 0;
1237
1238 sdiopkt->pkttype = MLAN_TYPE_CMD;
1239 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1240
1241 last_cmd_sent = HostCmd_CMD_FUNC_INIT;
1242
1243 #if defined(SD8801)
1244 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1245 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1246 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1247 #endif
1248
1249 wifi_sdio_unlock();
1250
1251 wifi_sdio_wait_for_cmdresp();
1252 }
1253
1254 #ifdef WLAN_LOW_POWER_ENABLE
1255 void wifi_prepare_low_power_mode_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
wlan_set_low_power_mode()1256 static int wlan_set_low_power_mode()
1257 {
1258 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1259 uint32_t resp;
1260
1261 wifi_sdio_lock();
1262
1263 (void)memset(outbuf, 0, buflen);
1264
1265 /* sdiopkt = outbuf */
1266
1267 wifi_prepare_low_power_mode_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1268
1269 sdiopkt->pkttype = MLAN_TYPE_CMD;
1270 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1271
1272 last_cmd_sent = HostCmd_CMD_LOW_POWER_MODE;
1273
1274 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1275
1276 wifi_sdio_unlock();
1277
1278 wifi_sdio_wait_for_cmdresp();
1279
1280 return true;
1281 }
1282 #endif
1283
1284 #if CONFIG_EXTERNAL_BLE_COEX
1285 void wifi_prepare_set_coex_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
1286
wlan_set_ext_ble_coex_mode()1287 static int wlan_set_ext_ble_coex_mode()
1288 {
1289 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1290 uint32_t resp;
1291
1292 if (!board_coex_interface())
1293 {
1294 return false;
1295 }
1296
1297 board_coex_pin_config(1);
1298
1299 wifi_sdio_lock();
1300
1301 (void)memset(outbuf, 0, buflen);
1302
1303 /* sdiopkt = outbuf */
1304 wifi_prepare_set_coex_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1305
1306 sdiopkt->pkttype = MLAN_TYPE_CMD;
1307 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1308
1309 last_cmd_sent = HostCmd_CMD_ROBUST_COEX;
1310
1311 /* send CMD53 to write the command to set mac control */
1312 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1313
1314 wifi_sdio_unlock();
1315
1316 wifi_sdio_wait_for_cmdresp();
1317
1318 return true;
1319 }
1320 #endif
1321
1322 /* Setup the firmware with commands */
wlan_fw_init_cfg(void)1323 static void wlan_fw_init_cfg(void)
1324 {
1325 #if CONFIG_FW_VDLL
1326 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[0];
1327 mlan_adapter *pmadapter = pmpriv->adapter;
1328 #endif
1329
1330 wifi_io_d("FWCMD : INIT (0xa9)");
1331
1332 wlan_cmd_init();
1333
1334 #ifdef WLAN_LOW_POWER_ENABLE
1335 if (low_power_mode)
1336 {
1337 #if CONFIG_FW_VDLL
1338 while (pmadapter->vdll_in_progress == MTRUE)
1339 {
1340 OSA_TimeDelay(50);
1341 }
1342 #endif
1343 wifi_io_d("CMD : LOW_POWER_MODE (0x128)");
1344
1345 wlan_set_low_power_mode();
1346 }
1347 #endif
1348
1349 if (cal_data_valid)
1350 {
1351 #if CONFIG_FW_VDLL
1352 while (pmadapter->vdll_in_progress == MTRUE)
1353 {
1354 OSA_TimeDelay(50);
1355 }
1356 #endif
1357 wifi_io_d("CMD : SET_CAL_DATA (0x8f)");
1358
1359 _wlan_set_cal_data();
1360 }
1361
1362 /* When cal data set command is sent, fimrware looses alignment of SDIO Tx buffers.
1363 * So we need to send reconfigure command. This can be removed if fix is added in firmware.
1364 */
1365 wifi_io_d("CMD : RECONFIGURE_TX_BUFF (0xd9)");
1366
1367 #if CONFIG_FW_VDLL
1368 while (pmadapter->vdll_in_progress == MTRUE)
1369 {
1370 OSA_TimeDelay(50);
1371 }
1372 #endif
1373
1374 wlan_reconfigure_tx_buffers();
1375
1376 if (mac_addr_valid)
1377 {
1378 wifi_io_d("CMD : SET_MAC_ADDR (0x4d)");
1379 #if CONFIG_FW_VDLL
1380 while (pmadapter->vdll_in_progress == MTRUE)
1381 {
1382 OSA_TimeDelay(50);
1383 }
1384 #endif
1385 _wlan_set_mac_addr();
1386 }
1387
1388 #ifdef OTP_CHANINFO
1389 wifi_io_d("CMD : Channel Region CFG (0x0242)");
1390
1391 #if CONFIG_FW_VDLL
1392 while (pmadapter->vdll_in_progress == MTRUE)
1393 {
1394 OSA_TimeDelay(50);
1395 }
1396 #endif
1397
1398 wlan_get_channel_region_cfg();
1399 #endif
1400
1401 wifi_io_d("CMD : GET_HW_SPEC (0x03)");
1402
1403 #if CONFIG_FW_VDLL
1404 while (pmadapter->vdll_in_progress == MTRUE)
1405 {
1406 OSA_TimeDelay(50);
1407 }
1408 #endif
1409
1410 wlan_get_hw_spec();
1411
1412 #if CONFIG_FW_VDLL
1413 while (pmadapter->vdll_in_progress == MTRUE)
1414 {
1415 OSA_TimeDelay(50);
1416 }
1417 #endif
1418
1419 wlan_get_value_1();
1420
1421 if (wm_wifi.wifi_init_done == 0U)
1422 {
1423
1424 wifi_io_d("CMD : GET_FW_VER_EXT (0x97)");
1425
1426 #if CONFIG_FW_VDLL
1427 while (pmadapter->vdll_in_progress == MTRUE)
1428 {
1429 OSA_TimeDelay(50);
1430 }
1431 #endif
1432
1433 wlan_get_fw_ver_ext(0);
1434 }
1435
1436 wifi_io_d("CMD : GET_MAC_ADDR (0x4d)");
1437
1438 #if CONFIG_FW_VDLL
1439 while (pmadapter->vdll_in_progress == MTRUE)
1440 {
1441 OSA_TimeDelay(50);
1442 }
1443 #endif
1444
1445 wlan_get_mac_addr_sta();
1446
1447 wifi_io_d("CMD : GET_MAC_ADDR (0x4d)");
1448
1449 #if CONFIG_FW_VDLL
1450 while (pmadapter->vdll_in_progress == MTRUE)
1451 {
1452 OSA_TimeDelay(50);
1453 }
1454 #endif
1455
1456 wlan_get_mac_addr_uap();
1457
1458 if (wm_wifi.wifi_init_done == 0U)
1459 {
1460
1461 wifi_io_d("CMD : GET_FW_VER_EXT (0x97)");
1462
1463 #if CONFIG_FW_VDLL
1464 while (pmadapter->vdll_in_progress == MTRUE)
1465 {
1466 OSA_TimeDelay(50);
1467 }
1468 #endif
1469
1470 wlan_get_fw_ver_ext(3);
1471
1472 }
1473
1474 wifi_io_d("CMD : MAC_CTRL (0x28)");
1475
1476 #if CONFIG_FW_VDLL
1477 while (pmadapter->vdll_in_progress == MTRUE)
1478 {
1479 OSA_TimeDelay(50);
1480 }
1481 #endif
1482
1483 wlan_set_mac_ctrl();
1484
1485 if (wm_wifi.wifi_init_done == 0U)
1486 {
1487 wifi_io_d("CMD : GET_FW_VER_EXT (0x97)");
1488
1489 #if CONFIG_FW_VDLL
1490 while (pmadapter->vdll_in_progress == MTRUE)
1491 {
1492 OSA_TimeDelay(50);
1493 }
1494 #endif
1495
1496 wlan_get_fw_ver_ext(4);
1497 }
1498
1499 #if CONFIG_EXTERNAL_BLE_COEX
1500 #if CONFIG_FW_VDLL
1501 while (pmadapter->vdll_in_progress == MTRUE)
1502 {
1503 OSA_TimeDelay(50);
1504 }
1505 #endif
1506
1507 wlan_set_ext_ble_coex_mode();
1508 #endif
1509
1510 #if CONFIG_11N
1511 wifi_io_d("CMD : 11N_CFG (0xcd)");
1512
1513 #if CONFIG_FW_VDLL
1514 while (pmadapter->vdll_in_progress == MTRUE)
1515 {
1516 OSA_TimeDelay(50);
1517 }
1518 #endif
1519
1520 wlan_set_11n_cfg();
1521
1522 #if CONFIG_ENABLE_AMSDU_RX
1523 wifi_io_d("CMD : AMSDU_AGGR_CTRL (0xdf)");
1524
1525 #if CONFIG_FW_VDLL
1526 while (pmadapter->vdll_in_progress == MTRUE)
1527 {
1528 OSA_TimeDelay(50);
1529 }
1530 #endif
1531
1532 wlan_enable_amsdu();
1533
1534 #endif /* CONFIG_ENABLE_AMSDU_RX */
1535 #endif /* CONFIG_11N */
1536
1537 return;
1538 }
1539
1540 #if CONFIG_P2P
wlan_send_gen_sdio_cmd(t_u8 * buf,t_u32 buflen)1541 mlan_status wlan_send_gen_sdio_cmd(t_u8 *buf, t_u32 buflen)
1542 {
1543 SDIOPkt *sdio = (SDIOPkt *)outbuf;
1544 uint32_t resp;
1545
1546 (void)memset(outbuf, 0, 512);
1547
1548 wifi_sdio_lock();
1549 (void)memcpy((void *)outbuf, (const void *)buf, buflen);
1550 sdio->pkttype = MLAN_TYPE_CMD;
1551 sdio->hostcmd.seq_num = (0x01) << 13;
1552 sdio->size = sdio->hostcmd.size + INTF_HEADER_LEN;
1553
1554 sdio_drv_write(mlan_adap->ioport, 1, 1, buflen, (t_u8 *)outbuf, &resp);
1555
1556 last_cmd_sent = sdio->hostcmd.command;
1557 wifi_sdio_unlock();
1558
1559 return 0;
1560 }
1561 #endif
1562
1563 #if CONFIG_FW_VDLL
wlan_send_sdio_vdllcmd(t_u8 * buf,t_u32 tx_blocks,t_u32 buflen)1564 int wlan_send_sdio_vdllcmd(t_u8 *buf, t_u32 tx_blocks, t_u32 buflen)
1565 {
1566 SDIOPkt *sdio = (SDIOPkt *)(void *)outbuf;
1567 uint32_t resp;
1568
1569 (void)memcpy((void *)outbuf, (const void *)buf, tx_blocks * buflen);
1570 sdio->pkttype = MLAN_TYPE_VDLL;
1571 sdio->size = sdio->hostcmd.size + INTF_HEADER_LEN;
1572
1573 #if CONFIG_WIFI_IO_DUMP
1574 (void)PRINTF("OUT_CMD");
1575 dump_hex(outbuf, sdio->size);
1576 #endif /* CONFIG_WIFI_IO_DUMP */
1577 #if defined(SD8801)
1578 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1579 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1580 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1581 #endif
1582
1583 return WM_SUCCESS;
1584 }
1585 #endif
1586
wlan_send_sdio_cmd(t_u8 * buf,t_u32 tx_blocks,t_u32 buflen)1587 int wlan_send_sdio_cmd(t_u8 *buf, t_u32 tx_blocks, t_u32 buflen)
1588 {
1589 SDIOPkt *sdio = (SDIOPkt *)(void *)outbuf;
1590 uint32_t resp;
1591
1592 (void)wifi_sdio_lock();
1593
1594 (void)memcpy((void *)outbuf, (const void *)buf, tx_blocks * buflen);
1595 sdio->pkttype = MLAN_TYPE_CMD;
1596 sdio->size = sdio->hostcmd.size + INTF_HEADER_LEN;
1597
1598 #if CONFIG_WIFI_IO_DUMP
1599 (void)PRINTF("OUT_CMD");
1600 dump_hex(outbuf, sdio->size);
1601 #endif /* CONFIG_WIFI_IO_DUMP */
1602 #if defined(SD8801)
1603 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1604 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1605 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1606 #endif
1607
1608 last_cmd_sent = sdio->hostcmd.command;
1609 wifi_sdio_unlock();
1610
1611 return WM_SUCCESS;
1612 }
1613
wifi_send_cmdbuffer(t_u32 tx_blocks,t_u32 len)1614 int wifi_send_cmdbuffer(t_u32 tx_blocks, t_u32 len)
1615 {
1616 return wlan_send_sdio_cmd(ctrl_cmd_buf, tx_blocks, len);
1617 }
1618
1619 #if CONFIG_FW_VDLL
wifi_send_vdllcmdbuffer(t_u32 tx_blocks,t_u32 len)1620 int wifi_send_vdllcmdbuffer(t_u32 tx_blocks, t_u32 len)
1621 {
1622 return wlan_send_sdio_vdllcmd(vdll_cmd_buf, tx_blocks, len);
1623 }
1624 #endif
1625
1626 #if CONFIG_WMM
1627
1628 #if CONFIG_SDIO_MULTI_PORT_TX_AGGR
1629 static t_u32 buf_block_len = 0;
1630 static t_u8 start_port = -1;
1631 static t_u8 ports = 0;
1632 static t_u8 pkt_cnt = 0;
1633
1634 /**
1635 * @brief This function gets available SDIO port for writing data
1636 *
1637 * @param pmadapter A pointer to mlan_adapter structure
1638 * @param pport A pointer to port number
1639 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1640 */
wlan_get_wr_port_data(t_u8 * pport)1641 mlan_status wlan_get_wr_port_data(t_u8 *pport)
1642 {
1643 #if CONFIG_WIFI_IO_DEBUG
1644 t_u32 wr_bitmap = mlan_adap->mp_wr_bitmap;
1645 #endif
1646
1647 ENTER();
1648
1649 wifi_io_d("wlan_get_wr_port_data: mp_wr_bitmap=0x%08x", wr_bitmap);
1650
1651 if ((1U << txportno) & mlan_adap->mp_wr_bitmap)
1652 {
1653 mlan_adap->mp_wr_bitmap &= (t_u32)(~(1 << txportno));
1654 *pport = txportno;
1655 txportno++;
1656
1657 if (txportno == mlan_adap->mp_end_port)
1658 {
1659 #if defined(SD8801)
1660 txportno = 1;
1661 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1662 txportno = 0;
1663 #endif
1664 }
1665 }
1666 else
1667 {
1668 LEAVE();
1669 return MLAN_STATUS_RESOURCE;
1670 }
1671
1672 #if defined(SD8801)
1673 if (*pport == CTRL_PORT)
1674 {
1675 wifi_io_d("Invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\r\n", *pport, txportno, wr_bitmap,
1676 mlan_adap->mp_wr_bitmap);
1677 LEAVE();
1678 return MLAN_STATUS_FAILURE;
1679 }
1680 #endif
1681
1682 wifi_io_d("port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", *pport, wr_bitmap, mlan_adap->mp_wr_bitmap);
1683
1684 LEAVE();
1685 return MLAN_STATUS_SUCCESS;
1686 }
1687
wifi_tx_data(t_u8 start_port,t_u8 ports,t_u8 pkt_cnt,t_u32 txlen)1688 static mlan_status wifi_tx_data(t_u8 start_port, t_u8 ports, t_u8 pkt_cnt, t_u32 txlen)
1689 {
1690 t_u32 cmd53_port;
1691 t_u32 tx_blocks = 0, buflen = 0;
1692 uint32_t resp;
1693 bool ret;
1694 #if CONFIG_WIFI_FW_DEBUG
1695 int ret_cb;
1696 #endif
1697 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1698 t_u32 port_count = 0;
1699 #endif
1700
1701 calculate_sdio_write_params(txlen, &tx_blocks, &buflen);
1702
1703 if (pkt_cnt == 1)
1704 {
1705 cmd53_port = mlan_adap->ioport + start_port;
1706 }
1707 else
1708 {
1709 #if defined(SD8801)
1710 cmd53_port = (mlan_adap->ioport | SDIO_MPA_ADDR_BASE | (ports << 4)) + start_port;
1711 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1712 port_count = ports - 1U;
1713 cmd53_port = (mlan_adap->ioport | SDIO_MPA_ADDR_BASE | (port_count << 8)) + start_port;
1714 #endif
1715 }
1716
1717 //(void)PRINTF("cmd53_port=%x, ports=%x, start_port=%x, pkt_cnt=%d, txlen=%d, txblocks=%d\r\n", cmd53_port, ports, start_port, pkt_cnt, txlen, tx_blocks);
1718
1719 /* send CMD53 */
1720 ret = sdio_drv_write(cmd53_port, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1721
1722 if (ret == false)
1723 {
1724 wifi_io_e("sdio_drv_write failed (%d)", ret);
1725 #if CONFIG_WIFI_FW_DEBUG
1726 wifi_sdio_reg_dbg(NULL);
1727 if (wm_wifi.wifi_usb_mount_cb != NULL)
1728 {
1729 ret_cb = wm_wifi.wifi_usb_mount_cb();
1730 if (ret_cb == WM_SUCCESS)
1731 wifi_dump_firmware_info(NULL);
1732 else
1733 wifi_e("USB mounting failed");
1734 }
1735 else
1736 wifi_e("USB mount callback is not registered");
1737 #endif
1738 return MLAN_STATUS_RESOURCE;
1739 }
1740 return MLAN_STATUS_SUCCESS;
1741 }
1742
wlan_xmit_wmm_pkt(t_u8 interface,t_u32 txlen,t_u8 * tx_buf)1743 mlan_status wlan_xmit_wmm_pkt(t_u8 interface, t_u32 txlen, t_u8 *tx_buf)
1744 {
1745 t_u32 tx_blocks = 0, buflen = 0;
1746 mlan_status ret = MLAN_STATUS_SUCCESS;
1747 #if CONFIG_WMM_UAPSD
1748 bool last_packet = 0;
1749 #endif
1750 t_u8 port = 0;
1751
1752 if (buf_block_len == 0)
1753 {
1754 start_port = -1;
1755 ports = 0;
1756 pkt_cnt = 0;
1757 }
1758
1759 calculate_sdio_write_params(txlen, &tx_blocks, &buflen);
1760
1761 #if CONFIG_WIFI_IO_DEBUG
1762 (void)PRINTF("%s: txportno = %d mlan_adap->mp_wr_bitmap: %x\n\r", __func__, txportno, mlan_adap->mp_wr_bitmap);
1763 #endif /* CONFIG_WIFI_IO_DEBUG */
1764
1765 ret = wlan_get_wr_port_data(&port);
1766 if (ret != WM_SUCCESS)
1767 {
1768 return MLAN_STATUS_RESOURCE;
1769 }
1770
1771 #if CONFIG_WMM_UAPSD
1772 if (mlan_adap->priv[interface]->adapter->pps_uapsd_mode &&
1773 wifi_check_last_packet_indication(mlan_adap->priv[interface]))
1774 {
1775 #if CONFIG_TX_RX_ZERO_COPY
1776 process_pkt_hdrs_flags(&((outbuf_t *)tx_buf)->intf_header[0], MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
1777 #else
1778 process_pkt_hdrs_flags((t_u8 *)tx_buf, MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
1779 #endif
1780 last_packet = 1;
1781 }
1782 #endif
1783
1784 if (buf_block_len == 0)
1785 {
1786 start_port = port;
1787 }
1788
1789 #if CONFIG_TX_RX_ZERO_COPY
1790 net_tx_zerocopy_process_cb(outbuf + buf_block_len, tx_buf, txlen);
1791 #else
1792 memcpy(outbuf + buf_block_len, tx_buf, txlen);
1793 #endif
1794
1795 buf_block_len += tx_blocks * buflen;
1796
1797 ports++;
1798 pkt_cnt++;
1799
1800 #if CONFIG_WMM_UAPSD
1801 if (last_packet)
1802 {
1803 mlan_adap->priv[interface]->adapter->tx_lock_flag = MTRUE;
1804 OSA_SemaphoreWait((osa_semaphore_handle_t)uapsd_sem, osaWaitForever_c);
1805 }
1806 #endif
1807
1808 wifi_io_info_d("OUT: i/f: %d, len: %d, start port: %d, pkt_cnt: %d, bufblocklen %d", interface, tx_blocks * buflen, start_port, pkt_cnt, buf_block_len);
1809
1810 return MLAN_STATUS_SUCCESS;
1811 }
1812
wlan_flush_wmm_pkt(t_u8 pkt_count)1813 mlan_status wlan_flush_wmm_pkt(t_u8 pkt_count)
1814 {
1815 int ret;
1816
1817 if (pkt_count == 0)
1818 return MLAN_STATUS_SUCCESS;
1819
1820 w_pkt_d("Data TX: Driver=>FW, pkt_count %d", pkt_cnt);
1821
1822 ret = wifi_tx_data(start_port, ports, pkt_cnt, buf_block_len);
1823
1824 buf_block_len = 0;
1825
1826 if (ret != MLAN_STATUS_SUCCESS)
1827 {
1828 return MLAN_STATUS_RESOURCE;
1829 }
1830
1831 return MLAN_STATUS_SUCCESS;
1832 }
1833 #else
1834 extern int retry_attempts;
1835
get_free_port(void)1836 static int get_free_port(void)
1837 {
1838 /* Check if the port is available */
1839 if (!((1 << txportno) & mlan_adap->mp_wr_bitmap))
1840 {
1841 #if CONFIG_WIFI_IO_DEBUG
1842 wifi_io_e(
1843 "txportno out of sync txportno "
1844 "= (%d) mp_wr_bitmap = (0x%x)",
1845 txportno, mlan_adap->mp_wr_bitmap);
1846 #endif /* CONFIG_WIFI_IO_DEBUG */
1847
1848 return -WM_FAIL;
1849 }
1850 else
1851 {
1852 /* Mark the port number we will use */
1853 mlan_adap->mp_wr_bitmap &= ~(1 << txportno);
1854 }
1855 return WM_SUCCESS;
1856 }
1857
wlan_xmit_wmm_pkt(t_u8 interface,t_u32 txlen,t_u8 * tx_buf)1858 mlan_status wlan_xmit_wmm_pkt(t_u8 interface, t_u32 txlen, t_u8 *tx_buf)
1859 {
1860 t_u32 tx_blocks = 0, buflen = 0;
1861 uint32_t resp;
1862 int ret = false;
1863 int retry = retry_attempts;
1864 #if CONFIG_WMM_UAPSD
1865 bool last_packet = 0;
1866 #endif
1867
1868 wifi_io_info_d("OUT: i/f: %d len: %d", interface, tx_blocks * buflen);
1869
1870 calculate_sdio_write_params(txlen, &tx_blocks, &buflen);
1871
1872 #if CONFIG_WIFI_IO_DEBUG
1873 (void)PRINTF("%s: txportno = %d mlan_adap->mp_wr_bitmap: %x\n\r", __func__, txportno, mlan_adap->mp_wr_bitmap);
1874 #endif /* CONFIG_WIFI_IO_DEBUG */
1875
1876 retry_xmit:
1877 ret = get_free_port();
1878 if (ret == -WM_FAIL)
1879 {
1880 if (!retry)
1881 {
1882 ret = MLAN_STATUS_RESOURCE;
1883 goto exit_fn;
1884 }
1885 else
1886 {
1887 retry--;
1888 /* Allow the other thread to run and hence
1889 * update the write bitmap so that pkt
1890 * can be sent to FW */
1891 OSA_TimeDelay(1);
1892 goto retry_xmit;
1893 }
1894 }
1895
1896 #if CONFIG_WMM_UAPSD
1897 if (mlan_adap->priv[interface]->adapter->pps_uapsd_mode &&
1898 wifi_check_last_packet_indication(mlan_adap->priv[interface]))
1899 {
1900 process_pkt_hdrs_flags((t_u8 *)tx_buf, MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
1901 last_packet = 1;
1902 }
1903 #endif
1904
1905 /* send CMD53 */
1906 ret = sdio_drv_write(mlan_adap->ioport + txportno, 1, tx_blocks, buflen, tx_buf, &resp);
1907
1908 txportno++;
1909 if (txportno == mlan_adap->mp_end_port)
1910 {
1911 #if defined(SD8801)
1912 txportno = 1;
1913 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1914 txportno = 0;
1915 #endif
1916 }
1917
1918 if (ret == false)
1919 {
1920 #if CONFIG_WMM_UAPSD
1921 if (last_packet)
1922 process_pkt_hdrs_flags((t_u8 *)tx_buf, 0);
1923 #endif
1924
1925 wifi_io_e("sdio_drv_write failed (%d)", ret);
1926 #if CONFIG_WIFI_FW_DEBUG
1927 wifi_sdio_reg_dbg(NULL);
1928 if (wm_wifi.wifi_usb_mount_cb != NULL)
1929 {
1930 ret = wm_wifi.wifi_usb_mount_cb();
1931 if (ret == WM_SUCCESS)
1932 wifi_dump_firmware_info(NULL);
1933 else
1934 wifi_e("USB mounting failed");
1935 }
1936 else
1937 wifi_e("USB mount callback is not registered");
1938 #endif
1939 ret = MLAN_STATUS_RESOURCE;
1940 goto exit_fn;
1941 }
1942
1943 #if CONFIG_WMM_UAPSD
1944 if (last_packet)
1945 {
1946 mlan_adap->priv[interface]->adapter->tx_lock_flag = MTRUE;
1947 OSA_SemaphoreWait((osa_semaphore_handle_t)uapsd_sem, osaWaitForever_c);
1948 }
1949 #endif
1950
1951 ret = MLAN_STATUS_SUCCESS;
1952
1953 exit_fn:
1954
1955 return ret;
1956 }
1957
wlan_flush_wmm_pkt(t_u8 pkt_count)1958 mlan_status wlan_flush_wmm_pkt(t_u8 pkt_count)
1959 {
1960 return MLAN_STATUS_SUCCESS;
1961 }
1962
1963 #endif
1964 #endif
1965
wlan_xmit_pkt(t_u8 * buffer,t_u32 txlen,t_u8 interface,t_u32 tx_control)1966 mlan_status wlan_xmit_pkt(t_u8 *buffer, t_u32 txlen, t_u8 interface, t_u32 tx_control)
1967 {
1968
1969 (void)interface;
1970
1971 wifi_io_info_d("OUT: i/f: %d len: %d", interface, txlen);
1972
1973 process_pkt_hdrs((t_u8 *)buffer, txlen, interface, 0, tx_control);
1974
1975 return wifi_send_fw_data(buffer, txlen);
1976 }
1977
1978 #if CONFIG_WMM
wlan_xmit_bypass_pkt(t_u8 * buffer,t_u32 txlen,t_u8 interface)1979 mlan_status wlan_xmit_bypass_pkt(t_u8 *buffer, t_u32 txlen, t_u8 interface)
1980 {
1981
1982 (void)interface;
1983
1984 wifi_io_info_d("OUT: i/f: %d len: %d", interface, txlen);
1985
1986 return wifi_send_fw_data(buffer, txlen);
1987 }
1988 #endif
1989
wlan_send_null_packet(pmlan_private priv,t_u8 flags)1990 mlan_status wlan_send_null_packet(pmlan_private priv, t_u8 flags)
1991 {
1992 mlan_status ret;
1993 t_u8 pbuf[128] = {0};
1994 TxPD *ptxpd = (TxPD *)((uint8_t *)pbuf + INTF_HEADER_LEN);
1995
1996 ptxpd->bss_type = priv->bss_type;
1997 ptxpd->bss_num = GET_BSS_NUM(priv);
1998 ptxpd->tx_pkt_offset = 0x16; /* we'll just make this constant */
1999 ptxpd->tx_pkt_length = 0;
2000 ptxpd->tx_control = 0;
2001 ptxpd->priority = 0;
2002 ptxpd->flags = flags;
2003 ptxpd->pkt_delay_2ms = 0;
2004
2005 ret = wifi_send_fw_data(pbuf, sizeof(TxPD) + INTF_HEADER_LEN);
2006
2007 if (ret != MLAN_STATUS_SUCCESS)
2008 {
2009 wifi_io_d("sdio_drv_write failed (%d)", ret);
2010 return MLAN_STATUS_FAILURE;
2011 }
2012
2013 return MLAN_STATUS_SUCCESS;
2014 }
2015
2016 /*
2017 * This function gets interrupt status.
2018 */
wlan_interrupt(mlan_adapter * pmadapter)2019 t_void wlan_interrupt(mlan_adapter *pmadapter)
2020 {
2021 /* Read SDIO multiple port group registers */
2022 uint32_t resp = 0;
2023 int ret;
2024 t_u8 *mp_regs = pmadapter->mp_regs;
2025
2026 /* Read the registers in DMA aligned buffer */
2027 #if defined(SD8801)
2028 ret = sdio_drv_read(0, 1, 1, MAX_MP_REGS, mp_regs, &resp);
2029 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2030 ret = sdio_drv_read(REG_PORT | MLAN_SDIO_BYTE_MODE_MASK, 1, 1, MAX_MP_REGS, mp_regs, &resp);
2031 #endif
2032
2033 if (!ret)
2034 {
2035 return;
2036 }
2037
2038 t_u8 sdio_ireg = mp_regs[HOST_INT_STATUS_REG];
2039
2040 if (sdio_ireg != 0U)
2041 {
2042 /*
2043 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
2044 * Clear the interrupt status register
2045 */
2046 pmadapter->sdio_ireg |= sdio_ireg;
2047 }
2048
2049 #if CONFIG_WMM
2050 t_u32 wr_bitmap;
2051
2052 #if defined(SD8801)
2053 wr_bitmap = ((t_u16)mp_regs[WR_BITMAP_U]) << 8;
2054 wr_bitmap |= (t_u16)mp_regs[WR_BITMAP_L];
2055 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2056 wr_bitmap = (t_u32)mp_regs[WR_BITMAP_L];
2057 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_U]) << 8;
2058 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_1L]) << 16;
2059 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_1U]) << 24;
2060 #endif
2061
2062 if (!!wr_bitmap)
2063 {
2064 if (mlan_adap->wait_txbuf == true)
2065 {
2066 OSA_SemaphorePost((osa_semaphore_handle_t)txbuf_sem);
2067 send_wifi_driver_tx_data_event(0);
2068 }
2069 }
2070 #endif
2071
2072 #if CONFIG_WIFI_IO_DEBUG
2073 t_u32 rd_bitmap;
2074 #if !CONFIG_WMM
2075 t_u32 wr_bitmap;
2076
2077 #if defined(SD8801)
2078 wr_bitmap = ((t_u16)mp_regs[WR_BITMAP_U]) << 8;
2079 wr_bitmap |= (t_u16)mp_regs[WR_BITMAP_L];
2080 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2081 wr_bitmap = (t_u32)mp_regs[WR_BITMAP_L];
2082 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_U]) << 8;
2083 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_1L]) << 16;
2084 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_1U]) << 24;
2085 #endif
2086
2087 #endif
2088 #if defined(SD8801)
2089 rd_bitmap = ((t_u16)mp_regs[RD_BITMAP_U]) << 8;
2090 rd_bitmap |= (t_u16)mp_regs[RD_BITMAP_L];
2091 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2092 rd_bitmap = (t_u32)mp_regs[RD_BITMAP_L];
2093 rd_bitmap |= ((t_u32)mp_regs[RD_BITMAP_U]) << 8;
2094 rd_bitmap |= ((t_u32)mp_regs[RD_BITMAP_1L]) << 16;
2095 rd_bitmap |= ((t_u32)mp_regs[RD_BITMAP_1U]) << 24;
2096 #endif
2097
2098 (void)PRINTF("INT : rd_bitmap=0x%x\n\r", rd_bitmap);
2099
2100 (void)PRINTF("INT : wr_bitmap=0x%x\n\r", wr_bitmap);
2101
2102 (void)PRINTF("INT : sdio_ireg = (0x%x)\r\n", sdio_ireg);
2103 #endif /* CONFIG_WIFI_IO_DEBUG */
2104 }
2105
2106 #if CONFIG_TP_OPTIMIZATIONS
bitcount(t_u32 num)2107 static t_u32 bitcount(t_u32 num)
2108 {
2109 t_u32 count = 0;
2110 static t_u32 nibblebits[] = { 0, 1, 1, 2, 1, 2, 2, 3,
2111 1, 2, 2, 3, 2, 3, 3, 4 };
2112 for (; num != 0; num >>= 4)
2113 count += nibblebits[num & 0x0f];
2114 return count;
2115 }
2116 #endif
2117 #if CONFIG_SDIO_MULTI_PORT_RX_AGGR
2118 #if CONFIG_TP_OPTIMIZATIONS
2119 static t_u8 start_check = 0;
2120 static t_u8 skip_int = 0;
2121 #endif
2122
2123 /* returns port number from rd_bitmap. if ctrl port, then it clears
2124 * the bit and does nothing else
2125 * if data port then increments curr_port value also */
wlan_get_rd_port(mlan_adapter * pmadapter,t_u32 * pport,t_u32 * rxlen,t_u32 * rxblocks,bool * aggr)2126 static mlan_status wlan_get_rd_port(mlan_adapter *pmadapter, t_u32 *pport, t_u32 *rxlen, t_u32 *rxblocks, bool *aggr)
2127 {
2128 #if defined(SD8801)
2129 t_u16 rd_bitmap = pmadapter->mp_rd_bitmap;
2130 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2131 t_u32 rd_bitmap = pmadapter->mp_rd_bitmap;
2132 #endif
2133 t_u16 pkt_cnt = 0;
2134 t_u32 len_reg_l, len_reg_u;
2135 t_u32 rx_len;
2136 t_u32 rx_blocks;
2137 t_u16 ports = 0;
2138 t_u32 start_port = -1;
2139 t_u32 cmd53_port = 0;
2140 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2141 t_u32 port_count = 0;
2142 #endif
2143 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2144 uint32_t *rxdataAddr = NULL;
2145 #endif
2146
2147 *pport = -1;
2148 *rxlen = 0;
2149 *rxblocks = 0;
2150
2151 wifi_io_d(
2152 "wlan_get_rd_port: mp_rd_bitmap=0x%x"
2153 " curr_rd_bitmap=0x%x\r\n",
2154 pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port);
2155
2156 #if defined(SD8801)
2157 if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK)))
2158 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2159 if (!(rd_bitmap & DATA_PORT_MASK))
2160 #endif
2161 {
2162 return MLAN_STATUS_FAILURE;
2163 }
2164
2165 #if defined(SD8801)
2166 if (pmadapter->mp_rd_bitmap & CTRL_PORT_MASK)
2167 {
2168 pmadapter->mp_rd_bitmap &= (t_u32)(~CTRL_PORT_MASK);
2169 *pport = CTRL_PORT;
2170
2171 len_reg_l = RD_LEN_P0_L + (*pport << 1);
2172 len_reg_u = RD_LEN_P0_U + (*pport << 1);
2173 rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
2174 rx_len |= (t_u16)pmadapter->mp_regs[len_reg_l];
2175 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) / MLAN_SDIO_BLOCK_SIZE;
2176 rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2177 *rxlen = rx_len;
2178 *rxblocks = rx_blocks;
2179
2180 *pport = mlan_adap->ioport + *pport;
2181
2182 wifi_io_d("RX: port=%d rxlen=%u rx_blocks=%u\r\n", *pport, *rxlen, *rxblocks);
2183
2184 wifi_io_d("wlan_get_rd_port: port=%d mp_rd_bitmap=0x%04x", *pport, pmadapter->mp_rd_bitmap);
2185 }
2186 else
2187 {
2188 #endif
2189
2190 #if CONFIG_TP_OPTIMIZATIONS
2191 /* This change is being added to handle low throughput caused for Tx due to excess interrupts received for Rx.
2192 * The intention is to ignore the interrupt if received agreggated packets are less than 4.
2193 * However, there could be single data packets during DHCP request, etc. whose Rx interrupt should not be skipped.
2194 * For actual data, we are checking if read bitmap has at least 4 ports available if current read port is 27.
2195 * If current read port is greater than 27 then any number of available ports is fine. */
2196 if (bitcount(pmadapter->mp_rd_bitmap) == 8U)
2197 {
2198 start_check = 1;
2199 }
2200
2201 if (skip_int == 2)
2202 {
2203 start_check = 0;
2204 }
2205 /* Data */
2206 if ((start_check) && ((pmadapter->mp_rd_bitmap & ((pmadapter->curr_rd_port > 27 ? 1U : 0xFU) << pmadapter->curr_rd_port)) == 0U))
2207 {
2208 skip_int++;
2209 return MLAN_STATUS_FAILURE;
2210 }
2211 #endif
2212 while ((pmadapter->mp_rd_bitmap & (1U << pmadapter->curr_rd_port)) != 0U)
2213 {
2214 *pport = pmadapter->curr_rd_port;
2215
2216 len_reg_l = RD_LEN_P0_L + (*pport << 1U);
2217 len_reg_u = RD_LEN_P0_U + (*pport << 1U);
2218 rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
2219 rx_len |= (t_u16)pmadapter->mp_regs[len_reg_l];
2220 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1U) / MLAN_SDIO_BLOCK_SIZE;
2221 rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2222 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2223 if (wm_wifi.wifi_get_rxbuf_desc != NULL)
2224 {
2225 rxdataAddr = (uint32_t *)wm_wifi.wifi_get_rxbuf_desc(rx_len);
2226
2227 if (rxdataAddr == NULL)
2228 {
2229 PRINTF("No pbuf\r\n");
2230 break;
2231 }
2232 }
2233 #else
2234 if ((*rxlen + rx_len) > INBUF_SIZE)
2235 {
2236 break;
2237 }
2238 #endif
2239
2240 pmadapter->mp_rd_bitmap &=
2241 #if defined(SD8801)
2242 (t_u16)(~(1 << pmadapter->curr_rd_port));
2243 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2244 (t_u32)(~(1 << pmadapter->curr_rd_port));
2245 #endif
2246
2247 #if defined(SD8801)
2248 if (!pkt_cnt)
2249 start_port = *pport;
2250 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2251 if (start_port == -1)
2252 {
2253 start_port = *pport;
2254 }
2255 #endif
2256
2257 #if defined(SD8801)
2258 if (start_port <= *pport)
2259 {
2260 ports |= (1 << (pkt_cnt));
2261 }
2262 else
2263 {
2264 ports |= (1 << (pkt_cnt + 1));
2265 }
2266 #endif
2267 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2268 if (rxdataAddr)
2269 {
2270 sg_set_buf(rxdataAddr, rx_len);
2271 num_sg++;
2272 }
2273 #endif
2274
2275 *rxlen += rx_len;
2276 *rxblocks += rx_blocks;
2277
2278 //PRINTF("RX: port=%d rxlen=%u rx_blocks=%u\r\n", *pport, *rxlen, *rxblocks);
2279
2280 if (++pmadapter->curr_rd_port == MAX_PORT)
2281 {
2282 #if defined(SD8801)
2283 pmadapter->curr_rd_port = 1;
2284 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2285 pmadapter->curr_rd_port = 0;
2286 #endif
2287 }
2288
2289 pkt_cnt++;
2290 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2291 ports++;
2292 #endif
2293
2294 if (pkt_cnt == SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX)
2295 {
2296 break;
2297 }
2298 #if defined(SD8801)
2299 if ((pmadapter->curr_rd_port < start_port) &&
2300 (((MAX_PORT - start_port) + pmadapter->curr_rd_port) >= SDIO_MP_AGGR_DEF_PKT_LIMIT))
2301 {
2302 break;
2303 }
2304 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2305 if (((pmadapter->curr_rd_port < start_port) &&
2306 (((MAX_PORT - start_port) + pmadapter->curr_rd_port) >= (pmadapter->mp_end_port >> 1))) ||
2307 ((pmadapter->curr_rd_port - start_port) >= (pmadapter->mp_end_port >> 1)))
2308 {
2309 break;
2310 }
2311 #endif
2312 }
2313
2314 if (*pport == -1 || ports == 0)
2315 {
2316 wifi_io_e("wlan_get_rd_port : Returning FAILURE");
2317 return MLAN_STATUS_FAILURE;
2318 }
2319
2320 #if defined(SD8801)
2321 if (pkt_cnt > 1)
2322 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2323 if (ports > 1U)
2324 #endif
2325 {
2326 #if defined(SD8801)
2327 cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE | (ports << 4)) + start_port;
2328 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2329 port_count = ports - 1U;
2330 cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE | (port_count << 8)) + start_port;
2331 #endif
2332 *pport = cmd53_port;
2333
2334 *aggr = true;
2335
2336 //(void)PRINTF("cmd53_port=%x, ports=%x, start_port=%x rxlen=%d rxblocks=%d\r\n", cmd53_port, ports,
2337 //start_port, *rxlen, *rxblocks);
2338 }
2339 else
2340 {
2341 *pport = mlan_adap->ioport + *pport;
2342 }
2343
2344 wifi_io_d("port=%x mp_rd_bitmap=0x%x -> 0x%x\n", *pport, rd_bitmap, pmadapter->mp_rd_bitmap);
2345 #if defined(SD8801)
2346 }
2347 #endif
2348
2349 return MLAN_STATUS_SUCCESS;
2350 }
2351
2352 /*
2353 * Assumes that pmadapter->mp_rd_bitmap contains latest values
2354 */
_handle_sdio_packet_read(mlan_adapter * pmadapter,t_u8 ** packet,t_u32 * datalen,t_u32 * pkt_type)2355 static mlan_status _handle_sdio_packet_read(mlan_adapter *pmadapter, t_u8 **packet, t_u32 *datalen, t_u32 *pkt_type)
2356 {
2357 t_u32 port;
2358 t_u32 rx_len = 0, rx_blocks = 0;
2359 bool aggr = false;
2360
2361 mlan_status ret = wlan_get_rd_port(pmadapter, &port, &rx_len, &rx_blocks, &aggr);
2362
2363 /* nothing to read */
2364 if (ret != MLAN_STATUS_SUCCESS)
2365 {
2366 return ret;
2367 }
2368
2369 *datalen = rx_len;
2370
2371 *packet = wlan_read_rcv_packet(port, rx_len, rx_blocks, pkt_type, aggr);
2372
2373 if ((*packet) == MNULL)
2374 {
2375 return MLAN_STATUS_FAILURE;
2376 }
2377
2378 return MLAN_STATUS_SUCCESS;
2379 }
2380 #else
2381 /* returns port number from rd_bitmap. if ctrl port, then it clears
2382 * the bit and does nothing else
2383 * if data port then increments curr_port value also */
wlan_get_rd_port(mlan_adapter * pmadapter,t_u32 * pport)2384 static mlan_status wlan_get_rd_port(mlan_adapter *pmadapter, t_u32 *pport)
2385 {
2386 #if defined(SD8801)
2387 t_u16 rd_bitmap = pmadapter->mp_rd_bitmap;
2388 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2389 t_u32 rd_bitmap = pmadapter->mp_rd_bitmap;
2390 #endif
2391
2392 wifi_io_d(
2393 "wlan_get_rd_port: mp_rd_bitmap=0x%x"
2394 " curr_rd_bitmap=0x%x",
2395 pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port);
2396
2397 #if defined(SD8801)
2398 if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK)))
2399 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2400 if (!(rd_bitmap & DATA_PORT_MASK))
2401 #endif
2402 return MLAN_STATUS_FAILURE;
2403
2404 #if defined(SD8801)
2405 if (pmadapter->mp_rd_bitmap & CTRL_PORT_MASK)
2406 {
2407 pmadapter->mp_rd_bitmap &= (t_u16)(~CTRL_PORT_MASK);
2408 *pport = CTRL_PORT;
2409
2410 wifi_io_d("wlan_get_rd_port: port=%d mp_rd_bitmap=0x%04x", *pport, pmadapter->mp_rd_bitmap);
2411 }
2412 else
2413 {
2414 #endif
2415 /* Data */
2416 if ((pmadapter->mp_rd_bitmap & (1 << pmadapter->curr_rd_port)) != 0U)
2417 {
2418 pmadapter->mp_rd_bitmap &=
2419 #if defined(SD8801)
2420 (t_u16)(~(1 << pmadapter->curr_rd_port));
2421 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2422 (t_u32)(~(1 << pmadapter->curr_rd_port));
2423 #endif
2424 *pport = pmadapter->curr_rd_port;
2425
2426 if (++pmadapter->curr_rd_port == MAX_PORT)
2427 #if defined(SD8801)
2428 pmadapter->curr_rd_port = 1;
2429 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2430 pmadapter->curr_rd_port = 0;
2431 #endif
2432 }
2433 else
2434 {
2435 wifi_io_e("wlan_get_rd_port : Returning FAILURE");
2436 return MLAN_STATUS_FAILURE;
2437 }
2438
2439 wifi_io_d("port=%d mp_rd_bitmap=0x%x -> 0x%x\n", *pport, rd_bitmap, pmadapter->mp_rd_bitmap);
2440 #if defined(SD8801)
2441 }
2442 #endif
2443
2444 return MLAN_STATUS_SUCCESS;
2445 }
2446
2447 /*
2448 * Assumes that pmadapter->mp_rd_bitmap contains latest values
2449 */
_handle_sdio_packet_read(mlan_adapter * pmadapter,t_u8 ** packet,t_u32 * datalen,t_u32 * pkt_type)2450 static mlan_status _handle_sdio_packet_read(mlan_adapter *pmadapter, t_u8 **packet, t_u32 *datalen, t_u32 *pkt_type)
2451 {
2452 t_u32 port;
2453 t_u32 rx_len, rx_blocks;
2454
2455 mlan_status ret = wlan_get_rd_port(pmadapter, &port);
2456
2457 /* nothing to read */
2458 if (ret != MLAN_STATUS_SUCCESS)
2459 return ret;
2460
2461 t_u32 len_reg_l = RD_LEN_P0_L + (port << 1);
2462 t_u32 len_reg_u = RD_LEN_P0_U + (port << 1);
2463
2464 rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
2465 *datalen = rx_len |= (t_u16)pmadapter->mp_regs[len_reg_l];
2466
2467 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) / MLAN_SDIO_BLOCK_SIZE;
2468 rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2469
2470 port = mlan_adap->ioport + port;
2471
2472 *packet = wlan_read_rcv_packet(port, rx_len, rx_blocks, pkt_type, false);
2473
2474 if (!*packet)
2475 return MLAN_STATUS_FAILURE;
2476
2477 return MLAN_STATUS_SUCCESS;
2478 }
2479 #endif
2480
2481 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
_handle_sdio_cmd_read(mlan_adapter * pmadapter,t_u8 ** packet,t_u32 * datalen,t_u32 * pkt_type,t_u32 rx_len,t_u32 rx_blocks)2482 static mlan_status _handle_sdio_cmd_read(
2483 mlan_adapter *pmadapter, t_u8 **packet, t_u32 *datalen, t_u32 *pkt_type, t_u32 rx_len, t_u32 rx_blocks)
2484 {
2485 *datalen = rx_len;
2486
2487 *packet = wlan_read_rcv_packet(mlan_adap->ioport | CMD_PORT_SLCT, rx_len, rx_blocks, pkt_type, false);
2488
2489 if ((*packet) == MNULL)
2490 {
2491 return MLAN_STATUS_FAILURE;
2492 }
2493
2494 return MLAN_STATUS_SUCCESS;
2495 }
2496 /*
2497 * This function keeps on looping till all the packets are read
2498 */
handle_sdio_cmd_read(mlan_adapter * pmadapter,t_u32 rx_len,t_u32 rx_blocks)2499 static void handle_sdio_cmd_read(mlan_adapter *pmadapter, t_u32 rx_len, t_u32 rx_blocks)
2500 {
2501 t_u32 datalen = 0;
2502
2503 t_u32 pkt_type = 0;
2504 t_u8 *packet = NULL;
2505
2506 (void)_handle_sdio_cmd_read(pmadapter, &packet, &datalen, &pkt_type, rx_len, rx_blocks);
2507 if (pkt_type == MLAN_TYPE_CMD || pkt_type == MLAN_TYPE_EVENT)
2508 {
2509 /* non-data packets such as events
2510 and command responses are
2511 handled here */
2512 (void)wlan_decode_rx_packet(packet, pkt_type);
2513 }
2514 }
2515 #endif
2516
2517 /*
2518 * This function keeps on looping till all the packets are read
2519 */
handle_sdio_packet_read(mlan_adapter * pmadapter)2520 static void handle_sdio_packet_read(mlan_adapter *pmadapter)
2521 {
2522 mlan_status ret = MLAN_STATUS_SUCCESS;
2523 t_u32 datalen = 0;
2524
2525 pmadapter->mp_rd_bitmap =
2526 #if defined(SD8801)
2527 ((t_u16)pmadapter->mp_regs[RD_BITMAP_U]) << 8;
2528 pmadapter->mp_rd_bitmap |= (t_u16)pmadapter->mp_regs[RD_BITMAP_L];
2529 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2530 (t_u32)pmadapter->mp_regs[RD_BITMAP_L];
2531 pmadapter->mp_rd_bitmap |= ((t_u32)pmadapter->mp_regs[RD_BITMAP_U]) << 8;
2532 pmadapter->mp_rd_bitmap |= ((t_u32)pmadapter->mp_regs[RD_BITMAP_1L]) << 16;
2533 pmadapter->mp_rd_bitmap |= ((t_u32)pmadapter->mp_regs[RD_BITMAP_1U]) << 24;
2534 #endif
2535
2536 while (true)
2537 {
2538 t_u32 pkt_type = 0;
2539 #if !FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2540 t_u8 interface;
2541 t_u32 rx_blocks;
2542 t_u32 total_size = 0;
2543 t_u32 size = 0;
2544 #endif
2545 t_u8 *packet = NULL;
2546
2547 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2548 num_sg = 0;
2549 sg_init_table();
2550 #endif
2551
2552 ret = _handle_sdio_packet_read(pmadapter, &packet, &datalen, &pkt_type);
2553 if (ret != MLAN_STATUS_SUCCESS)
2554 {
2555 /* nothing to read. break out of while loop */
2556 break;
2557 }
2558
2559 if (pkt_type == MLAN_TYPE_DATA)
2560 {
2561
2562 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2563 if (num_sg > 0)
2564 {
2565 // extern void net_rx_notify();
2566
2567 // net_rx_notify();
2568 wm_wifi.data_input_callback(0, NULL, 0);
2569 #if 0
2570 for (sg_idx = 0; sg_idx < num_sg; sg_idx++)
2571 {
2572 SDIOPkt *insdiopkt = (SDIOPkt *)(void *)rx_bufs[sg_idx];
2573 size = insdiopkt->size;
2574 pkt_type = insdiopkt->pkttype;
2575
2576 interface = *((t_u8 *)packet + INTF_HEADER_LEN);
2577
2578 //PRINTF("IN: i/f: %d len: %d\r\n", interface, size);
2579
2580 if (bus.wifi_low_level_input != NULL)
2581 {
2582 (void)bus.wifi_low_level_input(interface, rx_bufs[sg_idx], size);
2583 }
2584 }
2585 #endif
2586 }
2587 #else
2588 {
2589 while (total_size < datalen)
2590 {
2591 SDIOPkt *insdiopkt = (SDIOPkt *)(void *)packet;
2592 size = insdiopkt->size;
2593 pkt_type = insdiopkt->pkttype;
2594
2595 rx_blocks = (size + MLAN_SDIO_BLOCK_SIZE - 1U) / MLAN_SDIO_BLOCK_SIZE;
2596 size = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2597
2598 interface = *((t_u8 *)packet + INTF_HEADER_LEN);
2599
2600 //PRINTF("IN: i/f: %d len: %d\r\n", interface, size);
2601
2602 if (!size)
2603 {
2604 break;
2605 }
2606
2607 if (bus.wifi_low_level_input != NULL)
2608 {
2609 (void)bus.wifi_low_level_input(interface, packet, size);
2610 }
2611
2612 packet += size;
2613 total_size += size;
2614 }
2615 }
2616 #endif
2617 }
2618 else
2619 {
2620 /* non-data packets such as events
2621 and command responses are
2622 handled here */
2623 (void)wlan_decode_rx_packet(packet, pkt_type);
2624 }
2625 }
2626 }
2627
2628 /*
2629 * This is supposed to be called in thread context.
2630 */
wlan_process_int_status(mlan_adapter * pmadapter)2631 mlan_status wlan_process_int_status(mlan_adapter *pmadapter)
2632 {
2633 mlan_status ret = MLAN_STATUS_SUCCESS;
2634 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2635 t_u8 cmd_rd_len_0 = CMD_RD_LEN_0;
2636 t_u8 cmd_rd_len_1 = CMD_RD_LEN_1;
2637 t_u32 rx_len;
2638 t_u32 rx_blocks;
2639 #endif
2640
2641 /* Get the interrupt status */
2642 wlan_interrupt(pmadapter);
2643
2644 t_u8 sdio_ireg = pmadapter->sdio_ireg;
2645 pmadapter->sdio_ireg = 0;
2646
2647 if (!sdio_ireg)
2648 {
2649 goto done;
2650 }
2651
2652 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2653 /* check the command port */
2654 if ((sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS) != 0U)
2655 {
2656 if (pmadapter->cmd_sent != 0U)
2657 {
2658 pmadapter->cmd_sent = MFALSE;
2659 }
2660 PRINTM(MINFO, "cmd_sent=%d\n", pmadapter->cmd_sent);
2661 }
2662
2663 if ((sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) != 0U)
2664 {
2665 /* read the len of control packet */
2666 rx_len = ((t_u32)pmadapter->mp_regs[cmd_rd_len_1]) << 8;
2667 rx_len |= (t_u32)pmadapter->mp_regs[cmd_rd_len_0];
2668 PRINTM(MINFO, "RX: cmd port rx_len=%u\n", rx_len);
2669
2670 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1U) / MLAN_SDIO_BLOCK_SIZE;
2671
2672 // (void)PRINTF("CMD: cmd port rx_len=%u rx_blocks=%u\r\n", rx_len, rx_blocks);
2673 rx_len = (t_u32)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2674
2675 handle_sdio_cmd_read(pmadapter, rx_len, rx_blocks);
2676 }
2677 #elif defined(SD8801)
2678 /*
2679 * Below two statement look like they are present for the purpose
2680 * of unconditional initializing of mp_wr_bitmap which will be used
2681 * during packet xmit. proper mlan code does not do this most
2682 * probably because they have used wlan_get_wr_port_data() to
2683 * decide on the write port which we have not done. Check this out
2684 * later.
2685 */
2686 pmadapter->mp_wr_bitmap = ((t_u16)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2687 pmadapter->mp_wr_bitmap |= (t_u16)pmadapter->mp_regs[WR_BITMAP_L];
2688 #endif
2689
2690 pmadapter->mp_wr_bitmap =
2691 #if defined(SD8801)
2692 ((t_u16)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2693 pmadapter->mp_wr_bitmap |= (t_u16)pmadapter->mp_regs[WR_BITMAP_L];
2694 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2695 (t_u32)pmadapter->mp_regs[WR_BITMAP_L];
2696 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2697 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_1L]) << 16;
2698 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_1U]) << 24;
2699 #endif
2700
2701 /*
2702 * DN_LD_HOST_INT_STATUS interrupt happens when the txmit sdio
2703 * ports are freed This is usually when we write to port most
2704 * significant port.
2705 */
2706 if ((sdio_ireg & DN_LD_HOST_INT_STATUS) != 0U)
2707 {
2708 pmadapter->mp_wr_bitmap =
2709 #if defined(SD8801)
2710 ((t_u16)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2711 pmadapter->mp_wr_bitmap |= (t_u16)pmadapter->mp_regs[WR_BITMAP_L];
2712 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2713 (t_u32)pmadapter->mp_regs[WR_BITMAP_L];
2714 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2715 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_1L]) << 16;
2716 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_1U]) << 24;
2717 #endif
2718 }
2719
2720 /*
2721 * As firmware will not generate download ready interrupt if the
2722 * port updated is command port only, cmd_sent should be done for
2723 * any SDIO interrupt.
2724 */
2725 #if defined(SD8801)
2726 if (pmadapter->cmd_sent == true)
2727 {
2728 /*
2729 * Check if firmware has attach buffer at command port and
2730 * update just that in wr_bit_map.
2731 */
2732 pmadapter->mp_wr_bitmap |= (t_u16)pmadapter->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK;
2733
2734 if (pmadapter->mp_wr_bitmap & CTRL_PORT_MASK)
2735 pmadapter->cmd_sent = false;
2736 }
2737 #endif
2738
2739 if ((sdio_ireg & UP_LD_HOST_INT_STATUS) != 0U)
2740 {
2741 /* This means there is data to be read */
2742 handle_sdio_packet_read(pmadapter);
2743 }
2744
2745 ret = MLAN_STATUS_SUCCESS;
2746
2747 done:
2748 return ret;
2749 }
2750
2751 /**
2752 * Interrupt callback handler registered with the SDIO driver.
2753 */
handle_cdint(int error)2754 void handle_cdint(int error)
2755 {
2756 /* Wake up LWIP thread. */
2757 if (!error && g_txrx_flag)
2758 {
2759 g_txrx_flag = false;
2760 #if CONFIG_ZEPHYR
2761 (void)OSA_EventNotifyPost(wm_wifi.wifi_core_task_Handle);
2762 #else
2763 (void)OSA_EventSet((osa_event_handle_t)wm_wifi.wifi_event_Handle, WIFI_EVENT_SDIO);
2764 #endif
2765 }
2766 }
2767
wifi_raw_packet_recv(t_u8 ** data,t_u32 * pkt_type)2768 int wifi_raw_packet_recv(t_u8 **data, t_u32 *pkt_type)
2769 {
2770 OSA_SR_ALLOC()
2771 osa_event_flags_t flagsToWait = WIFI_EVENT_SDIO;
2772 osa_event_flags_t pSetFlags;
2773
2774 if (data == MNULL)
2775 {
2776 return -WM_FAIL;
2777 }
2778
2779 OSA_ENTER_CRITICAL();
2780 /* Allow interrupt handler to deliver us a packet */
2781 g_txrx_flag = true;
2782
2783 sdio_enable_interrupt();
2784
2785 OSA_EXIT_CRITICAL()
2786
2787 (void)OSA_EventWait((osa_event_handle_t)wm_wifi.wifi_event_Handle, flagsToWait, false, osaWaitForever_c, &pSetFlags);
2788
2789 OSA_EventClear((osa_event_handle_t)wm_wifi.wifi_event_Handle, WIFI_EVENT_SDIO);
2790
2791 if ((pSetFlags & WIFI_EVENT_SDIO) == 0U)
2792 {
2793 return -WM_FAIL;
2794 }
2795
2796 /* Get the interrupt status */
2797 wlan_interrupt(mlan_adap);
2798
2799 t_u8 sdio_ireg = mlan_adap->sdio_ireg;
2800 mlan_adap->sdio_ireg = 0;
2801
2802 #if defined(SD8801)
2803 if (!(sdio_ireg & UP_LD_HOST_INT_STATUS))
2804 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2805 if (!(sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS))
2806 #endif
2807 {
2808 return -WM_FAIL;
2809 }
2810
2811 t_u32 datalen = 0;
2812
2813 mlan_adap->mp_rd_bitmap =
2814 #if defined(SD8801)
2815 ((t_u16)mlan_adap->mp_regs[RD_BITMAP_U]) << 8;
2816 mlan_adap->mp_rd_bitmap |= (t_u16)mlan_adap->mp_regs[RD_BITMAP_L];
2817 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2818 (t_u32)mlan_adap->mp_regs[RD_BITMAP_L];
2819 mlan_adap->mp_rd_bitmap |= ((t_u32)mlan_adap->mp_regs[RD_BITMAP_U]) << 8;
2820 mlan_adap->mp_rd_bitmap |= ((t_u32)mlan_adap->mp_regs[RD_BITMAP_1L]) << 16;
2821 mlan_adap->mp_rd_bitmap |= ((t_u32)mlan_adap->mp_regs[RD_BITMAP_1U]) << 24;
2822 #endif
2823
2824 t_u8 *packet = NULL;
2825
2826 #if defined(SD8801)
2827 int ret;
2828 while (1)
2829 {
2830 ret = _handle_sdio_packet_read(mlan_adap, &packet, &datalen, pkt_type);
2831 if (ret == MLAN_STATUS_SUCCESS)
2832 {
2833 break;
2834 }
2835 }
2836 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2837
2838 t_u8 cmd_rd_len_0 = CMD_RD_LEN_0;
2839 t_u8 cmd_rd_len_1 = CMD_RD_LEN_1;
2840 t_u32 rx_len;
2841 t_u32 rx_blocks;
2842
2843 /* read the len of control packet */
2844 rx_len = ((t_u32)mlan_adap->mp_regs[cmd_rd_len_1]) << 8;
2845 rx_len |= (t_u32)mlan_adap->mp_regs[cmd_rd_len_0];
2846 PRINTM(MINFO, "RX: cmd port rx_len=%u\n", rx_len);
2847
2848 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1U) / MLAN_SDIO_BLOCK_SIZE;
2849
2850 rx_len = (t_u32)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2851
2852 (void)_handle_sdio_cmd_read(mlan_adap, &packet, &datalen, pkt_type, rx_len, rx_blocks);
2853 #endif
2854 *data = packet;
2855 return WM_SUCCESS;
2856 }
2857
wifi_raw_packet_send(const t_u8 * packet,t_u32 length)2858 int wifi_raw_packet_send(const t_u8 *packet, t_u32 length)
2859 {
2860 if ((packet == MNULL) || !length)
2861 {
2862 return -WM_E_INVAL;
2863 }
2864
2865 if (length > SDIO_OUTBUF_LEN)
2866 {
2867 wifi_io_e("Insufficient buffer");
2868 return -WM_FAIL;
2869 }
2870
2871 t_u32 tx_blocks = 0, buflen = 0;
2872 calculate_sdio_write_params(length, &tx_blocks, &buflen);
2873
2874 (void)memcpy((void *)outbuf, (const void *)packet, length);
2875 #if CONFIG_WIFI_IO_DUMP
2876 dump_hex(outbuf, length);
2877 #endif
2878 uint32_t resp;
2879 #if defined(SD8801)
2880 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
2881 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2882 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
2883 #endif
2884 return WM_SUCCESS;
2885 }
2886
sd_wifi_preinit(void)2887 static mlan_status sd_wifi_preinit(void)
2888 {
2889 mlan_status mlanstatus = MLAN_STATUS_SUCCESS;
2890
2891 /* initializes the driver struct */
2892 int sdiostatus = wlan_init_struct();
2893 if (sdiostatus != WM_SUCCESS)
2894 {
2895 wifi_io_e("Init failed. Cannot create init struct");
2896 return MLAN_STATUS_FAILURE;
2897 }
2898
2899 /*
2900 * Register a callback with power manager of MC200/MW300
2901 * This callback will be called on entry /exit
2902 * of low power mode of MC200/MW300 based on first paramter
2903 * passed to the call.
2904 */
2905 // pm_handle = pm_register_cb(ACTION_EXIT_PM3 | ACTION_ENTER_PM4,
2906 // sd_wifi_ps_cb, NULL);
2907
2908 (void)mlan_subsys_init();
2909 seqnum = 0;
2910 txportno = 0;
2911 return mlanstatus;
2912 }
2913
sd_wifi_reset_ports()2914 void sd_wifi_reset_ports()
2915 {
2916 #if defined(SD8801)
2917 txportno = 1;
2918 mlan_adap->curr_rd_port = 1;
2919 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2920 txportno = 0;
2921 mlan_adap->curr_rd_port = 0;
2922 #endif
2923 }
2924
sd_wifi_post_init(enum wlan_type type)2925 mlan_status sd_wifi_post_init(enum wlan_type type)
2926 {
2927 mlan_status mlanstatus = MLAN_STATUS_SUCCESS;
2928 uint32_t resp;
2929 bool invalid_wlantype = MFALSE;
2930 #if defined(SD8801)
2931 sdio_drv_creg_write(HOST_INT_MASK_REG, 1, 0x3, &resp);
2932 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2933 (void)sdio_drv_creg_write(HOST_INT_MASK_REG, 1, HIM_ENABLE, &resp);
2934 #endif
2935
2936 /* If we're running a Manufacturing image, start the tasks.
2937 If not, initialize and setup the firmware */
2938 switch (type)
2939 {
2940 case WLAN_TYPE_NORMAL:
2941 fw_init_cfg = 1;
2942 wlan_fw_init_cfg();
2943 fw_init_cfg = 0;
2944 break;
2945 case WLAN_TYPE_WIFI_CALIB:
2946 g_txrx_flag = true;
2947 break;
2948 case WLAN_TYPE_FCC_CERTIFICATION:
2949 g_txrx_flag = true;
2950 break;
2951 default:
2952 wifi_io_e("Enter a valid input to sd_wifi_init");
2953 invalid_wlantype = MTRUE;
2954 break;
2955 }
2956
2957 if (invalid_wlantype == MTRUE)
2958 {
2959 return MLAN_STATUS_FAILURE;
2960 }
2961
2962 sd_wifi_reset_ports();
2963
2964 return mlanstatus;
2965 }
2966
2967 static void *intf;
2968
sd_wifi_init(enum wlan_type type,const uint8_t * fw_start_addr,const size_t size)2969 mlan_status sd_wifi_init(enum wlan_type type, const uint8_t *fw_start_addr, const size_t size)
2970 {
2971 mlan_status ret = MLAN_STATUS_SUCCESS;
2972
2973 ret = sd_wifi_preinit();
2974
2975 if (ret == MLAN_STATUS_SUCCESS)
2976 {
2977 intf = (void *)sdio_init_interface(NULL);
2978
2979 if (intf != MNULL)
2980 {
2981 mlan_adap->fw_start_addr = fw_start_addr;
2982
2983 ret = (mlan_status)firmware_download(fw_start_addr, size, intf, 0);
2984 } else {
2985 ret = MLAN_STATUS_FAILURE;
2986 }
2987 }
2988 return ret;
2989 }
2990
2991 #if (CONFIG_WIFI_IND_DNLD)
sd_wifi_reinit(enum wlan_type type,const uint8_t * fw_start_addr,const size_t size,uint8_t fw_reload)2992 mlan_status sd_wifi_reinit(enum wlan_type type, const uint8_t *fw_start_addr, const size_t size, uint8_t fw_reload)
2993 {
2994 mlan_status ret = MLAN_STATUS_SUCCESS;
2995
2996 if (fw_reload == FW_RELOAD_NO_EMULATION)
2997 {
2998 OSA_SR_ALLOC();
2999 OSA_ENTER_CRITICAL();
3000
3001 /* Allow interrupt handler to deliver us a packet */
3002 g_txrx_flag = false;
3003
3004 sdio_disable_interrupt();
3005
3006 OSA_EXIT_CRITICAL();
3007
3008 sdio_ioport_init();
3009 }
3010
3011 ret = (mlan_status)firmware_download(fw_start_addr, size, intf, fw_reload);
3012
3013 if (ret != MLAN_STATUS_FAILURE)
3014 {
3015 if (fw_reload == FW_RELOAD_NO_EMULATION)
3016 {
3017 OSA_SR_ALLOC();
3018 OSA_ENTER_CRITICAL();
3019 /* Allow interrupt handler to deliver us a packet */
3020 g_txrx_flag = true;
3021
3022 sdio_enable_interrupt();
3023
3024 OSA_EXIT_CRITICAL();
3025 }
3026 }
3027
3028 return ret;
3029 }
3030 #endif
3031
3032 #if CONFIG_BT_SUPPORT
read_sdio_function_recvd()3033 uint8_t read_sdio_function_recvd()
3034 {
3035 uint32_t resp = 0;
3036 uint8_t val;
3037 sdio_drv_creg_read(0x5, 0x0, &resp);
3038 val = resp & 0xf;
3039 return val;
3040 }
3041 #endif
3042
sd_wifi_deinit(void)3043 void sd_wifi_deinit(void)
3044 {
3045 #ifdef WLAN_LOW_POWER_ENABLE
3046 low_power_mode = false;
3047 #endif
3048 cal_data_valid = false;
3049 mac_addr_valid = false;
3050 // pm_deregister_cb(pm_handle);
3051
3052 (void)wlan_cmd_shutdown();
3053 sdio_drv_deinit();
3054 (void)mlan_subsys_deinit();
3055 (void)wlan_deinit_struct();
3056 }
3057
3058 #if CONFIG_FW_VDLL
wifi_get_vdllcommand_buffer(void)3059 HostCmd_DS_COMMAND *wifi_get_vdllcommand_buffer(void)
3060 {
3061 /* First 4 bytes reserved for SDIO pkt header */
3062 return (HostCmd_DS_COMMAND *)(void *)(vdll_cmd_buf + INTF_HEADER_LEN);
3063 }
3064 #endif
3065
wifi_get_command_buffer(void)3066 HostCmd_DS_COMMAND *wifi_get_command_buffer(void)
3067 {
3068 /* First 4 bytes reserved for SDIO pkt header */
3069 return (HostCmd_DS_COMMAND *)(void *)(ctrl_cmd_buf + INTF_HEADER_LEN);
3070 }
3071
3072 /**
3073 * Function to set mlan ioport.
3074 */
set_ioport_inmlan(t_u32 port)3075 void set_ioport_inmlan(t_u32 port)
3076 {
3077 mlan_adap->ioport = port;
3078 }
3079
3080 #if CONFIG_HOST_SLEEP
wifi_print_wakeup_reason(t_u16 hs_wakeup_reason)3081 void wifi_print_wakeup_reason(t_u16 hs_wakeup_reason)
3082 {
3083 if (hs_wakeup_reason == 0)
3084 {
3085 PRINTF("Woken up by unknown reason\r\n");
3086 }
3087 else if (hs_wakeup_reason == 1)
3088 {
3089 PRINTF("Woken up by Broadcast data matched\r\n");
3090 }
3091 else if (hs_wakeup_reason == 2)
3092 {
3093 PRINTF("Woken up by Multicast data matched\r\n");
3094 }
3095 else if (hs_wakeup_reason == 3)
3096 {
3097 PRINTF("Woken up by Unicast data matched\r\n");
3098 }
3099 else if (hs_wakeup_reason == 4)
3100 {
3101 PRINTF("Woken up by Maskable event matched\r\n");
3102 }
3103 else if (hs_wakeup_reason == 5)
3104 {
3105 PRINTF("Woken up by Non-maskable event matched\r\n");
3106 }
3107 else if (hs_wakeup_reason == 6)
3108 {
3109 PRINTF("Woken up by Non-maskable condition matched (EAPoL rekey)\r\n");
3110 }
3111 else if (hs_wakeup_reason == 7)
3112 {
3113 PRINTF("Woken up by Magic pattern matched\r\n");
3114 }
3115 else if (hs_wakeup_reason == 8)
3116 {
3117 PRINTF("Woken up by control frames matched \r\n");
3118 }
3119 else if (hs_wakeup_reason == 9)
3120 {
3121 PRINTF("Woken up by management frame matched \r\n");
3122 }
3123 else if (hs_wakeup_reason == 10)
3124 {
3125 PRINTF("Woken up by GTK rekey failure\r\n");
3126 }
3127 else if (hs_wakeup_reason == 11)
3128 {
3129 PRINTF("Woken up by management frame filter extension matched\r\n");
3130 }
3131 else
3132 {
3133 PRINTF("Woken up by reserved reason\r\n");
3134 }
3135 }
3136
wifi_clear_wakeup_reason(void)3137 void wifi_clear_wakeup_reason(void)
3138 {
3139 if (mlan_adap != NULL)
3140 {
3141 memset(&mlan_adap->wlan_wakeup, 0x0, sizeof(wlan_wakeup_reason));
3142 }
3143 }
3144 #endif
3145