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
985 #if UAP_SUPPORT
wlan_get_mac_addr_uap(void)986 static void wlan_get_mac_addr_uap(void)
987 {
988 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
989 uint32_t resp;
990 t_u16 seq_number = 0;
991
992 wifi_sdio_lock();
993
994 (void)memset(outbuf, 0, buflen);
995 seq_number = HostCmd_SET_SEQ_NO_BSS_INFO(0 /* seq_num */, 0 /* bss_num */, MLAN_BSS_TYPE_UAP);
996
997 /* sdiopkt = outbuf */
998 wifi_prepare_get_mac_addr_cmd(&sdiopkt->hostcmd, seq_number);
999
1000 sdiopkt->pkttype = MLAN_TYPE_CMD;
1001 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1002
1003 last_cmd_sent = HostCmd_CMD_802_11_MAC_ADDRESS;
1004
1005 /* send CMD53 to write the command to get mac address */
1006 #if defined(SD8801)
1007 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1008 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1009 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1010 #endif
1011
1012 wifi_sdio_unlock();
1013
1014 wifi_sdio_wait_for_cmdresp();
1015
1016 }
1017 #endif
1018
1019 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)1020 static void wlan_get_fw_ver_ext(int version_str_sel)
1021 {
1022 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1023 uint32_t resp;
1024
1025 wifi_sdio_lock();
1026
1027 (void)memset(outbuf, 0, buflen);
1028
1029 /* sdiopkt = outbuf */
1030 wifi_prepare_get_fw_ver_ext_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num(), version_str_sel);
1031
1032 sdiopkt->pkttype = MLAN_TYPE_CMD;
1033 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1034
1035 last_cmd_sent = HostCmd_CMD_VERSION_EXT;
1036
1037 /* send CMD53 to write the command to get mac address */
1038 #if defined(SD8801)
1039 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1040 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1041 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1042 #endif
1043
1044 wifi_sdio_unlock();
1045
1046 wifi_sdio_wait_for_cmdresp();
1047
1048 }
1049
1050 void wifi_prepare_get_value1(HostCmd_DS_COMMAND *cmd, int seq_number);
1051
wlan_get_value_1(void)1052 static void wlan_get_value_1(void)
1053 {
1054 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1055 uint32_t resp;
1056
1057 wifi_sdio_lock();
1058
1059 (void)memset(outbuf, 0, buflen);
1060
1061 /* sdiopkt = outbuf */
1062 wifi_prepare_get_value1(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1063
1064 sdiopkt->pkttype = MLAN_TYPE_CMD;
1065 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1066
1067 last_cmd_sent = HostCmd_CMD_MAC_REG_ACCESS;
1068
1069 #if defined(SD8801)
1070 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1071 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1072 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1073 #endif
1074
1075 wifi_sdio_unlock();
1076
1077 wifi_sdio_wait_for_cmdresp();
1078
1079 }
1080
1081 void wifi_prepare_set_mac_addr_cmd(HostCmd_DS_COMMAND *cmd, int seq_number);
_wlan_set_mac_addr(void)1082 static void _wlan_set_mac_addr(void)
1083 {
1084 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1085 uint32_t resp;
1086
1087 wifi_sdio_lock();
1088
1089 (void)memset(outbuf, 0, buflen);
1090
1091 /* sdiopkt = outbuf */
1092 wifi_prepare_set_mac_addr_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1093
1094 sdiopkt->pkttype = MLAN_TYPE_CMD;
1095 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1096
1097 last_cmd_sent = HostCmd_CMD_802_11_MAC_ADDRESS;
1098
1099 /* send CMD53 to write the command to get mac address */
1100 #if defined(SD8801)
1101 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1102 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1103 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1104 #endif
1105
1106 wifi_sdio_unlock();
1107
1108 wifi_sdio_wait_for_cmdresp();
1109 }
1110
1111 #if CONFIG_11N
wlan_set_11n_cfg(void)1112 static void wlan_set_11n_cfg(void)
1113 {
1114 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1115 uint32_t resp;
1116
1117 wifi_sdio_lock();
1118
1119 (void)memset(outbuf, 0, SDIO_OUTBUF_LEN);
1120
1121 wrapper_wlan_cmd_11n_cfg(&sdiopkt->hostcmd);
1122 /* sdiopkt = outbuf */
1123 sdiopkt->hostcmd.seq_num = (t_u16)wlan_get_next_seq_num();
1124 sdiopkt->pkttype = MLAN_TYPE_CMD;
1125 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1126
1127 last_cmd_sent = HostCmd_CMD_11N_CFG;
1128
1129 #if defined(SD8801)
1130 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1131 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1132 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1133 #endif
1134
1135 wifi_sdio_unlock();
1136
1137 wifi_sdio_wait_for_cmdresp();
1138 }
1139
1140 #if CONFIG_ENABLE_AMSDU_RX
1141 void wifi_prepare_enable_amsdu_cmd(HostCmd_DS_COMMAND *cmd, int seq_number);
wlan_enable_amsdu(void)1142 static void wlan_enable_amsdu(void)
1143 {
1144 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1145 uint32_t resp;
1146
1147 wifi_sdio_lock();
1148
1149 (void)memset(outbuf, 0, buflen);
1150
1151 /* sdiopkt = outbuf */
1152 wifi_prepare_enable_amsdu_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1153
1154 sdiopkt->pkttype = MLAN_TYPE_CMD;
1155 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1156
1157 last_cmd_sent = HostCmd_CMD_AMSDU_AGGR_CTRL;
1158
1159 #if defined(SD8801)
1160 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1161 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1162 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1163 #endif
1164
1165 wifi_sdio_unlock();
1166
1167 wifi_sdio_wait_for_cmdresp();
1168
1169 }
1170 #endif /* CONFIG_ENABLE_AMSDU_RX */
1171 #endif /* CONFIG_11N */
1172
wlan_cmd_shutdown(void)1173 static void wlan_cmd_shutdown(void)
1174 {
1175 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1176 uint32_t resp;
1177
1178 (void)memset(outbuf, 0, buflen);
1179
1180 /* sdiopkt = outbuf */
1181 sdiopkt->hostcmd.command = HostCmd_CMD_FUNC_SHUTDOWN;
1182 sdiopkt->hostcmd.size = (t_u16)S_DS_GEN;
1183 sdiopkt->hostcmd.seq_num = (t_u16)wlan_get_next_seq_num();
1184 sdiopkt->hostcmd.result = 0;
1185
1186 sdiopkt->pkttype = MLAN_TYPE_CMD;
1187 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1188
1189 last_cmd_sent = HostCmd_CMD_FUNC_SHUTDOWN;
1190
1191 (void)sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1192 }
1193
1194 void wlan_prepare_mac_control_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
wlan_set_mac_ctrl(void)1195 static void wlan_set_mac_ctrl(void)
1196 {
1197 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1198 uint32_t resp;
1199
1200 wifi_sdio_lock();
1201
1202 (void)memset(outbuf, 0, buflen);
1203
1204 /* sdiopkt = outbuf */
1205 wlan_prepare_mac_control_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1206
1207 sdiopkt->pkttype = MLAN_TYPE_CMD;
1208 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1209
1210 last_cmd_sent = HostCmd_CMD_MAC_CONTROL;
1211
1212 /* send CMD53 to write the command to set mac control */
1213 #if defined(SD8801)
1214 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1215 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1216 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1217 #endif
1218
1219 wifi_sdio_unlock();
1220
1221 wifi_sdio_wait_for_cmdresp();
1222
1223 }
1224
wlan_cmd_init(void)1225 static void wlan_cmd_init(void)
1226 {
1227 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1228 uint32_t resp;
1229
1230 wifi_sdio_lock();
1231
1232 (void)memset(outbuf, 0, buflen);
1233
1234 /* sdiopkt = outbuf */
1235 sdiopkt->hostcmd.command = HostCmd_CMD_FUNC_INIT;
1236 sdiopkt->hostcmd.size = (t_u16)S_DS_GEN;
1237 sdiopkt->hostcmd.seq_num = (t_u16)wlan_get_next_seq_num();
1238 sdiopkt->hostcmd.result = 0;
1239
1240 sdiopkt->pkttype = MLAN_TYPE_CMD;
1241 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1242
1243 last_cmd_sent = HostCmd_CMD_FUNC_INIT;
1244
1245 #if defined(SD8801)
1246 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1247 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1248 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1249 #endif
1250
1251 wifi_sdio_unlock();
1252
1253 wifi_sdio_wait_for_cmdresp();
1254 }
1255
1256 #ifdef WLAN_LOW_POWER_ENABLE
1257 void wifi_prepare_low_power_mode_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
wlan_set_low_power_mode()1258 static int wlan_set_low_power_mode()
1259 {
1260 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1261 uint32_t resp;
1262
1263 wifi_sdio_lock();
1264
1265 (void)memset(outbuf, 0, buflen);
1266
1267 /* sdiopkt = outbuf */
1268
1269 wifi_prepare_low_power_mode_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1270
1271 sdiopkt->pkttype = MLAN_TYPE_CMD;
1272 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1273
1274 last_cmd_sent = HostCmd_CMD_LOW_POWER_MODE;
1275
1276 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1277
1278 wifi_sdio_unlock();
1279
1280 wifi_sdio_wait_for_cmdresp();
1281
1282 return true;
1283 }
1284 #endif
1285
1286 #if CONFIG_EXTERNAL_BLE_COEX
1287 void wifi_prepare_set_coex_cmd(HostCmd_DS_COMMAND *cmd, t_u16 seq_number);
1288
wlan_set_ext_ble_coex_mode()1289 static int wlan_set_ext_ble_coex_mode()
1290 {
1291 t_u32 tx_blocks = 1, buflen = MLAN_SDIO_BLOCK_SIZE;
1292 uint32_t resp;
1293
1294 if (!board_coex_interface())
1295 {
1296 return false;
1297 }
1298
1299 board_coex_pin_config(1);
1300
1301 wifi_sdio_lock();
1302
1303 (void)memset(outbuf, 0, buflen);
1304
1305 /* sdiopkt = outbuf */
1306 wifi_prepare_set_coex_cmd(&sdiopkt->hostcmd, (t_u16)wlan_get_next_seq_num());
1307
1308 sdiopkt->pkttype = MLAN_TYPE_CMD;
1309 sdiopkt->size = sdiopkt->hostcmd.size + INTF_HEADER_LEN;
1310
1311 last_cmd_sent = HostCmd_CMD_ROBUST_COEX;
1312
1313 /* send CMD53 to write the command to set mac control */
1314 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1315
1316 wifi_sdio_unlock();
1317
1318 wifi_sdio_wait_for_cmdresp();
1319
1320 return true;
1321 }
1322 #endif
1323
1324 /* Setup the firmware with commands */
wlan_fw_init_cfg(void)1325 static void wlan_fw_init_cfg(void)
1326 {
1327 #if CONFIG_FW_VDLL
1328 mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[0];
1329 mlan_adapter *pmadapter = pmpriv->adapter;
1330 #endif
1331
1332 wifi_io_d("FWCMD : INIT (0xa9)");
1333
1334 wlan_cmd_init();
1335
1336 #ifdef WLAN_LOW_POWER_ENABLE
1337 if (low_power_mode)
1338 {
1339 #if CONFIG_FW_VDLL
1340 while (pmadapter->vdll_in_progress == MTRUE)
1341 {
1342 OSA_TimeDelay(50);
1343 }
1344 #endif
1345 wifi_io_d("CMD : LOW_POWER_MODE (0x128)");
1346
1347 wlan_set_low_power_mode();
1348 }
1349 #endif
1350
1351 if (cal_data_valid)
1352 {
1353 #if CONFIG_FW_VDLL
1354 while (pmadapter->vdll_in_progress == MTRUE)
1355 {
1356 OSA_TimeDelay(50);
1357 }
1358 #endif
1359 wifi_io_d("CMD : SET_CAL_DATA (0x8f)");
1360
1361 _wlan_set_cal_data();
1362 }
1363
1364 /* When cal data set command is sent, fimrware looses alignment of SDIO Tx buffers.
1365 * So we need to send reconfigure command. This can be removed if fix is added in firmware.
1366 */
1367 wifi_io_d("CMD : RECONFIGURE_TX_BUFF (0xd9)");
1368
1369 #if CONFIG_FW_VDLL
1370 while (pmadapter->vdll_in_progress == MTRUE)
1371 {
1372 OSA_TimeDelay(50);
1373 }
1374 #endif
1375
1376 wlan_reconfigure_tx_buffers();
1377
1378 if (mac_addr_valid)
1379 {
1380 wifi_io_d("CMD : SET_MAC_ADDR (0x4d)");
1381 #if CONFIG_FW_VDLL
1382 while (pmadapter->vdll_in_progress == MTRUE)
1383 {
1384 OSA_TimeDelay(50);
1385 }
1386 #endif
1387 _wlan_set_mac_addr();
1388 }
1389
1390 #ifdef OTP_CHANINFO
1391 wifi_io_d("CMD : Channel Region CFG (0x0242)");
1392
1393 #if CONFIG_FW_VDLL
1394 while (pmadapter->vdll_in_progress == MTRUE)
1395 {
1396 OSA_TimeDelay(50);
1397 }
1398 #endif
1399
1400 wlan_get_channel_region_cfg();
1401 #endif
1402
1403 wifi_io_d("CMD : GET_HW_SPEC (0x03)");
1404
1405 #if CONFIG_FW_VDLL
1406 while (pmadapter->vdll_in_progress == MTRUE)
1407 {
1408 OSA_TimeDelay(50);
1409 }
1410 #endif
1411
1412 wlan_get_hw_spec();
1413
1414 #if CONFIG_FW_VDLL
1415 while (pmadapter->vdll_in_progress == MTRUE)
1416 {
1417 OSA_TimeDelay(50);
1418 }
1419 #endif
1420
1421 wlan_get_value_1();
1422
1423 if (wm_wifi.wifi_init_done == 0U)
1424 {
1425
1426 wifi_io_d("CMD : GET_FW_VER_EXT (0x97)");
1427
1428 #if CONFIG_FW_VDLL
1429 while (pmadapter->vdll_in_progress == MTRUE)
1430 {
1431 OSA_TimeDelay(50);
1432 }
1433 #endif
1434
1435 wlan_get_fw_ver_ext(0);
1436 }
1437
1438 wifi_io_d("CMD : GET_MAC_ADDR (0x4d)");
1439
1440 #if CONFIG_FW_VDLL
1441 while (pmadapter->vdll_in_progress == MTRUE)
1442 {
1443 OSA_TimeDelay(50);
1444 }
1445 #endif
1446
1447 wlan_get_mac_addr_sta();
1448
1449 wifi_io_d("CMD : GET_MAC_ADDR (0x4d)");
1450
1451 #if CONFIG_FW_VDLL
1452 while (pmadapter->vdll_in_progress == MTRUE)
1453 {
1454 OSA_TimeDelay(50);
1455 }
1456 #endif
1457
1458 #if UAP_SUPPORT
1459 wlan_get_mac_addr_uap();
1460 #endif
1461
1462 if (wm_wifi.wifi_init_done == 0U)
1463 {
1464
1465 wifi_io_d("CMD : GET_FW_VER_EXT (0x97)");
1466
1467 #if CONFIG_FW_VDLL
1468 while (pmadapter->vdll_in_progress == MTRUE)
1469 {
1470 OSA_TimeDelay(50);
1471 }
1472 #endif
1473
1474 wlan_get_fw_ver_ext(3);
1475
1476 }
1477
1478 wifi_io_d("CMD : MAC_CTRL (0x28)");
1479
1480 #if CONFIG_FW_VDLL
1481 while (pmadapter->vdll_in_progress == MTRUE)
1482 {
1483 OSA_TimeDelay(50);
1484 }
1485 #endif
1486
1487 wlan_set_mac_ctrl();
1488
1489 if (wm_wifi.wifi_init_done == 0U)
1490 {
1491 wifi_io_d("CMD : GET_FW_VER_EXT (0x97)");
1492
1493 #if CONFIG_FW_VDLL
1494 while (pmadapter->vdll_in_progress == MTRUE)
1495 {
1496 OSA_TimeDelay(50);
1497 }
1498 #endif
1499
1500 wlan_get_fw_ver_ext(4);
1501 }
1502
1503 #if CONFIG_EXTERNAL_BLE_COEX
1504 #if CONFIG_FW_VDLL
1505 while (pmadapter->vdll_in_progress == MTRUE)
1506 {
1507 OSA_TimeDelay(50);
1508 }
1509 #endif
1510
1511 wlan_set_ext_ble_coex_mode();
1512 #endif
1513
1514 #if CONFIG_11N
1515 wifi_io_d("CMD : 11N_CFG (0xcd)");
1516
1517 #if CONFIG_FW_VDLL
1518 while (pmadapter->vdll_in_progress == MTRUE)
1519 {
1520 OSA_TimeDelay(50);
1521 }
1522 #endif
1523
1524 wlan_set_11n_cfg();
1525
1526 #if CONFIG_ENABLE_AMSDU_RX
1527 wifi_io_d("CMD : AMSDU_AGGR_CTRL (0xdf)");
1528
1529 #if CONFIG_FW_VDLL
1530 while (pmadapter->vdll_in_progress == MTRUE)
1531 {
1532 OSA_TimeDelay(50);
1533 }
1534 #endif
1535
1536 wlan_enable_amsdu();
1537
1538 #endif /* CONFIG_ENABLE_AMSDU_RX */
1539 #endif /* CONFIG_11N */
1540
1541 return;
1542 }
1543
1544 #if CONFIG_P2P
wlan_send_gen_sdio_cmd(t_u8 * buf,t_u32 buflen)1545 mlan_status wlan_send_gen_sdio_cmd(t_u8 *buf, t_u32 buflen)
1546 {
1547 SDIOPkt *sdio = (SDIOPkt *)outbuf;
1548 uint32_t resp;
1549
1550 (void)memset(outbuf, 0, 512);
1551
1552 wifi_sdio_lock();
1553 (void)memcpy((void *)outbuf, (const void *)buf, buflen);
1554 sdio->pkttype = MLAN_TYPE_CMD;
1555 sdio->hostcmd.seq_num = (0x01) << 13;
1556 sdio->size = sdio->hostcmd.size + INTF_HEADER_LEN;
1557
1558 sdio_drv_write(mlan_adap->ioport, 1, 1, buflen, (t_u8 *)outbuf, &resp);
1559
1560 last_cmd_sent = sdio->hostcmd.command;
1561 wifi_sdio_unlock();
1562
1563 return 0;
1564 }
1565 #endif
1566
1567 #if CONFIG_FW_VDLL
wlan_send_sdio_vdllcmd(t_u8 * buf,t_u32 tx_blocks,t_u32 buflen)1568 int wlan_send_sdio_vdllcmd(t_u8 *buf, t_u32 tx_blocks, t_u32 buflen)
1569 {
1570 SDIOPkt *sdio = (SDIOPkt *)(void *)outbuf;
1571 uint32_t resp;
1572
1573 (void)memcpy((void *)outbuf, (const void *)buf, tx_blocks * buflen);
1574 sdio->pkttype = MLAN_TYPE_VDLL;
1575 sdio->size = sdio->hostcmd.size + INTF_HEADER_LEN;
1576
1577 #if CONFIG_WIFI_IO_DUMP
1578 (void)PRINTF("OUT_CMD");
1579 dump_hex(outbuf, sdio->size);
1580 #endif /* CONFIG_WIFI_IO_DUMP */
1581 #if defined(SD8801)
1582 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1583 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1584 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1585 #endif
1586
1587 return WM_SUCCESS;
1588 }
1589 #endif
1590
wlan_send_sdio_cmd(t_u8 * buf,t_u32 tx_blocks,t_u32 buflen)1591 int wlan_send_sdio_cmd(t_u8 *buf, t_u32 tx_blocks, t_u32 buflen)
1592 {
1593 SDIOPkt *sdio = (SDIOPkt *)(void *)outbuf;
1594 uint32_t resp;
1595
1596 (void)wifi_sdio_lock();
1597
1598 (void)memcpy((void *)outbuf, (const void *)buf, tx_blocks * buflen);
1599 sdio->pkttype = MLAN_TYPE_CMD;
1600 sdio->size = sdio->hostcmd.size + INTF_HEADER_LEN;
1601
1602 #if CONFIG_WIFI_IO_DUMP
1603 (void)PRINTF("OUT_CMD");
1604 dump_hex(outbuf, sdio->size);
1605 #endif /* CONFIG_WIFI_IO_DUMP */
1606 #if defined(SD8801)
1607 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1608 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1609 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1610 #endif
1611
1612 last_cmd_sent = sdio->hostcmd.command;
1613 wifi_sdio_unlock();
1614
1615 return WM_SUCCESS;
1616 }
1617
wifi_send_cmdbuffer(t_u32 tx_blocks,t_u32 len)1618 int wifi_send_cmdbuffer(t_u32 tx_blocks, t_u32 len)
1619 {
1620 return wlan_send_sdio_cmd(ctrl_cmd_buf, tx_blocks, len);
1621 }
1622
1623 #if CONFIG_FW_VDLL
wifi_send_vdllcmdbuffer(t_u32 tx_blocks,t_u32 len)1624 int wifi_send_vdllcmdbuffer(t_u32 tx_blocks, t_u32 len)
1625 {
1626 return wlan_send_sdio_vdllcmd(vdll_cmd_buf, tx_blocks, len);
1627 }
1628 #endif
1629
1630 #if CONFIG_WMM
1631
1632 #if CONFIG_SDIO_MULTI_PORT_TX_AGGR
1633 static t_u32 buf_block_len = 0;
1634 static t_u8 start_port = -1;
1635 static t_u8 ports = 0;
1636 static t_u8 pkt_cnt = 0;
1637
1638 /**
1639 * @brief This function gets available SDIO port for writing data
1640 *
1641 * @param pmadapter A pointer to mlan_adapter structure
1642 * @param pport A pointer to port number
1643 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1644 */
wlan_get_wr_port_data(t_u8 * pport)1645 mlan_status wlan_get_wr_port_data(t_u8 *pport)
1646 {
1647 #if CONFIG_WIFI_IO_DEBUG
1648 t_u32 wr_bitmap = mlan_adap->mp_wr_bitmap;
1649 #endif
1650
1651 ENTER();
1652
1653 wifi_io_d("wlan_get_wr_port_data: mp_wr_bitmap=0x%08x", wr_bitmap);
1654
1655 if ((1U << txportno) & mlan_adap->mp_wr_bitmap)
1656 {
1657 mlan_adap->mp_wr_bitmap &= (t_u32)(~(1 << txportno));
1658 *pport = txportno;
1659 txportno++;
1660
1661 if (txportno == mlan_adap->mp_end_port)
1662 {
1663 #if defined(SD8801)
1664 txportno = 1;
1665 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1666 txportno = 0;
1667 #endif
1668 }
1669 }
1670 else
1671 {
1672 LEAVE();
1673 return MLAN_STATUS_RESOURCE;
1674 }
1675
1676 #if defined(SD8801)
1677 if (*pport == CTRL_PORT)
1678 {
1679 wifi_io_d("Invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\r\n", *pport, txportno, wr_bitmap,
1680 mlan_adap->mp_wr_bitmap);
1681 LEAVE();
1682 return MLAN_STATUS_FAILURE;
1683 }
1684 #endif
1685
1686 wifi_io_d("port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", *pport, wr_bitmap, mlan_adap->mp_wr_bitmap);
1687
1688 LEAVE();
1689 return MLAN_STATUS_SUCCESS;
1690 }
1691
wifi_tx_data(t_u8 start_port,t_u8 ports,t_u8 pkt_cnt,t_u32 txlen)1692 static mlan_status wifi_tx_data(t_u8 start_port, t_u8 ports, t_u8 pkt_cnt, t_u32 txlen)
1693 {
1694 t_u32 cmd53_port;
1695 t_u32 tx_blocks = 0, buflen = 0;
1696 uint32_t resp;
1697 bool ret;
1698 #if CONFIG_WIFI_FW_DEBUG
1699 int ret_cb;
1700 #endif
1701 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1702 t_u32 port_count = 0;
1703 #endif
1704
1705 calculate_sdio_write_params(txlen, &tx_blocks, &buflen);
1706
1707 if (pkt_cnt == 1)
1708 {
1709 cmd53_port = mlan_adap->ioport + start_port;
1710 }
1711 else
1712 {
1713 #if defined(SD8801)
1714 cmd53_port = (mlan_adap->ioport | SDIO_MPA_ADDR_BASE | (ports << 4)) + start_port;
1715 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1716 port_count = ports - 1U;
1717 cmd53_port = (mlan_adap->ioport | SDIO_MPA_ADDR_BASE | (port_count << 8)) + start_port;
1718 #endif
1719 }
1720
1721 //(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);
1722
1723 /* send CMD53 */
1724 ret = sdio_drv_write(cmd53_port, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
1725
1726 if (ret == false)
1727 {
1728 wifi_io_e("sdio_drv_write failed (%d)", ret);
1729 #if CONFIG_WIFI_FW_DEBUG
1730 wifi_sdio_reg_dbg(NULL);
1731 if (wm_wifi.wifi_usb_mount_cb != NULL)
1732 {
1733 ret_cb = wm_wifi.wifi_usb_mount_cb();
1734 if (ret_cb == WM_SUCCESS)
1735 wifi_dump_firmware_info(NULL);
1736 else
1737 wifi_e("USB mounting failed");
1738 }
1739 else
1740 wifi_e("USB mount callback is not registered");
1741 #endif
1742 return MLAN_STATUS_RESOURCE;
1743 }
1744 return MLAN_STATUS_SUCCESS;
1745 }
1746
wlan_xmit_wmm_pkt(t_u8 interface,t_u32 txlen,t_u8 * tx_buf)1747 mlan_status wlan_xmit_wmm_pkt(t_u8 interface, t_u32 txlen, t_u8 *tx_buf)
1748 {
1749 t_u32 tx_blocks = 0, buflen = 0;
1750 mlan_status ret = MLAN_STATUS_SUCCESS;
1751 #if CONFIG_WMM_UAPSD
1752 bool last_packet = 0;
1753 #endif
1754 t_u8 port = 0;
1755
1756 if (buf_block_len == 0)
1757 {
1758 start_port = -1;
1759 ports = 0;
1760 pkt_cnt = 0;
1761 }
1762
1763 calculate_sdio_write_params(txlen, &tx_blocks, &buflen);
1764
1765 #if CONFIG_WIFI_IO_DEBUG
1766 (void)PRINTF("%s: txportno = %d mlan_adap->mp_wr_bitmap: %x\n\r", __func__, txportno, mlan_adap->mp_wr_bitmap);
1767 #endif /* CONFIG_WIFI_IO_DEBUG */
1768
1769 ret = wlan_get_wr_port_data(&port);
1770 if (ret != WM_SUCCESS)
1771 {
1772 return MLAN_STATUS_RESOURCE;
1773 }
1774
1775 #if CONFIG_WMM_UAPSD
1776 if (mlan_adap->priv[interface]->adapter->pps_uapsd_mode &&
1777 wifi_check_last_packet_indication(mlan_adap->priv[interface]))
1778 {
1779 #if CONFIG_TX_RX_ZERO_COPY
1780 process_pkt_hdrs_flags(&((outbuf_t *)tx_buf)->intf_header[0], MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
1781 #else
1782 process_pkt_hdrs_flags((t_u8 *)tx_buf, MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
1783 #endif
1784 last_packet = 1;
1785 }
1786 #endif
1787
1788 if (buf_block_len == 0)
1789 {
1790 start_port = port;
1791 }
1792
1793 #if CONFIG_TX_RX_ZERO_COPY
1794 net_tx_zerocopy_process_cb(outbuf + buf_block_len, tx_buf, txlen);
1795 #else
1796 memcpy(outbuf + buf_block_len, tx_buf, txlen);
1797 #endif
1798
1799 buf_block_len += tx_blocks * buflen;
1800
1801 ports++;
1802 pkt_cnt++;
1803
1804 #if CONFIG_WMM_UAPSD
1805 if (last_packet)
1806 {
1807 mlan_adap->priv[interface]->adapter->tx_lock_flag = MTRUE;
1808 OSA_SemaphoreWait((osa_semaphore_handle_t)uapsd_sem, osaWaitForever_c);
1809 }
1810 #endif
1811
1812 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);
1813
1814 return MLAN_STATUS_SUCCESS;
1815 }
1816
wlan_flush_wmm_pkt(t_u8 pkt_count)1817 mlan_status wlan_flush_wmm_pkt(t_u8 pkt_count)
1818 {
1819 int ret;
1820
1821 if (pkt_count == 0)
1822 return MLAN_STATUS_SUCCESS;
1823
1824 w_pkt_d("Data TX: Driver=>FW, pkt_count %d", pkt_cnt);
1825
1826 ret = wifi_tx_data(start_port, ports, pkt_cnt, buf_block_len);
1827
1828 buf_block_len = 0;
1829
1830 if (ret != MLAN_STATUS_SUCCESS)
1831 {
1832 return MLAN_STATUS_RESOURCE;
1833 }
1834
1835 return MLAN_STATUS_SUCCESS;
1836 }
1837 #else
1838 extern int retry_attempts;
1839
get_free_port(void)1840 static int get_free_port(void)
1841 {
1842 /* Check if the port is available */
1843 if (!((1 << txportno) & mlan_adap->mp_wr_bitmap))
1844 {
1845 #if CONFIG_WIFI_IO_DEBUG
1846 wifi_io_e(
1847 "txportno out of sync txportno "
1848 "= (%d) mp_wr_bitmap = (0x%x)",
1849 txportno, mlan_adap->mp_wr_bitmap);
1850 #endif /* CONFIG_WIFI_IO_DEBUG */
1851
1852 return -WM_FAIL;
1853 }
1854 else
1855 {
1856 /* Mark the port number we will use */
1857 mlan_adap->mp_wr_bitmap &= ~(1 << txportno);
1858 }
1859 return WM_SUCCESS;
1860 }
1861
wlan_xmit_wmm_pkt(t_u8 interface,t_u32 txlen,t_u8 * tx_buf)1862 mlan_status wlan_xmit_wmm_pkt(t_u8 interface, t_u32 txlen, t_u8 *tx_buf)
1863 {
1864 t_u32 tx_blocks = 0, buflen = 0;
1865 uint32_t resp;
1866 int ret = false;
1867 int retry = retry_attempts;
1868 #if CONFIG_WMM_UAPSD
1869 bool last_packet = 0;
1870 #endif
1871
1872 wifi_io_info_d("OUT: i/f: %d len: %d", interface, tx_blocks * buflen);
1873
1874 calculate_sdio_write_params(txlen, &tx_blocks, &buflen);
1875
1876 #if CONFIG_WIFI_IO_DEBUG
1877 (void)PRINTF("%s: txportno = %d mlan_adap->mp_wr_bitmap: %x\n\r", __func__, txportno, mlan_adap->mp_wr_bitmap);
1878 #endif /* CONFIG_WIFI_IO_DEBUG */
1879
1880 retry_xmit:
1881 ret = get_free_port();
1882 if (ret == -WM_FAIL)
1883 {
1884 if (!retry)
1885 {
1886 ret = MLAN_STATUS_RESOURCE;
1887 goto exit_fn;
1888 }
1889 else
1890 {
1891 retry--;
1892 /* Allow the other thread to run and hence
1893 * update the write bitmap so that pkt
1894 * can be sent to FW */
1895 OSA_TimeDelay(1);
1896 goto retry_xmit;
1897 }
1898 }
1899
1900 #if CONFIG_WMM_UAPSD
1901 if (mlan_adap->priv[interface]->adapter->pps_uapsd_mode &&
1902 wifi_check_last_packet_indication(mlan_adap->priv[interface]))
1903 {
1904 process_pkt_hdrs_flags((t_u8 *)tx_buf, MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
1905 last_packet = 1;
1906 }
1907 #endif
1908
1909 /* send CMD53 */
1910 ret = sdio_drv_write(mlan_adap->ioport + txportno, 1, tx_blocks, buflen, tx_buf, &resp);
1911
1912 txportno++;
1913 if (txportno == mlan_adap->mp_end_port)
1914 {
1915 #if defined(SD8801)
1916 txportno = 1;
1917 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
1918 txportno = 0;
1919 #endif
1920 }
1921
1922 if (ret == false)
1923 {
1924 #if CONFIG_WMM_UAPSD
1925 if (last_packet)
1926 process_pkt_hdrs_flags((t_u8 *)tx_buf, 0);
1927 #endif
1928
1929 wifi_io_e("sdio_drv_write failed (%d)", ret);
1930 #if CONFIG_WIFI_FW_DEBUG
1931 wifi_sdio_reg_dbg(NULL);
1932 if (wm_wifi.wifi_usb_mount_cb != NULL)
1933 {
1934 ret = wm_wifi.wifi_usb_mount_cb();
1935 if (ret == WM_SUCCESS)
1936 wifi_dump_firmware_info(NULL);
1937 else
1938 wifi_e("USB mounting failed");
1939 }
1940 else
1941 wifi_e("USB mount callback is not registered");
1942 #endif
1943 ret = MLAN_STATUS_RESOURCE;
1944 goto exit_fn;
1945 }
1946
1947 #if CONFIG_WMM_UAPSD
1948 if (last_packet)
1949 {
1950 mlan_adap->priv[interface]->adapter->tx_lock_flag = MTRUE;
1951 OSA_SemaphoreWait((osa_semaphore_handle_t)uapsd_sem, osaWaitForever_c);
1952 }
1953 #endif
1954
1955 ret = MLAN_STATUS_SUCCESS;
1956
1957 exit_fn:
1958
1959 return ret;
1960 }
1961
wlan_flush_wmm_pkt(t_u8 pkt_count)1962 mlan_status wlan_flush_wmm_pkt(t_u8 pkt_count)
1963 {
1964 return MLAN_STATUS_SUCCESS;
1965 }
1966
1967 #endif
1968 #endif
1969
wlan_xmit_pkt(t_u8 * buffer,t_u32 txlen,t_u8 interface,t_u32 tx_control)1970 mlan_status wlan_xmit_pkt(t_u8 *buffer, t_u32 txlen, t_u8 interface, t_u32 tx_control)
1971 {
1972
1973 (void)interface;
1974
1975 wifi_io_info_d("OUT: i/f: %d len: %d", interface, txlen);
1976
1977 process_pkt_hdrs((t_u8 *)buffer, txlen, interface, 0, tx_control);
1978
1979 return wifi_send_fw_data(buffer, txlen);
1980 }
1981
1982 #if CONFIG_WMM
wlan_xmit_bypass_pkt(t_u8 * buffer,t_u32 txlen,t_u8 interface)1983 mlan_status wlan_xmit_bypass_pkt(t_u8 *buffer, t_u32 txlen, t_u8 interface)
1984 {
1985
1986 (void)interface;
1987
1988 wifi_io_info_d("OUT: i/f: %d len: %d", interface, txlen);
1989
1990 return wifi_send_fw_data(buffer, txlen);
1991 }
1992 #endif
1993
wlan_send_null_packet(pmlan_private priv,t_u8 flags)1994 mlan_status wlan_send_null_packet(pmlan_private priv, t_u8 flags)
1995 {
1996 mlan_status ret;
1997 t_u8 pbuf[128] = {0};
1998 TxPD *ptxpd = (TxPD *)((uint8_t *)pbuf + INTF_HEADER_LEN);
1999
2000 ptxpd->bss_type = priv->bss_type;
2001 ptxpd->bss_num = GET_BSS_NUM(priv);
2002 ptxpd->tx_pkt_offset = 0x16; /* we'll just make this constant */
2003 ptxpd->tx_pkt_length = 0;
2004 ptxpd->tx_control = 0;
2005 ptxpd->priority = 0;
2006 ptxpd->flags = flags;
2007 ptxpd->pkt_delay_2ms = 0;
2008
2009 ret = wifi_send_fw_data(pbuf, sizeof(TxPD) + INTF_HEADER_LEN);
2010
2011 if (ret != MLAN_STATUS_SUCCESS)
2012 {
2013 wifi_io_d("sdio_drv_write failed (%d)", ret);
2014 return MLAN_STATUS_FAILURE;
2015 }
2016
2017 return MLAN_STATUS_SUCCESS;
2018 }
2019
2020 /*
2021 * This function gets interrupt status.
2022 */
wlan_interrupt(mlan_adapter * pmadapter)2023 t_void wlan_interrupt(mlan_adapter *pmadapter)
2024 {
2025 /* Read SDIO multiple port group registers */
2026 uint32_t resp = 0;
2027 int ret;
2028 t_u8 *mp_regs = pmadapter->mp_regs;
2029
2030 /* Read the registers in DMA aligned buffer */
2031 #if defined(SD8801)
2032 ret = sdio_drv_read(0, 1, 1, MAX_MP_REGS, mp_regs, &resp);
2033 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2034 ret = sdio_drv_read(REG_PORT | MLAN_SDIO_BYTE_MODE_MASK, 1, 1, MAX_MP_REGS, mp_regs, &resp);
2035 #endif
2036
2037 if (!ret)
2038 {
2039 return;
2040 }
2041
2042 t_u8 sdio_ireg = mp_regs[HOST_INT_STATUS_REG];
2043
2044 if (sdio_ireg != 0U)
2045 {
2046 /*
2047 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
2048 * Clear the interrupt status register
2049 */
2050 pmadapter->sdio_ireg |= sdio_ireg;
2051 }
2052
2053 #if CONFIG_WMM
2054 t_u32 wr_bitmap;
2055
2056 #if defined(SD8801)
2057 wr_bitmap = ((t_u16)mp_regs[WR_BITMAP_U]) << 8;
2058 wr_bitmap |= (t_u16)mp_regs[WR_BITMAP_L];
2059 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2060 wr_bitmap = (t_u32)mp_regs[WR_BITMAP_L];
2061 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_U]) << 8;
2062 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_1L]) << 16;
2063 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_1U]) << 24;
2064 #endif
2065
2066 if (!!wr_bitmap)
2067 {
2068 if (mlan_adap->wait_txbuf == true)
2069 {
2070 OSA_SemaphorePost((osa_semaphore_handle_t)txbuf_sem);
2071 send_wifi_driver_tx_data_event(0);
2072 }
2073 }
2074 #endif
2075
2076 #if CONFIG_WIFI_IO_DEBUG
2077 t_u32 rd_bitmap;
2078 #if !CONFIG_WMM
2079 t_u32 wr_bitmap;
2080
2081 #if defined(SD8801)
2082 wr_bitmap = ((t_u16)mp_regs[WR_BITMAP_U]) << 8;
2083 wr_bitmap |= (t_u16)mp_regs[WR_BITMAP_L];
2084 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2085 wr_bitmap = (t_u32)mp_regs[WR_BITMAP_L];
2086 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_U]) << 8;
2087 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_1L]) << 16;
2088 wr_bitmap |= ((t_u32)mp_regs[WR_BITMAP_1U]) << 24;
2089 #endif
2090
2091 #endif
2092 #if defined(SD8801)
2093 rd_bitmap = ((t_u16)mp_regs[RD_BITMAP_U]) << 8;
2094 rd_bitmap |= (t_u16)mp_regs[RD_BITMAP_L];
2095 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2096 rd_bitmap = (t_u32)mp_regs[RD_BITMAP_L];
2097 rd_bitmap |= ((t_u32)mp_regs[RD_BITMAP_U]) << 8;
2098 rd_bitmap |= ((t_u32)mp_regs[RD_BITMAP_1L]) << 16;
2099 rd_bitmap |= ((t_u32)mp_regs[RD_BITMAP_1U]) << 24;
2100 #endif
2101
2102 (void)PRINTF("INT : rd_bitmap=0x%x\n\r", rd_bitmap);
2103
2104 (void)PRINTF("INT : wr_bitmap=0x%x\n\r", wr_bitmap);
2105
2106 (void)PRINTF("INT : sdio_ireg = (0x%x)\r\n", sdio_ireg);
2107 #endif /* CONFIG_WIFI_IO_DEBUG */
2108 }
2109
2110 #if CONFIG_TP_OPTIMIZATIONS
bitcount(t_u32 num)2111 static t_u32 bitcount(t_u32 num)
2112 {
2113 t_u32 count = 0;
2114 static t_u32 nibblebits[] = { 0, 1, 1, 2, 1, 2, 2, 3,
2115 1, 2, 2, 3, 2, 3, 3, 4 };
2116 for (; num != 0; num >>= 4)
2117 count += nibblebits[num & 0x0f];
2118 return count;
2119 }
2120 #endif
2121 #if CONFIG_SDIO_MULTI_PORT_RX_AGGR
2122 #if CONFIG_TP_OPTIMIZATIONS
2123 static t_u8 start_check = 0;
2124 static t_u8 skip_int = 0;
2125 #endif
2126
2127 /* returns port number from rd_bitmap. if ctrl port, then it clears
2128 * the bit and does nothing else
2129 * 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)2130 static mlan_status wlan_get_rd_port(mlan_adapter *pmadapter, t_u32 *pport, t_u32 *rxlen, t_u32 *rxblocks, bool *aggr)
2131 {
2132 #if defined(SD8801)
2133 t_u16 rd_bitmap = pmadapter->mp_rd_bitmap;
2134 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2135 t_u32 rd_bitmap = pmadapter->mp_rd_bitmap;
2136 #endif
2137 t_u16 pkt_cnt = 0;
2138 t_u32 len_reg_l, len_reg_u;
2139 t_u32 rx_len;
2140 t_u32 rx_blocks;
2141 t_u16 ports = 0;
2142 t_u32 start_port = -1;
2143 t_u32 cmd53_port = 0;
2144 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2145 t_u32 port_count = 0;
2146 #endif
2147 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2148 uint32_t *rxdataAddr = NULL;
2149 #endif
2150
2151 *pport = -1;
2152 *rxlen = 0;
2153 *rxblocks = 0;
2154
2155 wifi_io_d(
2156 "wlan_get_rd_port: mp_rd_bitmap=0x%x"
2157 " curr_rd_bitmap=0x%x\r\n",
2158 pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port);
2159
2160 #if defined(SD8801)
2161 if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK)))
2162 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2163 if (!(rd_bitmap & DATA_PORT_MASK))
2164 #endif
2165 {
2166 return MLAN_STATUS_FAILURE;
2167 }
2168
2169 #if defined(SD8801)
2170 if (pmadapter->mp_rd_bitmap & CTRL_PORT_MASK)
2171 {
2172 pmadapter->mp_rd_bitmap &= (t_u32)(~CTRL_PORT_MASK);
2173 *pport = CTRL_PORT;
2174
2175 len_reg_l = RD_LEN_P0_L + (*pport << 1);
2176 len_reg_u = RD_LEN_P0_U + (*pport << 1);
2177 rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
2178 rx_len |= (t_u16)pmadapter->mp_regs[len_reg_l];
2179 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) / MLAN_SDIO_BLOCK_SIZE;
2180 rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2181 *rxlen = rx_len;
2182 *rxblocks = rx_blocks;
2183
2184 *pport = mlan_adap->ioport + *pport;
2185
2186 wifi_io_d("RX: port=%d rxlen=%u rx_blocks=%u\r\n", *pport, *rxlen, *rxblocks);
2187
2188 wifi_io_d("wlan_get_rd_port: port=%d mp_rd_bitmap=0x%04x", *pport, pmadapter->mp_rd_bitmap);
2189 }
2190 else
2191 {
2192 #endif
2193
2194 #if CONFIG_TP_OPTIMIZATIONS
2195 /* This change is being added to handle low throughput caused for Tx due to excess interrupts received for Rx.
2196 * The intention is to ignore the interrupt if received agreggated packets are less than 4.
2197 * However, there could be single data packets during DHCP request, etc. whose Rx interrupt should not be skipped.
2198 * For actual data, we are checking if read bitmap has at least 4 ports available if current read port is 27.
2199 * If current read port is greater than 27 then any number of available ports is fine. */
2200 if (bitcount(pmadapter->mp_rd_bitmap) == 8U)
2201 {
2202 start_check = 1;
2203 }
2204
2205 if (skip_int == 2)
2206 {
2207 start_check = 0;
2208 }
2209 /* Data */
2210 if ((start_check) && ((pmadapter->mp_rd_bitmap & ((pmadapter->curr_rd_port > 27 ? 1U : 0xFU) << pmadapter->curr_rd_port)) == 0U))
2211 {
2212 skip_int++;
2213 return MLAN_STATUS_FAILURE;
2214 }
2215 #endif
2216 while ((pmadapter->mp_rd_bitmap & (1U << pmadapter->curr_rd_port)) != 0U)
2217 {
2218 *pport = pmadapter->curr_rd_port;
2219
2220 len_reg_l = RD_LEN_P0_L + (*pport << 1U);
2221 len_reg_u = RD_LEN_P0_U + (*pport << 1U);
2222 rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
2223 rx_len |= (t_u16)pmadapter->mp_regs[len_reg_l];
2224 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1U) / MLAN_SDIO_BLOCK_SIZE;
2225 rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2226 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2227 if (wm_wifi.wifi_get_rxbuf_desc != NULL)
2228 {
2229 rxdataAddr = (uint32_t *)wm_wifi.wifi_get_rxbuf_desc(rx_len);
2230
2231 if (rxdataAddr == NULL)
2232 {
2233 PRINTF("No pbuf\r\n");
2234 break;
2235 }
2236 }
2237 #else
2238 if ((*rxlen + rx_len) > INBUF_SIZE)
2239 {
2240 break;
2241 }
2242 #endif
2243
2244 pmadapter->mp_rd_bitmap &=
2245 #if defined(SD8801)
2246 (t_u16)(~(1 << pmadapter->curr_rd_port));
2247 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2248 (t_u32)(~(1 << pmadapter->curr_rd_port));
2249 #endif
2250
2251 #if defined(SD8801)
2252 if (!pkt_cnt)
2253 start_port = *pport;
2254 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2255 if (start_port == -1)
2256 {
2257 start_port = *pport;
2258 }
2259 #endif
2260
2261 #if defined(SD8801)
2262 if (start_port <= *pport)
2263 {
2264 ports |= (1 << (pkt_cnt));
2265 }
2266 else
2267 {
2268 ports |= (1 << (pkt_cnt + 1));
2269 }
2270 #endif
2271 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2272 if (rxdataAddr)
2273 {
2274 sg_set_buf(rxdataAddr, rx_len);
2275 num_sg++;
2276 }
2277 #endif
2278
2279 *rxlen += rx_len;
2280 *rxblocks += rx_blocks;
2281
2282 //PRINTF("RX: port=%d rxlen=%u rx_blocks=%u\r\n", *pport, *rxlen, *rxblocks);
2283
2284 if (++pmadapter->curr_rd_port == MAX_PORT)
2285 {
2286 #if defined(SD8801)
2287 pmadapter->curr_rd_port = 1;
2288 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2289 pmadapter->curr_rd_port = 0;
2290 #endif
2291 }
2292
2293 pkt_cnt++;
2294 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2295 ports++;
2296 #endif
2297
2298 if (pkt_cnt == SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX)
2299 {
2300 break;
2301 }
2302 #if defined(SD8801)
2303 if ((pmadapter->curr_rd_port < start_port) &&
2304 (((MAX_PORT - start_port) + pmadapter->curr_rd_port) >= SDIO_MP_AGGR_DEF_PKT_LIMIT))
2305 {
2306 break;
2307 }
2308 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2309 if (((pmadapter->curr_rd_port < start_port) &&
2310 (((MAX_PORT - start_port) + pmadapter->curr_rd_port) >= (pmadapter->mp_end_port >> 1))) ||
2311 ((pmadapter->curr_rd_port - start_port) >= (pmadapter->mp_end_port >> 1)))
2312 {
2313 break;
2314 }
2315 #endif
2316 }
2317
2318 if (*pport == -1 || ports == 0)
2319 {
2320 wifi_io_e("wlan_get_rd_port : Returning FAILURE");
2321 return MLAN_STATUS_FAILURE;
2322 }
2323
2324 #if defined(SD8801)
2325 if (pkt_cnt > 1)
2326 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2327 if (ports > 1U)
2328 #endif
2329 {
2330 #if defined(SD8801)
2331 cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE | (ports << 4)) + start_port;
2332 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2333 port_count = ports - 1U;
2334 cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE | (port_count << 8)) + start_port;
2335 #endif
2336 *pport = cmd53_port;
2337
2338 *aggr = true;
2339
2340 //(void)PRINTF("cmd53_port=%x, ports=%x, start_port=%x rxlen=%d rxblocks=%d\r\n", cmd53_port, ports,
2341 //start_port, *rxlen, *rxblocks);
2342 }
2343 else
2344 {
2345 *pport = mlan_adap->ioport + *pport;
2346 }
2347
2348 wifi_io_d("port=%x mp_rd_bitmap=0x%x -> 0x%x\n", *pport, rd_bitmap, pmadapter->mp_rd_bitmap);
2349 #if defined(SD8801)
2350 }
2351 #endif
2352
2353 return MLAN_STATUS_SUCCESS;
2354 }
2355
2356 /*
2357 * Assumes that pmadapter->mp_rd_bitmap contains latest values
2358 */
_handle_sdio_packet_read(mlan_adapter * pmadapter,t_u8 ** packet,t_u32 * datalen,t_u32 * pkt_type)2359 static mlan_status _handle_sdio_packet_read(mlan_adapter *pmadapter, t_u8 **packet, t_u32 *datalen, t_u32 *pkt_type)
2360 {
2361 t_u32 port;
2362 t_u32 rx_len = 0, rx_blocks = 0;
2363 bool aggr = false;
2364
2365 mlan_status ret = wlan_get_rd_port(pmadapter, &port, &rx_len, &rx_blocks, &aggr);
2366
2367 /* nothing to read */
2368 if (ret != MLAN_STATUS_SUCCESS)
2369 {
2370 return ret;
2371 }
2372
2373 *datalen = rx_len;
2374
2375 *packet = wlan_read_rcv_packet(port, rx_len, rx_blocks, pkt_type, aggr);
2376
2377 if ((*packet) == MNULL)
2378 {
2379 return MLAN_STATUS_FAILURE;
2380 }
2381
2382 return MLAN_STATUS_SUCCESS;
2383 }
2384 #else
2385 /* returns port number from rd_bitmap. if ctrl port, then it clears
2386 * the bit and does nothing else
2387 * if data port then increments curr_port value also */
wlan_get_rd_port(mlan_adapter * pmadapter,t_u32 * pport)2388 static mlan_status wlan_get_rd_port(mlan_adapter *pmadapter, t_u32 *pport)
2389 {
2390 #if defined(SD8801)
2391 t_u16 rd_bitmap = pmadapter->mp_rd_bitmap;
2392 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2393 t_u32 rd_bitmap = pmadapter->mp_rd_bitmap;
2394 #endif
2395
2396 wifi_io_d(
2397 "wlan_get_rd_port: mp_rd_bitmap=0x%x"
2398 " curr_rd_bitmap=0x%x",
2399 pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port);
2400
2401 #if defined(SD8801)
2402 if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK)))
2403 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2404 if (!(rd_bitmap & DATA_PORT_MASK))
2405 #endif
2406 return MLAN_STATUS_FAILURE;
2407
2408 #if defined(SD8801)
2409 if (pmadapter->mp_rd_bitmap & CTRL_PORT_MASK)
2410 {
2411 pmadapter->mp_rd_bitmap &= (t_u16)(~CTRL_PORT_MASK);
2412 *pport = CTRL_PORT;
2413
2414 wifi_io_d("wlan_get_rd_port: port=%d mp_rd_bitmap=0x%04x", *pport, pmadapter->mp_rd_bitmap);
2415 }
2416 else
2417 {
2418 #endif
2419 /* Data */
2420 if ((pmadapter->mp_rd_bitmap & (1 << pmadapter->curr_rd_port)) != 0U)
2421 {
2422 pmadapter->mp_rd_bitmap &=
2423 #if defined(SD8801)
2424 (t_u16)(~(1 << pmadapter->curr_rd_port));
2425 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2426 (t_u32)(~(1 << pmadapter->curr_rd_port));
2427 #endif
2428 *pport = pmadapter->curr_rd_port;
2429
2430 if (++pmadapter->curr_rd_port == MAX_PORT)
2431 #if defined(SD8801)
2432 pmadapter->curr_rd_port = 1;
2433 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2434 pmadapter->curr_rd_port = 0;
2435 #endif
2436 }
2437 else
2438 {
2439 wifi_io_e("wlan_get_rd_port : Returning FAILURE");
2440 return MLAN_STATUS_FAILURE;
2441 }
2442
2443 wifi_io_d("port=%d mp_rd_bitmap=0x%x -> 0x%x\n", *pport, rd_bitmap, pmadapter->mp_rd_bitmap);
2444 #if defined(SD8801)
2445 }
2446 #endif
2447
2448 return MLAN_STATUS_SUCCESS;
2449 }
2450
2451 /*
2452 * Assumes that pmadapter->mp_rd_bitmap contains latest values
2453 */
_handle_sdio_packet_read(mlan_adapter * pmadapter,t_u8 ** packet,t_u32 * datalen,t_u32 * pkt_type)2454 static mlan_status _handle_sdio_packet_read(mlan_adapter *pmadapter, t_u8 **packet, t_u32 *datalen, t_u32 *pkt_type)
2455 {
2456 t_u32 port;
2457 t_u32 rx_len, rx_blocks;
2458
2459 mlan_status ret = wlan_get_rd_port(pmadapter, &port);
2460
2461 /* nothing to read */
2462 if (ret != MLAN_STATUS_SUCCESS)
2463 return ret;
2464
2465 t_u32 len_reg_l = RD_LEN_P0_L + (port << 1);
2466 t_u32 len_reg_u = RD_LEN_P0_U + (port << 1);
2467
2468 rx_len = ((t_u16)pmadapter->mp_regs[len_reg_u]) << 8;
2469 *datalen = rx_len |= (t_u16)pmadapter->mp_regs[len_reg_l];
2470
2471 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) / MLAN_SDIO_BLOCK_SIZE;
2472 rx_len = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2473
2474 port = mlan_adap->ioport + port;
2475
2476 *packet = wlan_read_rcv_packet(port, rx_len, rx_blocks, pkt_type, false);
2477
2478 if (!*packet)
2479 return MLAN_STATUS_FAILURE;
2480
2481 return MLAN_STATUS_SUCCESS;
2482 }
2483 #endif
2484
2485 #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)2486 static mlan_status _handle_sdio_cmd_read(
2487 mlan_adapter *pmadapter, t_u8 **packet, t_u32 *datalen, t_u32 *pkt_type, t_u32 rx_len, t_u32 rx_blocks)
2488 {
2489 *datalen = rx_len;
2490
2491 *packet = wlan_read_rcv_packet(mlan_adap->ioport | CMD_PORT_SLCT, rx_len, rx_blocks, pkt_type, false);
2492
2493 if ((*packet) == MNULL)
2494 {
2495 return MLAN_STATUS_FAILURE;
2496 }
2497
2498 return MLAN_STATUS_SUCCESS;
2499 }
2500 /*
2501 * This function keeps on looping till all the packets are read
2502 */
handle_sdio_cmd_read(mlan_adapter * pmadapter,t_u32 rx_len,t_u32 rx_blocks)2503 static void handle_sdio_cmd_read(mlan_adapter *pmadapter, t_u32 rx_len, t_u32 rx_blocks)
2504 {
2505 t_u32 datalen = 0;
2506
2507 t_u32 pkt_type = 0;
2508 t_u8 *packet = NULL;
2509
2510 (void)_handle_sdio_cmd_read(pmadapter, &packet, &datalen, &pkt_type, rx_len, rx_blocks);
2511 if (pkt_type == MLAN_TYPE_CMD || pkt_type == MLAN_TYPE_EVENT)
2512 {
2513 /* non-data packets such as events
2514 and command responses are
2515 handled here */
2516 (void)wlan_decode_rx_packet(packet, pkt_type);
2517 }
2518 }
2519 #endif
2520
2521 /*
2522 * This function keeps on looping till all the packets are read
2523 */
handle_sdio_packet_read(mlan_adapter * pmadapter)2524 static void handle_sdio_packet_read(mlan_adapter *pmadapter)
2525 {
2526 mlan_status ret = MLAN_STATUS_SUCCESS;
2527 t_u32 datalen = 0;
2528
2529 pmadapter->mp_rd_bitmap =
2530 #if defined(SD8801)
2531 ((t_u16)pmadapter->mp_regs[RD_BITMAP_U]) << 8;
2532 pmadapter->mp_rd_bitmap |= (t_u16)pmadapter->mp_regs[RD_BITMAP_L];
2533 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2534 (t_u32)pmadapter->mp_regs[RD_BITMAP_L];
2535 pmadapter->mp_rd_bitmap |= ((t_u32)pmadapter->mp_regs[RD_BITMAP_U]) << 8;
2536 pmadapter->mp_rd_bitmap |= ((t_u32)pmadapter->mp_regs[RD_BITMAP_1L]) << 16;
2537 pmadapter->mp_rd_bitmap |= ((t_u32)pmadapter->mp_regs[RD_BITMAP_1U]) << 24;
2538 #endif
2539
2540 while (true)
2541 {
2542 t_u32 pkt_type = 0;
2543 #if !FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2544 t_u8 interface;
2545 t_u32 rx_blocks;
2546 t_u32 total_size = 0;
2547 t_u32 size = 0;
2548 #endif
2549 t_u8 *packet = NULL;
2550
2551 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2552 num_sg = 0;
2553 sg_init_table();
2554 #endif
2555
2556 ret = _handle_sdio_packet_read(pmadapter, &packet, &datalen, &pkt_type);
2557 if (ret != MLAN_STATUS_SUCCESS)
2558 {
2559 /* nothing to read. break out of while loop */
2560 break;
2561 }
2562
2563 if (pkt_type == MLAN_TYPE_DATA)
2564 {
2565
2566 #if FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2567 if (num_sg > 0)
2568 {
2569 // extern void net_rx_notify();
2570
2571 // net_rx_notify();
2572 wm_wifi.data_input_callback(0, NULL, 0);
2573 #if 0
2574 for (sg_idx = 0; sg_idx < num_sg; sg_idx++)
2575 {
2576 SDIOPkt *insdiopkt = (SDIOPkt *)(void *)rx_bufs[sg_idx];
2577 size = insdiopkt->size;
2578 pkt_type = insdiopkt->pkttype;
2579
2580 interface = *((t_u8 *)packet + INTF_HEADER_LEN);
2581
2582 //PRINTF("IN: i/f: %d len: %d\r\n", interface, size);
2583
2584 if (bus.wifi_low_level_input != NULL)
2585 {
2586 (void)bus.wifi_low_level_input(interface, rx_bufs[sg_idx], size);
2587 }
2588 }
2589 #endif
2590 }
2591 #else
2592 {
2593 while (total_size < datalen)
2594 {
2595 SDIOPkt *insdiopkt = (SDIOPkt *)(void *)packet;
2596 size = insdiopkt->size;
2597 pkt_type = insdiopkt->pkttype;
2598
2599 rx_blocks = (size + MLAN_SDIO_BLOCK_SIZE - 1U) / MLAN_SDIO_BLOCK_SIZE;
2600 size = (t_u16)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2601
2602 interface = *((t_u8 *)packet + INTF_HEADER_LEN);
2603
2604 //PRINTF("IN: i/f: %d len: %d\r\n", interface, size);
2605
2606 if (!size)
2607 {
2608 break;
2609 }
2610
2611 if (bus.wifi_low_level_input != NULL)
2612 {
2613 (void)bus.wifi_low_level_input(interface, packet, size);
2614 }
2615
2616 packet += size;
2617 total_size += size;
2618 }
2619 }
2620 #endif
2621 }
2622 else
2623 {
2624 /* non-data packets such as events
2625 and command responses are
2626 handled here */
2627 (void)wlan_decode_rx_packet(packet, pkt_type);
2628 }
2629 }
2630 }
2631
2632 /*
2633 * This is supposed to be called in thread context.
2634 */
wlan_process_int_status(mlan_adapter * pmadapter)2635 mlan_status wlan_process_int_status(mlan_adapter *pmadapter)
2636 {
2637 mlan_status ret = MLAN_STATUS_SUCCESS;
2638 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2639 t_u8 cmd_rd_len_0 = CMD_RD_LEN_0;
2640 t_u8 cmd_rd_len_1 = CMD_RD_LEN_1;
2641 t_u32 rx_len;
2642 t_u32 rx_blocks;
2643 #endif
2644
2645 /* Get the interrupt status */
2646 wlan_interrupt(pmadapter);
2647
2648 t_u8 sdio_ireg = pmadapter->sdio_ireg;
2649 pmadapter->sdio_ireg = 0;
2650
2651 if (!sdio_ireg)
2652 {
2653 goto done;
2654 }
2655
2656 #if defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2657 /* check the command port */
2658 if ((sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS) != 0U)
2659 {
2660 if (pmadapter->cmd_sent != 0U)
2661 {
2662 pmadapter->cmd_sent = MFALSE;
2663 }
2664 PRINTM(MINFO, "cmd_sent=%d\n", pmadapter->cmd_sent);
2665 }
2666
2667 if ((sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) != 0U)
2668 {
2669 /* read the len of control packet */
2670 rx_len = ((t_u32)pmadapter->mp_regs[cmd_rd_len_1]) << 8;
2671 rx_len |= (t_u32)pmadapter->mp_regs[cmd_rd_len_0];
2672 PRINTM(MINFO, "RX: cmd port rx_len=%u\n", rx_len);
2673
2674 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1U) / MLAN_SDIO_BLOCK_SIZE;
2675
2676 // (void)PRINTF("CMD: cmd port rx_len=%u rx_blocks=%u\r\n", rx_len, rx_blocks);
2677 rx_len = (t_u32)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2678
2679 handle_sdio_cmd_read(pmadapter, rx_len, rx_blocks);
2680 }
2681 #elif defined(SD8801)
2682 /*
2683 * Below two statement look like they are present for the purpose
2684 * of unconditional initializing of mp_wr_bitmap which will be used
2685 * during packet xmit. proper mlan code does not do this most
2686 * probably because they have used wlan_get_wr_port_data() to
2687 * decide on the write port which we have not done. Check this out
2688 * later.
2689 */
2690 pmadapter->mp_wr_bitmap = ((t_u16)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2691 pmadapter->mp_wr_bitmap |= (t_u16)pmadapter->mp_regs[WR_BITMAP_L];
2692 #endif
2693
2694 pmadapter->mp_wr_bitmap =
2695 #if defined(SD8801)
2696 ((t_u16)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2697 pmadapter->mp_wr_bitmap |= (t_u16)pmadapter->mp_regs[WR_BITMAP_L];
2698 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2699 (t_u32)pmadapter->mp_regs[WR_BITMAP_L];
2700 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2701 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_1L]) << 16;
2702 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_1U]) << 24;
2703 #endif
2704
2705 /*
2706 * DN_LD_HOST_INT_STATUS interrupt happens when the txmit sdio
2707 * ports are freed This is usually when we write to port most
2708 * significant port.
2709 */
2710 if ((sdio_ireg & DN_LD_HOST_INT_STATUS) != 0U)
2711 {
2712 pmadapter->mp_wr_bitmap =
2713 #if defined(SD8801)
2714 ((t_u16)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2715 pmadapter->mp_wr_bitmap |= (t_u16)pmadapter->mp_regs[WR_BITMAP_L];
2716 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2717 (t_u32)pmadapter->mp_regs[WR_BITMAP_L];
2718 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_U]) << 8;
2719 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_1L]) << 16;
2720 pmadapter->mp_wr_bitmap |= ((t_u32)pmadapter->mp_regs[WR_BITMAP_1U]) << 24;
2721 #endif
2722 }
2723
2724 /*
2725 * As firmware will not generate download ready interrupt if the
2726 * port updated is command port only, cmd_sent should be done for
2727 * any SDIO interrupt.
2728 */
2729 #if defined(SD8801)
2730 if (pmadapter->cmd_sent == true)
2731 {
2732 /*
2733 * Check if firmware has attach buffer at command port and
2734 * update just that in wr_bit_map.
2735 */
2736 pmadapter->mp_wr_bitmap |= (t_u16)pmadapter->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK;
2737
2738 if (pmadapter->mp_wr_bitmap & CTRL_PORT_MASK)
2739 pmadapter->cmd_sent = false;
2740 }
2741 #endif
2742
2743 if ((sdio_ireg & UP_LD_HOST_INT_STATUS) != 0U)
2744 {
2745 /* This means there is data to be read */
2746 handle_sdio_packet_read(pmadapter);
2747 }
2748
2749 ret = MLAN_STATUS_SUCCESS;
2750
2751 done:
2752 return ret;
2753 }
2754
2755 /**
2756 * Interrupt callback handler registered with the SDIO driver.
2757 */
handle_cdint(int error)2758 void handle_cdint(int error)
2759 {
2760 /* Wake up LWIP thread. */
2761 if (!error && g_txrx_flag)
2762 {
2763 g_txrx_flag = false;
2764 #if CONFIG_ZEPHYR
2765 (void)OSA_EventNotifyPost(wm_wifi.wifi_core_task_Handle);
2766 #else
2767 (void)OSA_EventSet((osa_event_handle_t)wm_wifi.wifi_event_Handle, WIFI_EVENT_SDIO);
2768 #endif
2769 }
2770 }
2771
wifi_raw_packet_recv(t_u8 ** data,t_u32 * pkt_type)2772 int wifi_raw_packet_recv(t_u8 **data, t_u32 *pkt_type)
2773 {
2774 OSA_SR_ALLOC()
2775 osa_event_flags_t flagsToWait = WIFI_EVENT_SDIO;
2776 osa_event_flags_t pSetFlags;
2777
2778 if (data == MNULL)
2779 {
2780 return -WM_FAIL;
2781 }
2782
2783 OSA_ENTER_CRITICAL();
2784 /* Allow interrupt handler to deliver us a packet */
2785 g_txrx_flag = true;
2786
2787 sdio_enable_interrupt();
2788
2789 OSA_EXIT_CRITICAL()
2790
2791 (void)OSA_EventWait((osa_event_handle_t)wm_wifi.wifi_event_Handle, flagsToWait, false, osaWaitForever_c, &pSetFlags);
2792
2793 OSA_EventClear((osa_event_handle_t)wm_wifi.wifi_event_Handle, WIFI_EVENT_SDIO);
2794
2795 if ((pSetFlags & WIFI_EVENT_SDIO) == 0U)
2796 {
2797 return -WM_FAIL;
2798 }
2799
2800 /* Get the interrupt status */
2801 wlan_interrupt(mlan_adap);
2802
2803 t_u8 sdio_ireg = mlan_adap->sdio_ireg;
2804 mlan_adap->sdio_ireg = 0;
2805
2806 #if defined(SD8801)
2807 if (!(sdio_ireg & UP_LD_HOST_INT_STATUS))
2808 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2809 if (!(sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS))
2810 #endif
2811 {
2812 return -WM_FAIL;
2813 }
2814
2815 t_u32 datalen = 0;
2816
2817 mlan_adap->mp_rd_bitmap =
2818 #if defined(SD8801)
2819 ((t_u16)mlan_adap->mp_regs[RD_BITMAP_U]) << 8;
2820 mlan_adap->mp_rd_bitmap |= (t_u16)mlan_adap->mp_regs[RD_BITMAP_L];
2821 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2822 (t_u32)mlan_adap->mp_regs[RD_BITMAP_L];
2823 mlan_adap->mp_rd_bitmap |= ((t_u32)mlan_adap->mp_regs[RD_BITMAP_U]) << 8;
2824 mlan_adap->mp_rd_bitmap |= ((t_u32)mlan_adap->mp_regs[RD_BITMAP_1L]) << 16;
2825 mlan_adap->mp_rd_bitmap |= ((t_u32)mlan_adap->mp_regs[RD_BITMAP_1U]) << 24;
2826 #endif
2827
2828 t_u8 *packet = NULL;
2829
2830 #if defined(SD8801)
2831 int ret;
2832 while (1)
2833 {
2834 ret = _handle_sdio_packet_read(mlan_adap, &packet, &datalen, pkt_type);
2835 if (ret == MLAN_STATUS_SUCCESS)
2836 {
2837 break;
2838 }
2839 }
2840 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2841
2842 t_u8 cmd_rd_len_0 = CMD_RD_LEN_0;
2843 t_u8 cmd_rd_len_1 = CMD_RD_LEN_1;
2844 t_u32 rx_len;
2845 t_u32 rx_blocks;
2846
2847 /* read the len of control packet */
2848 rx_len = ((t_u32)mlan_adap->mp_regs[cmd_rd_len_1]) << 8;
2849 rx_len |= (t_u32)mlan_adap->mp_regs[cmd_rd_len_0];
2850 PRINTM(MINFO, "RX: cmd port rx_len=%u\n", rx_len);
2851
2852 rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1U) / MLAN_SDIO_BLOCK_SIZE;
2853
2854 rx_len = (t_u32)(rx_blocks * MLAN_SDIO_BLOCK_SIZE);
2855
2856 (void)_handle_sdio_cmd_read(mlan_adap, &packet, &datalen, pkt_type, rx_len, rx_blocks);
2857 #endif
2858 *data = packet;
2859 return WM_SUCCESS;
2860 }
2861
wifi_raw_packet_send(const t_u8 * packet,t_u32 length)2862 int wifi_raw_packet_send(const t_u8 *packet, t_u32 length)
2863 {
2864 if ((packet == MNULL) || !length)
2865 {
2866 return -WM_E_INVAL;
2867 }
2868
2869 if (length > SDIO_OUTBUF_LEN)
2870 {
2871 wifi_io_e("Insufficient buffer");
2872 return -WM_FAIL;
2873 }
2874
2875 t_u32 tx_blocks = 0, buflen = 0;
2876 calculate_sdio_write_params(length, &tx_blocks, &buflen);
2877
2878 (void)memcpy((void *)outbuf, (const void *)packet, length);
2879 #if CONFIG_WIFI_IO_DUMP
2880 dump_hex(outbuf, length);
2881 #endif
2882 uint32_t resp;
2883 #if defined(SD8801)
2884 sdio_drv_write(mlan_adap->ioport, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
2885 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2886 (void)sdio_drv_write(mlan_adap->ioport | CMD_PORT_SLCT, 1, tx_blocks, buflen, (t_u8 *)outbuf, &resp);
2887 #endif
2888 return WM_SUCCESS;
2889 }
2890
sd_wifi_preinit(void)2891 static mlan_status sd_wifi_preinit(void)
2892 {
2893 mlan_status mlanstatus = MLAN_STATUS_SUCCESS;
2894
2895 /* initializes the driver struct */
2896 int sdiostatus = wlan_init_struct();
2897 if (sdiostatus != WM_SUCCESS)
2898 {
2899 wifi_io_e("Init failed. Cannot create init struct");
2900 return MLAN_STATUS_FAILURE;
2901 }
2902
2903 /*
2904 * Register a callback with power manager of MC200/MW300
2905 * This callback will be called on entry /exit
2906 * of low power mode of MC200/MW300 based on first paramter
2907 * passed to the call.
2908 */
2909 // pm_handle = pm_register_cb(ACTION_EXIT_PM3 | ACTION_ENTER_PM4,
2910 // sd_wifi_ps_cb, NULL);
2911
2912 (void)mlan_subsys_init();
2913 seqnum = 0;
2914 txportno = 0;
2915 return mlanstatus;
2916 }
2917
sd_wifi_reset_ports()2918 void sd_wifi_reset_ports()
2919 {
2920 #if defined(SD8801)
2921 txportno = 1;
2922 mlan_adap->curr_rd_port = 1;
2923 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2924 txportno = 0;
2925 mlan_adap->curr_rd_port = 0;
2926 #endif
2927 }
2928
sd_wifi_post_init(enum wlan_type type)2929 mlan_status sd_wifi_post_init(enum wlan_type type)
2930 {
2931 mlan_status mlanstatus = MLAN_STATUS_SUCCESS;
2932 uint32_t resp;
2933 bool invalid_wlantype = MFALSE;
2934 #if defined(SD8801)
2935 sdio_drv_creg_write(HOST_INT_MASK_REG, 1, 0x3, &resp);
2936 #elif defined(SD8978) || defined(SD8987) || defined(SD8997) || defined(SD9097) || defined(SD9098) || defined(SD9177)
2937 (void)sdio_drv_creg_write(HOST_INT_MASK_REG, 1, HIM_ENABLE, &resp);
2938 #endif
2939
2940 /* If we're running a Manufacturing image, start the tasks.
2941 If not, initialize and setup the firmware */
2942 switch (type)
2943 {
2944 case WLAN_TYPE_NORMAL:
2945 fw_init_cfg = 1;
2946 wlan_fw_init_cfg();
2947 fw_init_cfg = 0;
2948 break;
2949 case WLAN_TYPE_WIFI_CALIB:
2950 g_txrx_flag = true;
2951 break;
2952 case WLAN_TYPE_FCC_CERTIFICATION:
2953 g_txrx_flag = true;
2954 break;
2955 default:
2956 wifi_io_e("Enter a valid input to sd_wifi_init");
2957 invalid_wlantype = MTRUE;
2958 break;
2959 }
2960
2961 if (invalid_wlantype == MTRUE)
2962 {
2963 return MLAN_STATUS_FAILURE;
2964 }
2965
2966 sd_wifi_reset_ports();
2967
2968 return mlanstatus;
2969 }
2970
2971 static void *intf;
2972
sd_wifi_init(enum wlan_type type,const uint8_t * fw_start_addr,const size_t size)2973 mlan_status sd_wifi_init(enum wlan_type type, const uint8_t *fw_start_addr, const size_t size)
2974 {
2975 mlan_status ret = MLAN_STATUS_SUCCESS;
2976
2977 ret = sd_wifi_preinit();
2978
2979 if (ret == MLAN_STATUS_SUCCESS)
2980 {
2981 intf = (void *)sdio_init_interface(NULL);
2982
2983 if (intf != MNULL)
2984 {
2985 mlan_adap->fw_start_addr = fw_start_addr;
2986
2987 ret = (mlan_status)firmware_download(fw_start_addr, size, intf, 0);
2988 } else {
2989 ret = MLAN_STATUS_FAILURE;
2990 }
2991 }
2992 return ret;
2993 }
2994
2995 #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)2996 mlan_status sd_wifi_reinit(enum wlan_type type, const uint8_t *fw_start_addr, const size_t size, uint8_t fw_reload)
2997 {
2998 mlan_status ret = MLAN_STATUS_SUCCESS;
2999
3000 if (fw_reload == FW_RELOAD_NO_EMULATION)
3001 {
3002 OSA_SR_ALLOC();
3003 OSA_ENTER_CRITICAL();
3004
3005 /* Allow interrupt handler to deliver us a packet */
3006 g_txrx_flag = false;
3007
3008 sdio_disable_interrupt();
3009
3010 OSA_EXIT_CRITICAL();
3011
3012 sdio_ioport_init();
3013 }
3014
3015 ret = (mlan_status)firmware_download(fw_start_addr, size, intf, fw_reload);
3016
3017 if (ret != MLAN_STATUS_FAILURE)
3018 {
3019 if (fw_reload == FW_RELOAD_NO_EMULATION)
3020 {
3021 OSA_SR_ALLOC();
3022 OSA_ENTER_CRITICAL();
3023 /* Allow interrupt handler to deliver us a packet */
3024 g_txrx_flag = true;
3025
3026 sdio_enable_interrupt();
3027
3028 OSA_EXIT_CRITICAL();
3029 }
3030 }
3031
3032 return ret;
3033 }
3034 #endif
3035
3036 #if CONFIG_BT_SUPPORT
read_sdio_function_recvd()3037 uint8_t read_sdio_function_recvd()
3038 {
3039 uint32_t resp = 0;
3040 uint8_t val;
3041 sdio_drv_creg_read(0x5, 0x0, &resp);
3042 val = resp & 0xf;
3043 return val;
3044 }
3045 #endif
3046
sd_wifi_deinit(void)3047 void sd_wifi_deinit(void)
3048 {
3049 #ifdef WLAN_LOW_POWER_ENABLE
3050 low_power_mode = false;
3051 #endif
3052 cal_data_valid = false;
3053 mac_addr_valid = false;
3054 // pm_deregister_cb(pm_handle);
3055
3056 (void)wlan_cmd_shutdown();
3057 sdio_drv_deinit();
3058 (void)mlan_subsys_deinit();
3059 (void)wlan_deinit_struct();
3060 }
3061
3062 #if CONFIG_FW_VDLL
wifi_get_vdllcommand_buffer(void)3063 HostCmd_DS_COMMAND *wifi_get_vdllcommand_buffer(void)
3064 {
3065 /* First 4 bytes reserved for SDIO pkt header */
3066 return (HostCmd_DS_COMMAND *)(void *)(vdll_cmd_buf + INTF_HEADER_LEN);
3067 }
3068 #endif
3069
wifi_get_command_buffer(void)3070 HostCmd_DS_COMMAND *wifi_get_command_buffer(void)
3071 {
3072 /* First 4 bytes reserved for SDIO pkt header */
3073 return (HostCmd_DS_COMMAND *)(void *)(ctrl_cmd_buf + INTF_HEADER_LEN);
3074 }
3075
3076 /**
3077 * Function to set mlan ioport.
3078 */
set_ioport_inmlan(t_u32 port)3079 void set_ioport_inmlan(t_u32 port)
3080 {
3081 mlan_adap->ioport = port;
3082 }
3083
3084 #if CONFIG_HOST_SLEEP
wifi_print_wakeup_reason(t_u16 hs_wakeup_reason)3085 void wifi_print_wakeup_reason(t_u16 hs_wakeup_reason)
3086 {
3087 if (hs_wakeup_reason == 0)
3088 {
3089 PRINTF("Woken up by unknown reason\r\n");
3090 }
3091 else if (hs_wakeup_reason == 1)
3092 {
3093 PRINTF("Woken up by Broadcast data matched\r\n");
3094 }
3095 else if (hs_wakeup_reason == 2)
3096 {
3097 PRINTF("Woken up by Multicast data matched\r\n");
3098 }
3099 else if (hs_wakeup_reason == 3)
3100 {
3101 PRINTF("Woken up by Unicast data matched\r\n");
3102 }
3103 else if (hs_wakeup_reason == 4)
3104 {
3105 PRINTF("Woken up by Maskable event matched\r\n");
3106 }
3107 else if (hs_wakeup_reason == 5)
3108 {
3109 PRINTF("Woken up by Non-maskable event matched\r\n");
3110 }
3111 else if (hs_wakeup_reason == 6)
3112 {
3113 PRINTF("Woken up by Non-maskable condition matched (EAPoL rekey)\r\n");
3114 }
3115 else if (hs_wakeup_reason == 7)
3116 {
3117 PRINTF("Woken up by Magic pattern matched\r\n");
3118 }
3119 else if (hs_wakeup_reason == 8)
3120 {
3121 PRINTF("Woken up by control frames matched \r\n");
3122 }
3123 else if (hs_wakeup_reason == 9)
3124 {
3125 PRINTF("Woken up by management frame matched \r\n");
3126 }
3127 else if (hs_wakeup_reason == 10)
3128 {
3129 PRINTF("Woken up by GTK rekey failure\r\n");
3130 }
3131 else if (hs_wakeup_reason == 11)
3132 {
3133 PRINTF("Woken up by management frame filter extension matched\r\n");
3134 }
3135 else
3136 {
3137 PRINTF("Woken up by reserved reason\r\n");
3138 }
3139 }
3140
wifi_clear_wakeup_reason(void)3141 void wifi_clear_wakeup_reason(void)
3142 {
3143 if (mlan_adap != NULL)
3144 {
3145 memset(&mlan_adap->wlan_wakeup, 0x0, sizeof(wlan_wakeup_reason));
3146 }
3147 }
3148 #endif
3149