1 /******************************************************************************
3 * Copyright(c) 2015 - 2016 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
20 #define _HAL_HALMAC_C_
22 #include <drv_types.h> /* PADAPTER, struct dvobj_priv, SDIO_ERR_VAL8 and etc. */
23 #include <hal_data.h> /* efuse, PHAL_DATA_TYPE and etc. */
24 #include "halmac/halmac_api.h" /* HALMAC_FW_SIZE_MAX_88XX and etc. */
25 #include "hal_halmac.h" /* dvobj_to_halmac() and ect. */
27 #define DEFAULT_INDICATOR_TIMELMT 1000 /* ms */
28 #define FIRMWARE_MAX_SIZE HALMAC_FW_SIZE_MAX_88XX
31 * Driver API for HALMAC operations
34 #ifdef CONFIG_SDIO_HCI
37 static u8 _halmac_mac_reg_page0_chk(const char *func, struct dvobj_priv *dvobj, u32 offset)
39 #if defined(CONFIG_IO_CHECK_IN_ANA_LOW_CLK) && defined(CONFIG_LPS_LCLK)
40 struct pwrctrl_priv *pwrpriv = &dvobj->pwrctl_priv;
41 u32 mac_reg_offset = 0;
43 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
46 if (pwrpriv->rpwm >= PS_STATE_S2)
49 if (offset & (WLAN_IOREG_DEVICE_ID << 13)) { /*WLAN_IOREG_OFFSET*/
50 mac_reg_offset = offset & HALMAC_WLAN_MAC_REG_MSK;
51 if (mac_reg_offset < 0x100) {
52 RTW_ERR(FUNC_ADPT_FMT "access MAC REG -0x%04x in PS-mode:0x%02x\n",
53 FUNC_ADPT_ARG(dvobj_get_primary_adapter(dvobj)), mac_reg_offset, pwrpriv->pwr_mode);
62 static u8 _halmac_sdio_cmd52_read(void *p, u32 offset)
69 d = (struct dvobj_priv *)p;
70 _halmac_mac_reg_page0_chk(__func__, d, offset);
71 ret = rtw_sdio_read_cmd52(d, offset, &val, 1);
73 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
80 static void _halmac_sdio_cmd52_write(void *p, u32 offset, u8 val)
86 d = (struct dvobj_priv *)p;
87 _halmac_mac_reg_page0_chk(__func__, d, offset);
88 ret = rtw_sdio_write_cmd52(d, offset, &val, 1);
90 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
93 static u8 _halmac_sdio_reg_read_8(void *p, u32 offset)
101 d = (struct dvobj_priv *)p;
103 _halmac_mac_reg_page0_chk(__func__, d, offset);
104 pbuf = rtw_zmalloc(1);
108 err = d->intf_ops->read(d, offset, pbuf, 1, 0);
110 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
122 static u16 _halmac_sdio_reg_read_16(void *p, u32 offset)
124 struct dvobj_priv *d;
130 d = (struct dvobj_priv *)p;
131 val = SDIO_ERR_VAL16;
132 _halmac_mac_reg_page0_chk(__func__, d, offset);
133 pbuf = rtw_zmalloc(2);
137 err = d->intf_ops->read(d, offset, pbuf, 2, 0);
139 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
143 val = le16_to_cpu(*(u16 *)pbuf);
151 static u32 _halmac_sdio_reg_read_32(void *p, u32 offset)
153 struct dvobj_priv *d;
159 d = (struct dvobj_priv *)p;
160 val = SDIO_ERR_VAL32;
161 _halmac_mac_reg_page0_chk(__func__, d, offset);
162 pbuf = rtw_zmalloc(4);
166 err = d->intf_ops->read(d, offset, pbuf, 4, 0);
168 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
172 val = le32_to_cpu(*(u32 *)pbuf);
180 static u8 _halmac_sdio_reg_read_n(void *p, u32 offset, u32 size, u8 *data)
182 struct dvobj_priv *d = (struct dvobj_priv *)p;
183 PSDIO_DATA psdio = &d->intf_data;
190 sdio_read_size = RND4(size);
191 if (sdio_read_size > psdio->block_transfer_len)
192 sdio_read_size = _RND(sdio_read_size, psdio->block_transfer_len);
194 pbuf = rtw_zmalloc(sdio_read_size);
195 if ((!pbuf) || (!data))
198 err = d->intf_ops->read(d, offset, pbuf, sdio_read_size, 0);
200 RTW_ERR("%s: [ERROR] I/O FAIL!\n", __func__);
204 _rtw_memcpy(data, pbuf, size);
207 rtw_mfree(pbuf, sdio_read_size);
212 static void _halmac_sdio_reg_write_8(void *p, u32 offset, u8 val)
214 struct dvobj_priv *d;
219 d = (struct dvobj_priv *)p;
220 _halmac_mac_reg_page0_chk(__func__, d, offset);
221 pbuf = rtw_zmalloc(1);
224 _rtw_memcpy(pbuf, &val, 1);
226 err = d->intf_ops->write(d, offset, pbuf, 1, 0);
228 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
233 static void _halmac_sdio_reg_write_16(void *p, u32 offset, u16 val)
235 struct dvobj_priv *d;
240 d = (struct dvobj_priv *)p;
241 _halmac_mac_reg_page0_chk(__func__, d, offset);
242 val = cpu_to_le16(val);
243 pbuf = rtw_zmalloc(2);
246 _rtw_memcpy(pbuf, &val, 2);
248 err = d->intf_ops->write(d, offset, pbuf, 2, 0);
250 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
255 static void _halmac_sdio_reg_write_32(void *p, u32 offset, u32 val)
257 struct dvobj_priv *d;
262 d = (struct dvobj_priv *)p;
263 _halmac_mac_reg_page0_chk(__func__, d, offset);
264 val = cpu_to_le32(val);
265 pbuf = rtw_zmalloc(4);
268 _rtw_memcpy(pbuf, &val, 4);
270 err = d->intf_ops->write(d, offset, pbuf, 4, 0);
272 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
277 #else /* !CONFIG_SDIO_HCI */
279 static u8 _halmac_reg_read_8(void *p, u32 offset)
281 struct dvobj_priv *d;
285 d = (struct dvobj_priv *)p;
286 adapter = dvobj_get_primary_adapter(d);
288 return rtw_read8(adapter, offset);
291 static u16 _halmac_reg_read_16(void *p, u32 offset)
293 struct dvobj_priv *d;
297 d = (struct dvobj_priv *)p;
298 adapter = dvobj_get_primary_adapter(d);
300 return rtw_read16(adapter, offset);
303 static u32 _halmac_reg_read_32(void *p, u32 offset)
305 struct dvobj_priv *d;
309 d = (struct dvobj_priv *)p;
310 adapter = dvobj_get_primary_adapter(d);
312 return rtw_read32(adapter, offset);
315 static void _halmac_reg_write_8(void *p, u32 offset, u8 val)
317 struct dvobj_priv *d;
322 d = (struct dvobj_priv *)p;
323 adapter = dvobj_get_primary_adapter(d);
325 err = rtw_write8(adapter, offset, val);
327 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
330 static void _halmac_reg_write_16(void *p, u32 offset, u16 val)
332 struct dvobj_priv *d;
337 d = (struct dvobj_priv *)p;
338 adapter = dvobj_get_primary_adapter(d);
340 err = rtw_write16(adapter, offset, val);
342 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
345 static void _halmac_reg_write_32(void *p, u32 offset, u32 val)
347 struct dvobj_priv *d;
352 d = (struct dvobj_priv *)p;
353 adapter = dvobj_get_primary_adapter(d);
355 err = rtw_write32(adapter, offset, val);
357 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
359 #endif /* !CONFIG_SDIO_HCI */
361 static u8 _halmac_mfree(void *p, void *buffer, u32 size)
363 rtw_mfree(buffer, size);
367 static void *_halmac_malloc(void *p, u32 size)
369 return rtw_zmalloc(size);
372 static u8 _halmac_memcpy(void *p, void *dest, void *src, u32 size)
374 _rtw_memcpy(dest, src, size);
378 static u8 _halmac_memset(void *p, void *addr, u8 value, u32 size)
380 _rtw_memset(addr, value, size);
384 static void _halmac_udelay(void *p, u32 us)
389 static u8 _halmac_mutex_init(void *p, HALMAC_MUTEX *pMutex)
391 _rtw_mutex_init(pMutex);
395 static u8 _halmac_mutex_deinit(void *p, HALMAC_MUTEX *pMutex)
397 _rtw_mutex_free(pMutex);
401 static u8 _halmac_mutex_lock(void *p, HALMAC_MUTEX *pMutex)
405 err = _enter_critical_mutex(pMutex, NULL);
412 static u8 _halmac_mutex_unlock(void *p, HALMAC_MUTEX *pMutex)
414 _exit_critical_mutex(pMutex, NULL);
418 static u8 _halmac_msg_print(void *p, u32 msg_type, u8 msg_level, s8 *fmt, ...)
421 #define MSG_PREFIX "[HALMAC]"
423 u8 str[MSG_LEN] = {0};
428 vsnprintf(str, MSG_LEN, fmt, args);
431 if (msg_level <= HALMAC_DBG_ERR)
432 RTW_ERR(MSG_PREFIX "%s", str);
433 else if (msg_level <= HALMAC_DBG_WARN)
434 RTW_WARN(MSG_PREFIX "%s", str);
436 RTW_DBG(MSG_PREFIX "%s", str);
441 static u8 _halmac_buff_print(void *p, u32 msg_type, u8 msg_level, s8 *buf, u32 size)
443 #define MSG_PREFIX "[HALMAC]"
445 if (msg_level <= HALMAC_DBG_WARN)
446 RTW_INFO_DUMP(MSG_PREFIX, buf, size);
448 RTW_DBG_DUMP(MSG_PREFIX, buf, size);
454 const char *const RTW_HALMAC_FEATURE_NAME[] = {
455 "HALMAC_FEATURE_CFG_PARA",
456 "HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE",
457 "HALMAC_FEATURE_DUMP_LOGICAL_EFUSE",
458 "HALMAC_FEATURE_UPDATE_PACKET",
459 "HALMAC_FEATURE_UPDATE_DATAPACK",
460 "HALMAC_FEATURE_RUN_DATAPACK",
461 "HALMAC_FEATURE_CHANNEL_SWITCH",
462 "HALMAC_FEATURE_IQK",
463 "HALMAC_FEATURE_POWER_TRACKING",
464 "HALMAC_FEATURE_PSD",
468 static inline u8 is_valid_id_status(HALMAC_FEATURE_ID id, HALMAC_CMD_PROCESS_STATUS status)
471 case HALMAC_FEATURE_CFG_PARA:
472 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
474 case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
475 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
476 if (HALMAC_CMD_PROCESS_DONE != status)
477 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
478 __FUNCTION__, id, status);
480 case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
481 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
482 if (HALMAC_CMD_PROCESS_DONE != status)
483 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
484 __FUNCTION__, id, status);
486 case HALMAC_FEATURE_UPDATE_PACKET:
487 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
489 case HALMAC_FEATURE_UPDATE_DATAPACK:
490 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
492 case HALMAC_FEATURE_RUN_DATAPACK:
493 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
495 case HALMAC_FEATURE_CHANNEL_SWITCH:
496 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
498 case HALMAC_FEATURE_IQK:
499 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
501 case HALMAC_FEATURE_POWER_TRACKING:
502 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
504 case HALMAC_FEATURE_PSD:
505 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
507 case HALMAC_FEATURE_ALL:
508 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
511 RTW_ERR("%s: unknown feature id(%d)\n", __FUNCTION__, id);
518 static int init_halmac_event_with_waittime(struct dvobj_priv *d, HALMAC_FEATURE_ID id, u8 *buf, u32 size, u32 time)
520 struct submit_ctx *sctx;
523 if (!d->hmpriv.indicator[id].sctx) {
524 sctx = (struct submit_ctx *)rtw_zmalloc(sizeof(*sctx));
528 RTW_WARN("%s: id(%d) sctx is not NULL!!\n", __FUNCTION__, id);
529 sctx = d->hmpriv.indicator[id].sctx;
530 d->hmpriv.indicator[id].sctx = NULL;
533 rtw_sctx_init(sctx, time);
534 d->hmpriv.indicator[id].buffer = buf;
535 d->hmpriv.indicator[id].buf_size = size;
536 d->hmpriv.indicator[id].ret_size = 0;
537 d->hmpriv.indicator[id].status = 0;
538 /* fill sctx at least to sure other variables are all ready! */
539 d->hmpriv.indicator[id].sctx = sctx;
544 static inline int init_halmac_event(struct dvobj_priv *d, HALMAC_FEATURE_ID id, u8 *buf, u32 size)
546 return init_halmac_event_with_waittime(d, id, buf, size, DEFAULT_INDICATOR_TIMELMT);
549 static void free_halmac_event(struct dvobj_priv *d, HALMAC_FEATURE_ID id)
551 struct submit_ctx *sctx;
554 if (!d->hmpriv.indicator[id].sctx)
557 sctx = d->hmpriv.indicator[id].sctx;
558 d->hmpriv.indicator[id].sctx = NULL;
559 rtw_mfree((u8 *)sctx, sizeof(*sctx));
562 static int wait_halmac_event(struct dvobj_priv *d, HALMAC_FEATURE_ID id)
566 struct submit_ctx *sctx;
570 sctx = d->hmpriv.indicator[id].sctx;
574 ret = rtw_sctx_wait(sctx, RTW_HALMAC_FEATURE_NAME[id]);
575 free_halmac_event(d, id);
579 /* timeout! We have to reset halmac state */
580 RTW_ERR("%s: Wait id(%d, %s) TIMEOUT! Reset HALMAC state!\n",
581 __FUNCTION__, id, RTW_HALMAC_FEATURE_NAME[id]);
582 mac = dvobj_to_halmac(d);
583 api = HALMAC_GET_API(mac);
584 api->halmac_reset_feature(mac, id);
591 * Always return _TRUE, HALMAC don't care the return value.
593 static u8 _halmac_event_indication(void *p, HALMAC_FEATURE_ID feature_id, HALMAC_CMD_PROCESS_STATUS process_status, u8 *buf, u32 size)
595 struct dvobj_priv *d;
598 struct halmac_indicator *tbl, *indicator;
599 struct submit_ctx *sctx;
604 d = (struct dvobj_priv *)p;
605 adapter = dvobj_get_primary_adapter(d);
606 hal = GET_HAL_DATA(adapter);
607 tbl = d->hmpriv.indicator;
609 /* Filter(Skip) middle status indication */
610 ret = is_valid_id_status(feature_id, process_status);
614 indicator = &tbl[feature_id];
615 indicator->status = process_status;
616 indicator->ret_size = size;
617 if (!indicator->sctx) {
618 RTW_WARN("%s: No feature id(%d, %s) waiting!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
621 sctx = indicator->sctx;
623 if (HALMAC_CMD_PROCESS_ERROR == process_status) {
624 RTW_ERR("%s: Something wrong id(%d, %s)!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
625 rtw_sctx_done_err(&sctx, RTW_SCTX_DONE_UNKNOWN);
629 if (size > indicator->buf_size) {
630 RTW_WARN("%s: id(%d, %s) buffer is not enough(%d<%d), data will be truncated!\n",
631 __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id], indicator->buf_size, size);
632 cpsz = indicator->buf_size;
636 if (cpsz && indicator->buffer)
637 _rtw_memcpy(indicator->buffer, buf, cpsz);
639 rtw_sctx_done(&sctx);
645 HALMAC_PLATFORM_API rtw_halmac_platform_api = {
647 #ifdef CONFIG_SDIO_HCI
648 .SDIO_CMD52_READ = _halmac_sdio_cmd52_read,
649 .SDIO_CMD53_READ_8 = _halmac_sdio_reg_read_8,
650 .SDIO_CMD53_READ_16 = _halmac_sdio_reg_read_16,
651 .SDIO_CMD53_READ_32 = _halmac_sdio_reg_read_32,
652 .SDIO_CMD53_READ_N = _halmac_sdio_reg_read_n,
653 .SDIO_CMD52_WRITE = _halmac_sdio_cmd52_write,
654 .SDIO_CMD53_WRITE_8 = _halmac_sdio_reg_write_8,
655 .SDIO_CMD53_WRITE_16 = _halmac_sdio_reg_write_16,
656 .SDIO_CMD53_WRITE_32 = _halmac_sdio_reg_write_32,
658 #endif /* CONFIG_SDIO_HCI */
659 #if defined(CONFIG_USB_HCI) || defined(CONFIG_PCIE_HCI)
660 .REG_READ_8 = _halmac_reg_read_8,
661 .REG_READ_16 = _halmac_reg_read_16,
662 .REG_READ_32 = _halmac_reg_read_32,
663 .REG_WRITE_8 = _halmac_reg_write_8,
664 .REG_WRITE_16 = _halmac_reg_write_16,
665 .REG_WRITE_32 = _halmac_reg_write_32,
666 #endif /* CONFIG_USB_HCI || CONFIG_PCIE_HCI */
670 /* impletement in HAL-IC level */
671 .SEND_RSVD_PAGE = sdio_write_data_rsvd_page,
672 .SEND_H2C_PKT = sdio_write_data_h2c,
674 /* Memory allocate */
675 .RTL_FREE = _halmac_mfree,
676 .RTL_MALLOC = _halmac_malloc,
677 .RTL_MEMCPY = _halmac_memcpy,
678 .RTL_MEMSET = _halmac_memset,
681 .RTL_DELAY_US = _halmac_udelay,
683 /* Process Synchronization */
684 .MUTEX_INIT = _halmac_mutex_init,
685 .MUTEX_DEINIT = _halmac_mutex_deinit,
686 .MUTEX_LOCK = _halmac_mutex_lock,
687 .MUTEX_UNLOCK = _halmac_mutex_unlock,
689 .MSG_PRINT = _halmac_msg_print,
690 .BUFF_PRINT = _halmac_buff_print,
691 .EVENT_INDICATION = _halmac_event_indication,
694 u8 rtw_halmac_read8(struct intf_hdl *pintfhdl, u32 addr)
700 /* WARNING: pintf_dev should not be null! */
701 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
702 api = HALMAC_GET_API(mac);
704 return api->halmac_reg_read_8(mac, addr);
707 u16 rtw_halmac_read16(struct intf_hdl *pintfhdl, u32 addr)
713 /* WARNING: pintf_dev should not be null! */
714 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
715 api = HALMAC_GET_API(mac);
717 return api->halmac_reg_read_16(mac, addr);
720 u32 rtw_halmac_read32(struct intf_hdl *pintfhdl, u32 addr)
726 /* WARNING: pintf_dev should not be null! */
727 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
728 api = HALMAC_GET_API(mac);
730 return api->halmac_reg_read_32(mac, addr);
733 void rtw_halmac_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem)
735 #if defined(CONFIG_SDIO_HCI)
740 RTW_ERR("pmem is NULL\n");
743 /* WARNING: pintf_dev should not be null! */
744 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
745 api = HALMAC_GET_API(mac);
747 api->halmac_reg_sdio_cmd53_read_n(mac, addr, cnt, pmem);
751 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
752 u8 rtw_halmac_iread8(struct intf_hdl *pintfhdl, u32 addr)
757 /* WARNING: pintf_dev should not be null! */
758 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
759 api = HALMAC_GET_API(mac);
761 /*return api->halmac_reg_read_indirect_8(mac, addr);*/
762 return api->halmac_reg_read_8(mac, addr);
765 u16 rtw_halmac_iread16(struct intf_hdl *pintfhdl, u32 addr)
771 /* WARNING: pintf_dev should not be null! */
772 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
773 api = HALMAC_GET_API(mac);
775 /*return api->halmac_reg_read_indirect_16(mac, addr);*/
776 return api->halmac_reg_read_16(mac, addr);
779 u32 rtw_halmac_iread32(struct intf_hdl *pintfhdl, u32 addr)
785 /* WARNING: pintf_dev should not be null! */
786 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
787 api = HALMAC_GET_API(mac);
789 return api->halmac_reg_read_indirect_32(mac, addr);
793 int rtw_halmac_write8(struct intf_hdl *pintfhdl, u32 addr, u8 value)
797 HALMAC_RET_STATUS status;
800 /* WARNING: pintf_dev should not be null! */
801 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
802 api = HALMAC_GET_API(mac);
804 status = api->halmac_reg_write_8(mac, addr, value);
806 if (status == HALMAC_RET_SUCCESS)
812 int rtw_halmac_write16(struct intf_hdl *pintfhdl, u32 addr, u16 value)
816 HALMAC_RET_STATUS status;
819 /* WARNING: pintf_dev should not be null! */
820 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
821 api = HALMAC_GET_API(mac);
823 status = api->halmac_reg_write_16(mac, addr, value);
825 if (status == HALMAC_RET_SUCCESS)
831 int rtw_halmac_write32(struct intf_hdl *pintfhdl, u32 addr, u32 value)
835 HALMAC_RET_STATUS status;
838 /* WARNING: pintf_dev should not be null! */
839 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
840 api = HALMAC_GET_API(mac);
842 status = api->halmac_reg_write_32(mac, addr, value);
844 if (status == HALMAC_RET_SUCCESS)
850 static int init_priv(struct halmacpriv *priv)
852 struct halmac_indicator *indicator;
856 size = sizeof(*priv);
857 _rtw_memset(priv, 0, size);
859 count = HALMAC_FEATURE_ALL + 1;
860 size = sizeof(*indicator) * count;
861 indicator = (struct halmac_indicator *)rtw_zmalloc(size);
864 priv->indicator = indicator;
869 static void deinit_priv(struct halmacpriv *priv)
871 struct halmac_indicator *indicator;
874 indicator = priv->indicator;
875 priv->indicator = NULL;
879 count = HALMAC_FEATURE_ALL + 1;
880 #ifdef CONFIG_RTW_DEBUG
882 struct submit_ctx *sctx;
885 for (i = 0; i < count; i++) {
886 if (!indicator[i].sctx)
889 RTW_INFO("%s: <WARN> %s id(%d) sctx still exist!!\n",
890 __FUNCTION__, RTW_HALMAC_FEATURE_NAME[i], i);
891 sctx = indicator[i].sctx;
892 indicator[i].sctx = NULL;
893 rtw_mfree((u8 *)sctx, sizeof(*sctx));
896 #endif /* !CONFIG_RTW_DEBUG */
897 size = sizeof(*indicator) * count;
898 rtw_mfree((u8 *)indicator, size);
902 void rtw_dump_halmac_info(void *sel)
904 HALMAC_RET_STATUS status;
905 HALMAC_VER halmac_version;
907 status = halmac_get_version(&halmac_version);
908 if (status != HALMAC_RET_SUCCESS)
911 RTW_PRINT_SEL(sel, "HALMAC VER -%x.%x.%x\n", halmac_version.major_ver, halmac_version.prototype_ver, halmac_version.minor_ver);
914 int rtw_halmac_init_adapter(struct dvobj_priv *d, PHALMAC_PLATFORM_API pf_api)
916 PHALMAC_ADAPTER halmac;
918 HALMAC_INTERFACE intf;
919 HALMAC_RET_STATUS status;
923 halmac = dvobj_to_halmac(d);
929 err = init_priv(&d->hmpriv);
933 #ifdef CONFIG_SDIO_HCI
934 intf = HALMAC_INTERFACE_SDIO;
935 #elif defined(CONFIG_USB_HCI)
936 intf = HALMAC_INTERFACE_USB;
937 #elif defined(CONFIG_PCIE_HCI)
938 intf = HALMAC_INTERFACE_PCIE;
940 #warning "INTERFACE(CONFIG_XXX_HCI) not be defined!!"
941 intf = HALMAC_INTERFACE_UNDEFINE;
943 status = halmac_init_adapter(d, pf_api, intf, &halmac, &api);
944 if (HALMAC_RET_SUCCESS != status) {
945 RTW_INFO("%s: halmac_init_adapter fail!(status=%d)\n", __FUNCTION__, status);
950 dvobj_set_halmac(d, halmac);
954 rtw_halmac_deinit_adapter(d);
959 int rtw_halmac_deinit_adapter(struct dvobj_priv *d)
961 PHALMAC_ADAPTER halmac;
962 HALMAC_RET_STATUS status;
966 halmac = dvobj_to_halmac(d);
972 deinit_priv(&d->hmpriv);
974 status = halmac_deinit_adapter(halmac);
975 dvobj_set_halmac(d, NULL);
976 if (status != HALMAC_RET_SUCCESS) {
987 * Power on device hardware.
988 * [Notice!] If device's power state is on before,
989 * it would be power off first and turn on power again.
994 * -2 power state unchange
996 int rtw_halmac_poweron(struct dvobj_priv *d)
998 PHALMAC_ADAPTER halmac;
1000 HALMAC_RET_STATUS status;
1004 halmac = dvobj_to_halmac(d);
1008 api = HALMAC_GET_API(halmac);
1010 status = api->halmac_pre_init_system_cfg(halmac);
1011 if (status != HALMAC_RET_SUCCESS)
1014 #ifdef CONFIG_SDIO_HCI
1015 status = api->halmac_sdio_cmd53_4byte(halmac, 1);
1016 if (status != HALMAC_RET_SUCCESS)
1020 status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_ON);
1021 if (HALMAC_RET_PWR_UNCHANGE == status) {
1023 * Work around for warm reboot but device not power off,
1024 * but it would also fall into this case when auto power on is enabled.
1026 api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
1027 status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_ON);
1028 RTW_WARN("%s: Power state abnormal, try to recover...%s\n",
1029 __FUNCTION__, (HALMAC_RET_SUCCESS == status)?"OK":"FAIL!");
1031 if (HALMAC_RET_SUCCESS != status) {
1032 if (HALMAC_RET_PWR_UNCHANGE == status)
1037 status = api->halmac_init_system_cfg(halmac);
1038 if (status != HALMAC_RET_SUCCESS)
1048 * Power off device hardware.
1051 * 0 Power off success
1054 int rtw_halmac_poweroff(struct dvobj_priv *d)
1056 PHALMAC_ADAPTER halmac;
1058 HALMAC_RET_STATUS status;
1062 halmac = dvobj_to_halmac(d);
1066 api = HALMAC_GET_API(halmac);
1068 status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
1069 if ((HALMAC_RET_SUCCESS != status)
1070 && (HALMAC_RET_PWR_UNCHANGE != status))
1080 * When this function return, the register REG_RCR may be changed.
1082 int rtw_halmac_config_rx_info(struct dvobj_priv *d, HALMAC_DRV_INFO info)
1084 PHALMAC_ADAPTER halmac;
1086 HALMAC_RET_STATUS status;
1090 halmac = dvobj_to_halmac(d);
1091 api = HALMAC_GET_API(halmac);
1093 status = api->halmac_cfg_drv_info(halmac, info);
1094 if (status != HALMAC_RET_SUCCESS)
1102 #ifdef CONFIG_SUPPORT_TRX_SHARED
1103 static inline HALMAC_RX_FIFO_EXPANDING_MODE _trx_share_mode_drv2halmac(u8 trx_share_mode)
1105 if (0 == trx_share_mode)
1106 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
1107 else if (1 == trx_share_mode)
1108 return HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK;
1109 else if (2 == trx_share_mode)
1110 return HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK;
1111 else if (3 == trx_share_mode)
1112 return HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK;
1114 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
1116 static HALMAC_RX_FIFO_EXPANDING_MODE _rtw_get_trx_share_mode(_adapter *adapter)
1118 struct registry_priv *registry_par = &adapter->registrypriv;
1120 return _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
1122 void dump_trx_share_mode(void *sel, _adapter *adapter)
1124 struct registry_priv *registry_par = &adapter->registrypriv;
1125 u8 mode = _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
1127 if (HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK == mode)
1128 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_1");
1129 else if (HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK == mode)
1130 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_2");
1131 else if (HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK == mode)
1132 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_3");
1134 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "DISABLE");
1138 static u8 _get_drv_rsvd_page(HALMAC_DRV_RSVD_PG_NUM rsvd_page_number)
1140 if (HALMAC_RSVD_PG_NUM16 == rsvd_page_number)
1142 else if (HALMAC_RSVD_PG_NUM24 == rsvd_page_number)
1144 else if (HALMAC_RSVD_PG_NUM32 == rsvd_page_number)
1147 RTW_ERR("%s unknown HALMAC_RSVD_PG type :%d\n", __func__, rsvd_page_number);
1152 static HALMAC_TRX_MODE _choose_trx_mode(struct dvobj_priv *d)
1157 p = dvobj_get_primary_adapter(d);
1159 if (p->registrypriv.wifi_spec)
1160 return HALMAC_TRX_MODE_WMM;
1162 #ifdef CONFIG_SUPPORT_TRX_SHARED
1163 if (_rtw_get_trx_share_mode(p))
1164 return HALMAC_TRX_MODE_TRXSHARE;
1167 return HALMAC_TRX_MODE_NORMAL;
1170 static inline HALMAC_RF_TYPE _rf_type_drv2halmac(RT_RF_TYPE_DEF_E rf_drv)
1172 HALMAC_RF_TYPE rf_mac;
1177 rf_mac = HALMAC_RF_1T2R;
1180 rf_mac = HALMAC_RF_2T4R;
1183 rf_mac = HALMAC_RF_2T2R;
1186 rf_mac = HALMAC_RF_1T1R;
1189 rf_mac = HALMAC_RF_2T2R_GREEN;
1192 rf_mac = HALMAC_RF_2T3R;
1195 rf_mac = HALMAC_RF_3T3R;
1198 rf_mac = HALMAC_RF_3T4R;
1201 rf_mac = HALMAC_RF_4T4R;
1204 rf_mac = (HALMAC_RF_TYPE)rf_drv;
1211 static int _send_general_info(struct dvobj_priv *d)
1215 PHALMAC_ADAPTER halmac;
1217 HALMAC_GENERAL_INFO info;
1218 HALMAC_RET_STATUS status;
1222 adapter = dvobj_get_primary_adapter(d);
1223 hal = GET_HAL_DATA(adapter);
1224 halmac = dvobj_to_halmac(d);
1227 api = HALMAC_GET_API(halmac);
1229 _rtw_memset(&info, 0, sizeof(info));
1230 info.rfe_type = (u8)hal->rfe_type;
1231 rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, &val8);
1232 info.rf_type = _rf_type_drv2halmac(val8);
1234 status = api->halmac_send_general_info(halmac, &info);
1236 case HALMAC_RET_SUCCESS:
1238 case HALMAC_RET_NO_DLFW:
1239 RTW_WARN("%s: halmac_send_general_info() fail because fw not dl!\n",
1251 * Downlaod Firmware Flow
1254 * d pointer of struct dvobj_priv
1256 * fwsize firmware size
1257 * re_dl re-download firmware or not
1258 * 0: run in init hal flow, not re-download
1259 * 1: it is a stand alone operation, not in init hal flow
1265 static int download_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize, u8 re_dl)
1267 PHALMAC_ADAPTER mac;
1269 HALMAC_RET_STATUS status;
1272 HALMAC_FW_VERSION fw_vesion;
1275 mac = dvobj_to_halmac(d);
1276 api = HALMAC_GET_API(mac);
1277 hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
1279 if ((!fw) || (!fwsize))
1282 /* 1. Driver Stop Tx */
1285 /* 2. Driver Check Tx FIFO is empty */
1288 /* 3. Config MAX download size */
1289 #ifdef CONFIG_USB_HCI
1290 /* for USB do not exceed MAX_CMDBUF_SZ */
1291 api->halmac_cfg_max_dl_size(mac, 0x1000);
1292 #elif defined CONFIG_PCIE_HCI
1293 /* required a even length from u32 */
1294 api->halmac_cfg_max_dl_size(mac, (MAX_CMDBUF_SZ - TXDESC_OFFSET) & 0xFFFFFFFE);
1297 /* 4. Download Firmware */
1298 status = api->halmac_download_firmware(mac, fw, fwsize);
1299 if (HALMAC_RET_SUCCESS != status)
1302 /* 5. Driver resume TX if needed */
1306 HALMAC_TRX_MODE mode;
1308 /* 6. Init TRX Configuration */
1309 mode = _choose_trx_mode(d);
1310 status = api->halmac_init_trx_cfg(mac, mode);
1311 if (HALMAC_RET_SUCCESS != status)
1314 /* 7. Config RX Aggregation */
1315 err = rtw_halmac_rx_agg_switch(d, _TRUE);
1319 /* 8. Send General Info */
1320 err = _send_general_info(d);
1325 /* 9. Reset driver variables if needed */
1326 hal->LastHMEBoxNum = 0;
1328 /* 10. Get FW version */
1329 status = api->halmac_get_fw_version(mac, &fw_vesion);
1330 if (status == HALMAC_RET_SUCCESS) {
1331 hal->firmware_version = fw_vesion.version;
1332 hal->firmware_sub_version = fw_vesion.sub_version;
1338 static HALMAC_RET_STATUS init_mac_flow(struct dvobj_priv *d)
1341 PHALMAC_ADAPTER halmac;
1343 HALMAC_WLAN_ADDR hwa;
1344 HALMAC_TRX_MODE trx_mode;
1345 HALMAC_RET_STATUS status;
1349 HALMAC_DRV_RSVD_PG_NUM rsvd_page_number = HALMAC_RSVD_PG_NUM16;/*HALMAC_RSVD_PG_NUM24/HALMAC_RSVD_PG_NUM32*/
1351 p = dvobj_get_primary_adapter(d);
1352 hal = GET_HAL_DATA(p);
1353 halmac = dvobj_to_halmac(d);
1354 api = HALMAC_GET_API(halmac);
1356 #ifdef CONFIG_SUPPORT_TRX_SHARED
1357 status = api->halmac_cfg_rx_fifo_expanding_mode(halmac, _rtw_get_trx_share_mode(p));
1358 if (status != HALMAC_RET_SUCCESS)
1362 #ifdef CONFIG_PNO_SUPPORT
1363 rsvd_page_number = HALMAC_RSVD_PG_NUM32;
1365 status = api->halmac_cfg_drv_rsvd_pg_num(halmac, rsvd_page_number);
1366 if (status != HALMAC_RET_SUCCESS)
1368 hal->drv_rsvd_page_number = _get_drv_rsvd_page(rsvd_page_number);
1370 #ifdef CONFIG_USB_HCI
1371 status = api->halmac_set_bulkout_num(halmac, d->RtNumOutPipes);
1372 if (status != HALMAC_RET_SUCCESS)
1374 #endif /* CONFIG_USB_HCI */
1376 trx_mode = _choose_trx_mode(d);
1377 status = api->halmac_init_mac_cfg(halmac, trx_mode);
1378 if (status != HALMAC_RET_SUCCESS)
1381 err = rtw_halmac_rx_agg_switch(d, _TRUE);
1385 nettype = dvobj_to_regsty(d)->wireless_mode;
1386 if (is_supported_vht(nettype) == _TRUE)
1387 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_AC);
1388 else if (is_supported_ht(nettype) == _TRUE)
1389 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_N);
1390 else if (IsSupportedTxOFDM(nettype) == _TRUE)
1391 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_G);
1393 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_B);
1394 if (status != HALMAC_RET_SUCCESS)
1404 * 1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
1405 * 2. HAL_DATA_TYPE.rfe_type
1406 * already ready for use before calling this function.
1408 static int _halmac_init_hal(struct dvobj_priv *d, u8 *fw, u32 fwsize)
1411 PHALMAC_ADAPTER halmac;
1413 HALMAC_RET_STATUS status;
1416 int err, err_ret = -1;
1419 adapter = dvobj_get_primary_adapter(d);
1420 halmac = dvobj_to_halmac(d);
1423 api = HALMAC_GET_API(halmac);
1427 /* SKIP: halmac_init_adapter (Already done before) */
1429 /* halmac_pre_Init_system_cfg */
1430 /* halmac_mac_power_switch(on) */
1431 /* halmac_Init_system_cfg */
1432 ok = rtw_hal_power_on(adapter);
1440 err = download_fw(d, fw, fwsize, 0);
1447 status = init_mac_flow(d);
1448 if (status != HALMAC_RET_SUCCESS)
1451 /* halmac_send_general_info */
1452 if (_TRUE == fw_ok) {
1453 err = _send_general_info(d);
1458 /* Init Phy parameter-MAC */
1459 ok = rtw_hal_init_mac_register(adapter);
1463 /* StateMacInitialized */
1465 /* halmac_cfg_drv_info */
1466 err = rtw_halmac_config_rx_info(d, HALMAC_DRV_INFO_PHY_STATUS);
1470 /* halmac_set_hw_value(HALMAC_HW_EN_BB_RF) */
1472 ok = rtw_hal_init_phy(adapter);
1476 status = api->halmac_init_interface_cfg(halmac);
1477 if (status != HALMAC_RET_SUCCESS)
1480 /* SKIP: halmac_verify_platform_api */
1481 /* SKIP: halmac_h2c_lb */
1490 int rtw_halmac_init_hal(struct dvobj_priv *d)
1492 return _halmac_init_hal(d, NULL, 0);
1498 * 1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
1499 * 2. HAL_DATA_TYPE.rfe_type
1500 * already ready for use before calling this function.
1502 int rtw_halmac_init_hal_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
1504 return _halmac_init_hal(d, fw, fwsize);
1510 * 1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
1511 * 2. HAL_DATA_TYPE.rfe_type
1512 * already ready for use before calling this function.
1514 int rtw_halmac_init_hal_fw_file(struct dvobj_priv *d, u8 *fwpath)
1517 u32 fwmaxsize, size = 0;
1521 fwmaxsize = FIRMWARE_MAX_SIZE;
1522 fw = rtw_zmalloc(fwmaxsize);
1526 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
1532 err = _halmac_init_hal(d, fw, size);
1535 rtw_mfree(fw, fwmaxsize);
1541 int rtw_halmac_deinit_hal(struct dvobj_priv *d)
1544 PHALMAC_ADAPTER halmac;
1546 HALMAC_RET_STATUS status;
1550 adapter = dvobj_get_primary_adapter(d);
1551 halmac = dvobj_to_halmac(d);
1554 api = HALMAC_GET_API(halmac);
1556 status = api->halmac_deinit_interface_cfg(halmac);
1557 if (status != HALMAC_RET_SUCCESS)
1560 rtw_hal_power_off(adapter);
1567 int rtw_halmac_self_verify(struct dvobj_priv *d)
1569 PHALMAC_ADAPTER mac;
1571 HALMAC_RET_STATUS status;
1575 mac = dvobj_to_halmac(d);
1576 api = HALMAC_GET_API(mac);
1578 status = api->halmac_verify_platform_api(mac);
1579 if (status != HALMAC_RET_SUCCESS)
1582 status = api->halmac_h2c_lb(mac);
1583 if (status != HALMAC_RET_SUCCESS)
1591 int rtw_halmac_redl_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
1601 * -22 Invalid arguemnt
1603 int rtw_halmac_dlfw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
1606 HALMAC_RET_STATUS status;
1608 int err, err_ret = -1;
1614 adapter = dvobj_get_primary_adapter(d);
1616 /* re-download firmware */
1617 if (rtw_is_hw_init_completed(adapter))
1618 return download_fw(d, fw, fwsize, 1);
1620 /* Download firmware before hal init */
1621 /* Power on, download firmware and init mac */
1622 ok = rtw_hal_power_on(adapter);
1626 err = download_fw(d, fw, fwsize, 0);
1632 status = init_mac_flow(d);
1633 if (status != HALMAC_RET_SUCCESS)
1636 err = _send_general_info(d);
1646 int rtw_halmac_dlfw_from_file(struct dvobj_priv *d, u8 *fwpath)
1649 u32 fwmaxsize, size = 0;
1653 fwmaxsize = FIRMWARE_MAX_SIZE;
1654 fw = rtw_zmalloc(fwmaxsize);
1658 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
1660 err = rtw_halmac_dlfw(d, fw, size);
1664 rtw_mfree(fw, fwmaxsize);
1672 * Power on/off BB/RF domain.
1675 * enable _TRUE/_FALSE for power on/off
1681 int rtw_halmac_phy_power_switch(struct dvobj_priv *d, u8 enable)
1684 PHALMAC_ADAPTER halmac;
1686 HALMAC_RET_STATUS status;
1689 adapter = dvobj_get_primary_adapter(d);
1690 halmac = dvobj_to_halmac(d);
1693 api = HALMAC_GET_API(halmac);
1695 status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &enable);
1696 if (status != HALMAC_RET_SUCCESS)
1702 static u8 _is_fw_read_cmd_down(PADAPTER adapter, u8 msgbox_num)
1704 u8 read_down = _FALSE;
1705 int retry_cnts = 100;
1708 /* RTW_INFO("_is_fw_read_cmd_down, reg_1cc(%x), msg_box(%d)...\n", rtw_read8(adapter, REG_HMETFR), msgbox_num); */
1711 valid = rtw_read8(adapter, REG_HMETFR) & BIT(msgbox_num);
1716 } while ((!read_down) && (retry_cnts--));
1721 int rtw_halmac_send_h2c(struct dvobj_priv *d, u8 *h2c)
1723 PADAPTER adapter = dvobj_get_primary_adapter(d);
1724 PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
1726 u32 msgbox_addr = 0;
1727 u32 msgbox_ex_addr = 0;
1732 if (adapter->bFWReady == _FALSE) {
1733 RTW_INFO("%s: return H2C cmd because fw is not ready\n", __FUNCTION__);
1738 RTW_INFO("%s: pbuf is NULL\n", __FUNCTION__);
1742 if (rtw_is_surprise_removed(adapter)) {
1743 RTW_INFO("%s: surprise removed\n", __FUNCTION__);
1747 _enter_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
1749 /* pay attention to if race condition happened in H2C cmd setting */
1750 h2c_box_num = hal->LastHMEBoxNum;
1752 if (!_is_fw_read_cmd_down(adapter, h2c_box_num)) {
1753 RTW_INFO(" fw read cmd failed...\n");
1757 /* Write Ext command(byte 4 -7) */
1758 msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
1759 _rtw_memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
1760 h2c_cmd_ex = le32_to_cpu(h2c_cmd_ex);
1761 rtw_write32(adapter, msgbox_ex_addr, h2c_cmd_ex);
1763 /* Write command (byte 0 -3 ) */
1764 msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
1765 _rtw_memcpy((u8 *)(&h2c_cmd), h2c, 4);
1766 h2c_cmd = le32_to_cpu(h2c_cmd);
1767 rtw_write32(adapter, msgbox_addr, h2c_cmd);
1769 /* update last msg box number */
1770 hal->LastHMEBoxNum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
1773 #ifdef DBG_H2C_CONTENT
1774 RTW_INFO_DUMP("[H2C] - ", h2c, RTW_HALMAC_H2C_MAX_SIZE);
1777 _exit_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
1781 int rtw_halmac_c2h_handle(struct dvobj_priv *d, u8 *c2h, u32 size)
1783 PHALMAC_ADAPTER mac;
1785 HALMAC_RET_STATUS status;
1788 mac = dvobj_to_halmac(d);
1789 api = HALMAC_GET_API(mac);
1791 status = api->halmac_get_c2h_info(mac, c2h, size);
1792 if (HALMAC_RET_SUCCESS != status)
1798 int rtw_halmac_get_available_efuse_size(struct dvobj_priv *d, u32 *size)
1800 PHALMAC_ADAPTER mac;
1802 HALMAC_RET_STATUS status;
1806 mac = dvobj_to_halmac(d);
1807 api = HALMAC_GET_API(mac);
1809 status = api->halmac_get_efuse_available_size(mac, &val);
1810 if (HALMAC_RET_SUCCESS != status)
1817 int rtw_halmac_get_physical_efuse_size(struct dvobj_priv *d, u32 *size)
1819 PHALMAC_ADAPTER mac;
1821 HALMAC_RET_STATUS status;
1825 mac = dvobj_to_halmac(d);
1826 api = HALMAC_GET_API(mac);
1828 status = api->halmac_get_efuse_size(mac, &val);
1829 if (HALMAC_RET_SUCCESS != status)
1836 int rtw_halmac_read_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
1838 PHALMAC_ADAPTER mac;
1840 HALMAC_RET_STATUS status;
1841 HALMAC_FEATURE_ID id;
1845 mac = dvobj_to_halmac(d);
1846 api = HALMAC_GET_API(mac);
1847 id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
1849 ret = init_halmac_event(d, id, map, size);
1853 status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_AUTO);
1854 if (HALMAC_RET_SUCCESS != status) {
1855 free_halmac_event(d, id);
1859 ret = wait_halmac_event(d, id);
1866 int rtw_halmac_read_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
1868 PHALMAC_ADAPTER mac;
1870 HALMAC_RET_STATUS status;
1875 mac = dvobj_to_halmac(d);
1876 api = HALMAC_GET_API(mac);
1878 for (i = 0; i < cnt; i++) {
1879 status = api->halmac_read_efuse(mac, offset + i, &v);
1880 if (HALMAC_RET_SUCCESS != status)
1888 int rtw_halmac_write_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
1890 PHALMAC_ADAPTER mac;
1892 HALMAC_RET_STATUS status;
1896 mac = dvobj_to_halmac(d);
1897 api = HALMAC_GET_API(mac);
1899 for (i = 0; i < cnt; i++) {
1900 status = api->halmac_write_efuse(mac, offset + i, data[i]);
1901 if (HALMAC_RET_SUCCESS != status)
1908 int rtw_halmac_get_logical_efuse_size(struct dvobj_priv *d, u32 *size)
1910 PHALMAC_ADAPTER mac;
1912 HALMAC_RET_STATUS status;
1916 mac = dvobj_to_halmac(d);
1917 api = HALMAC_GET_API(mac);
1919 status = api->halmac_get_logical_efuse_size(mac, &val);
1920 if (HALMAC_RET_SUCCESS != status)
1927 int rtw_halmac_read_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
1929 PHALMAC_ADAPTER mac;
1931 HALMAC_RET_STATUS status;
1932 HALMAC_FEATURE_ID id;
1936 mac = dvobj_to_halmac(d);
1937 api = HALMAC_GET_API(mac);
1938 id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
1940 ret = init_halmac_event(d, id, map, size);
1944 status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_DRV);
1945 if (HALMAC_RET_SUCCESS != status) {
1946 free_halmac_event(d, id);
1950 ret = wait_halmac_event(d, id);
1957 int rtw_halmac_write_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
1959 PHALMAC_ADAPTER mac;
1961 HALMAC_PG_EFUSE_INFO pginfo;
1962 HALMAC_RET_STATUS status;
1965 mac = dvobj_to_halmac(d);
1966 api = HALMAC_GET_API(mac);
1968 pginfo.pEfuse_map = map;
1969 pginfo.efuse_map_size = size;
1970 pginfo.pEfuse_mask = maskmap;
1971 pginfo.efuse_mask_size = masksize;
1973 status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
1974 if (HALMAC_RET_SUCCESS != status)
1980 int rtw_halmac_read_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
1982 PHALMAC_ADAPTER mac;
1984 HALMAC_RET_STATUS status;
1989 mac = dvobj_to_halmac(d);
1990 api = HALMAC_GET_API(mac);
1992 for (i = 0; i < cnt; i++) {
1993 status = api->halmac_read_logical_efuse(mac, offset + i, &v);
1994 if (HALMAC_RET_SUCCESS != status)
2002 int rtw_halmac_write_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
2004 PHALMAC_ADAPTER mac;
2006 HALMAC_RET_STATUS status;
2010 mac = dvobj_to_halmac(d);
2011 api = HALMAC_GET_API(mac);
2013 for (i = 0; i < cnt; i++) {
2014 status = api->halmac_write_logical_efuse(mac, offset + i, data[i]);
2015 if (HALMAC_RET_SUCCESS != status)
2022 int rtw_halmac_write_bt_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
2024 PHALMAC_ADAPTER mac;
2026 HALMAC_RET_STATUS status;
2030 mac = dvobj_to_halmac(d);
2031 api = HALMAC_GET_API(mac);
2033 for (i = 0; i < cnt; i++) {
2034 status = api->halmac_write_efuse_bt(mac, offset + i, data[i], bank);
2035 if (HALMAC_RET_SUCCESS != status) {
2036 printk("%s: halmac_write_efuse_bt status = %d\n", __FUNCTION__, status);
2040 printk("%s: halmac_write_efuse_bt status = HALMAC_RET_SUCCESS %d\n", __FUNCTION__, status);
2045 int rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
2047 PHALMAC_ADAPTER mac;
2049 HALMAC_RET_STATUS status;
2050 HALMAC_FEATURE_ID id;
2054 mac = dvobj_to_halmac(d);
2055 api = HALMAC_GET_API(mac);
2057 status = api->halmac_dump_efuse_map_bt(mac, bank, size, map);
2058 if (HALMAC_RET_SUCCESS != status) {
2059 printk("%s: halmac_dump_efuse_map_bt fail!\n", __FUNCTION__);
2063 printk("%s: OK!\n", __FUNCTION__);
2068 static inline u8 _hw_port_drv2halmac(enum _hw_port hwport)
2097 int rtw_halmac_set_mac_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2099 PHALMAC_ADAPTER halmac;
2102 HALMAC_WLAN_ADDR hwa;
2103 HALMAC_RET_STATUS status;
2107 halmac = dvobj_to_halmac(d);
2108 api = HALMAC_GET_API(halmac);
2110 port = _hw_port_drv2halmac(hwport);
2111 _rtw_memset(&hwa, 0, sizeof(hwa));
2112 _rtw_memcpy(hwa.Address, addr, 6);
2114 status = api->halmac_cfg_mac_addr(halmac, port, &hwa);
2115 if (status != HALMAC_RET_SUCCESS)
2123 int rtw_halmac_set_bssid(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2125 PHALMAC_ADAPTER halmac;
2128 HALMAC_WLAN_ADDR hwa;
2129 HALMAC_RET_STATUS status;
2132 halmac = dvobj_to_halmac(d);
2133 api = HALMAC_GET_API(halmac);
2134 port = _hw_port_drv2halmac(hwport);
2136 _rtw_memset(&hwa, 0, sizeof(HALMAC_WLAN_ADDR));
2137 _rtw_memcpy(hwa.Address, addr, 6);
2138 status = api->halmac_cfg_bssid(halmac, port, &hwa);
2139 if (status != HALMAC_RET_SUCCESS)
2147 int rtw_halmac_set_bandwidth(struct dvobj_priv *d, u8 channel, u8 pri_ch_idx, u8 bw)
2149 PHALMAC_ADAPTER mac;
2151 HALMAC_RET_STATUS status;
2154 mac = dvobj_to_halmac(d);
2155 api = HALMAC_GET_API(mac);
2157 status = api->halmac_cfg_ch_bw(mac, channel, pri_ch_idx, bw);
2158 if (HALMAC_RET_SUCCESS != status)
2164 int rtw_halmac_get_hw_value(struct dvobj_priv *d, HALMAC_HW_ID hw_id, VOID *pvalue)
2166 PHALMAC_ADAPTER mac;
2168 HALMAC_RET_STATUS status;
2171 mac = dvobj_to_halmac(d);
2172 api = HALMAC_GET_API(mac);
2174 status = api->halmac_get_hw_value(mac, hw_id, pvalue);
2175 if (HALMAC_RET_SUCCESS != status)
2181 static HAL_FIFO_SEL _fifo_sel_drv2halmac(u8 fifo_sel)
2184 return HAL_FIFO_SEL_TX;
2185 else if (1 == fifo_sel)
2186 return HAL_FIFO_SEL_RX;
2187 else if (2 == fifo_sel)
2188 return HAL_FIFO_SEL_RSVD_PAGE;
2189 else if (3 == fifo_sel)
2190 return HAL_FIFO_SEL_REPORT;
2191 else if (4 == fifo_sel)
2192 return HAL_FIFO_SEL_LLT;
2194 return HAL_FIFO_SEL_RSVD_PAGE;
2197 #define CONFIG_HALMAC_FIFO_DUMP
2198 int rtw_halmac_dump_fifo(struct dvobj_priv *d, u8 fifo_sel, u32 addr, u32 size, u8 *buffer)
2200 PHALMAC_ADAPTER mac;
2202 HALMAC_RET_STATUS status;
2203 u8 *pfifo_map = NULL;
2205 s8 ret = 0;/* 0:success, -1:error */
2206 u8 mem_created = _FALSE;
2208 HAL_FIFO_SEL halmac_fifo_sel;
2210 mac = dvobj_to_halmac(d);
2211 api = HALMAC_GET_API(mac);
2213 if ((size != 0) && (buffer == NULL))
2216 halmac_fifo_sel = _fifo_sel_drv2halmac(fifo_sel);
2218 if ((size) && (buffer)) {
2222 fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
2225 pfifo_map = rtw_zvmalloc(fifo_size);
2226 if (pfifo_map == NULL)
2228 mem_created = _TRUE;
2231 status = api->halmac_dump_fifo(mac, halmac_fifo_sel, addr, fifo_size, pfifo_map);
2232 if (HALMAC_RET_SUCCESS != status) {
2237 #ifdef CONFIG_HALMAC_FIFO_DUMP
2239 static const char * const fifo_sel_str[] = {
2240 "TX", "RX", "RSVD_PAGE", "REPORT", "LLT"
2243 RTW_INFO("%s FIFO DUMP [start_addr:0x%04x , size:%d]\n", fifo_sel_str[halmac_fifo_sel], addr, fifo_size);
2244 RTW_INFO_DUMP("\n", pfifo_map, fifo_size);
2245 RTW_INFO(" ==================================================\n");
2250 if (mem_created && pfifo_map)
2251 rtw_vmfree(pfifo_map, fifo_size);
2256 int rtw_halmac_rx_agg_switch(struct dvobj_priv *d, u8 enable)
2260 PHALMAC_ADAPTER halmac;
2262 HALMAC_RXAGG_CFG rxaggcfg;
2263 HALMAC_RET_STATUS status;
2267 adapter = dvobj_get_primary_adapter(d);
2268 hal = GET_HAL_DATA(adapter);
2269 halmac = dvobj_to_halmac(d);
2270 api = HALMAC_GET_API(halmac);
2271 _rtw_memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
2273 if (_TRUE == enable) {
2274 #ifdef CONFIG_SDIO_HCI
2275 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
2276 rxaggcfg.threshold.drv_define = 0;
2277 #elif defined(CONFIG_USB_HCI) && defined(CONFIG_USB_RX_AGGREGATION)
2278 switch (hal->rxagg_mode) {
2279 case RX_AGG_DISABLE:
2280 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
2284 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
2285 if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
2286 rxaggcfg.threshold.drv_define = 1;
2287 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
2288 rxaggcfg.threshold.size = hal->rxagg_dma_size;
2294 rxaggcfg.mode = HALMAC_RX_AGG_MODE_USB;
2295 if (hal->rxagg_usb_size || hal->rxagg_usb_timeout) {
2296 rxaggcfg.threshold.drv_define = 1;
2297 rxaggcfg.threshold.timeout = hal->rxagg_usb_timeout;
2298 rxaggcfg.threshold.size = hal->rxagg_usb_size;
2302 #endif /* CONFIG_USB_HCI */
2304 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
2306 status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
2307 if (status != HALMAC_RET_SUCCESS)
2317 * Get RX driver info size. RX driver info is a small memory space between
2318 * scriptor and RX payload.
2320 * +-------------------------+
2322 * | usually 24 bytes |
2323 * +-------------------------+
2324 * | RX driver info |
2325 * | depends on driver cfg |
2326 * +-------------------------+
2329 * +-------------------------+
2332 * d pointer to struct dvobj_priv of driver
2333 * sz rx driver info size in bytes.
2339 int rtw_halmac_get_drv_info_sz(struct dvobj_priv *d, u8 *sz)
2341 HALMAC_RET_STATUS status;
2342 PHALMAC_ADAPTER halmac = dvobj_to_halmac(d);
2343 PHALMAC_API api = HALMAC_GET_API(halmac);
2346 status = api->halmac_get_hw_value(halmac, HALMAC_HW_DRV_INFO_SIZE, &dw);
2347 if (status != HALMAC_RET_SUCCESS)
2353 int rtw_halmac_get_rsvd_drv_pg_bndy(struct dvobj_priv *dvobj, u16 *drv_pg)
2355 HALMAC_RET_STATUS status;
2356 PHALMAC_ADAPTER halmac = dvobj_to_halmac(dvobj);
2357 PHALMAC_API api = HALMAC_GET_API(halmac);
2359 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RSVD_PG_BNDY, drv_pg);
2360 if (status != HALMAC_RET_SUCCESS)
2366 int rtw_halmac_download_rsvd_page(struct dvobj_priv *dvobj, u8 pg_offset, u8 *pbuf, u32 size)
2368 HALMAC_RET_STATUS status = HALMAC_RET_SUCCESS;
2369 PHALMAC_ADAPTER halmac = dvobj_to_halmac(dvobj);
2370 PHALMAC_API api = HALMAC_GET_API(halmac);
2372 status = api->halmac_dl_drv_rsvd_page(halmac, pg_offset, pbuf, size);
2373 if (status != HALMAC_RET_SUCCESS)
2382 * Fill following spec info from HALMAC API:
2389 int rtw_halmac_fill_hal_spec(struct dvobj_priv *dvobj, struct hal_spec_t *spec)
2391 HALMAC_RET_STATUS status;
2392 PHALMAC_ADAPTER halmac;
2394 u8 cam = 0; /* Security Cam Entry Number */
2397 halmac = dvobj_to_halmac(dvobj);
2398 api = HALMAC_GET_API(halmac);
2400 /* Prepare data from HALMAC */
2401 status = api->halmac_get_hw_value(halmac, HALMAC_HW_CAM_ENTRY_NUM, &cam);
2402 if (status != HALMAC_RET_SUCCESS)
2405 /* Fill data to hal_spec_t */
2406 spec->sec_cam_ent_num = cam;
2411 #ifdef CONFIG_SDIO_HCI
2415 * Update queue allocated page number to driver
2418 * d pointer to struct dvobj_priv of driver
2421 * 0 Success, "page" is valid.
2422 * others Fail, "page" is invalid.
2424 int rtw_halmac_query_tx_page_num(struct dvobj_priv *d)
2427 struct halmacpriv *hmpriv;
2428 PHALMAC_ADAPTER halmac;
2430 HALMAC_RQPN_MAP rqpn;
2431 HALMAC_DMA_MAPPING dmaqueue;
2432 HALMAC_TXFF_ALLOCATION fifosize;
2433 HALMAC_RET_STATUS status;
2437 adapter = dvobj_get_primary_adapter(d);
2438 hmpriv = &d->hmpriv;
2439 halmac = dvobj_to_halmac(d);
2440 api = HALMAC_GET_API(halmac);
2441 _rtw_memset((void *)&rqpn, 0, sizeof(rqpn));
2442 _rtw_memset((void *)&fifosize, 0, sizeof(fifosize));
2444 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RQPN_MAPPING, &rqpn);
2445 if (status != HALMAC_RET_SUCCESS)
2447 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFF_ALLOCATION, &fifosize);
2448 if (status != HALMAC_RET_SUCCESS)
2451 for (i = 0; i < HW_QUEUE_ENTRY; i++) {
2452 hmpriv->txpage[i] = 0;
2454 /* Driver index mapping to HALMAC DMA queue */
2455 dmaqueue = HALMAC_DMA_MAPPING_UNDEFINE;
2458 dmaqueue = rqpn.dma_map_vo;
2461 dmaqueue = rqpn.dma_map_vi;
2464 dmaqueue = rqpn.dma_map_be;
2467 dmaqueue = rqpn.dma_map_bk;
2470 dmaqueue = rqpn.dma_map_mg;
2472 case HIGH_QUEUE_INX:
2473 dmaqueue = rqpn.dma_map_hi;
2476 case TXCMD_QUEUE_INX:
2478 hmpriv->txpage[i] = 0xFFFF;
2483 case HALMAC_DMA_MAPPING_EXTRA:
2484 hmpriv->txpage[i] = fifosize.extra_queue_pg_num;
2486 case HALMAC_DMA_MAPPING_LOW:
2487 hmpriv->txpage[i] = fifosize.low_queue_pg_num;
2489 case HALMAC_DMA_MAPPING_NORMAL:
2490 hmpriv->txpage[i] = fifosize.normal_queue_pg_num;
2492 case HALMAC_DMA_MAPPING_HIGH:
2493 hmpriv->txpage[i] = fifosize.high_queue_pg_num;
2495 case HALMAC_DMA_MAPPING_UNDEFINE:
2498 hmpriv->txpage[i] += fifosize.pub_queue_pg_num;
2506 * Get specific queue allocated page number
2509 * d pointer to struct dvobj_priv of driver
2510 * queue target queue to query, VO/VI/BE/BK/.../TXCMD_QUEUE_INX
2511 * page return allocated page number
2514 * 0 Success, "page" is valid.
2515 * others Fail, "page" is invalid.
2517 int rtw_halmac_get_tx_queue_page_num(struct dvobj_priv *d, u8 queue, u32 *page)
2520 if (queue < HW_QUEUE_ENTRY)
2521 *page = d->hmpriv.txpage[queue];
2528 * address for SDIO command
2530 u32 rtw_halmac_sdio_get_tx_addr(struct dvobj_priv *d, u8 *desc, u32 size)
2532 PHALMAC_ADAPTER mac;
2534 HALMAC_RET_STATUS status;
2538 mac = dvobj_to_halmac(d);
2539 api = HALMAC_GET_API(mac);
2541 status = api->halmac_get_sdio_tx_addr(mac, desc, size, &addr);
2542 if (HALMAC_RET_SUCCESS != status)
2548 int rtw_halmac_sdio_tx_allowed(struct dvobj_priv *d, u8 *buf, u32 size)
2550 PHALMAC_ADAPTER mac;
2552 HALMAC_RET_STATUS status;
2555 mac = dvobj_to_halmac(d);
2556 api = HALMAC_GET_API(mac);
2558 status = api->halmac_tx_allowed_sdio(mac, buf, size);
2559 if (HALMAC_RET_SUCCESS != status)
2565 u32 rtw_halmac_sdio_get_rx_addr(struct dvobj_priv *d, u8 *seq)
2569 #define RTW_SDIO_ADDR_RX_RX0FF_PRFIX 0x0E000
2570 #define RTW_SDIO_ADDR_RX_RX0FF_GEN(a) (RTW_SDIO_ADDR_RX_RX0FF_PRFIX|(a&0x3))
2574 return RTW_SDIO_ADDR_RX_RX0FF_GEN(id);
2576 #endif /* CONFIG_SDIO_HCI */
2578 #ifdef CONFIG_USB_HCI
2579 u8 rtw_halmac_usb_get_bulkout_id(struct dvobj_priv *d, u8 *buf, u32 size)
2581 PHALMAC_ADAPTER mac;
2583 HALMAC_RET_STATUS status;
2587 mac = dvobj_to_halmac(d);
2588 api = HALMAC_GET_API(mac);
2590 status = api->halmac_get_usb_bulkout_id(mac, buf, size, &bulkout_id);
2591 if (HALMAC_RET_SUCCESS != status)
2597 static inline HALMAC_USB_MODE _usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)
2599 HALMAC_USB_MODE halmac_usb_mode = HALMAC_USB_MODE_U2;
2602 case RTW_USB_SPEED_2:
2603 halmac_usb_mode = HALMAC_USB_MODE_U2;
2605 case RTW_USB_SPEED_3:
2606 halmac_usb_mode = HALMAC_USB_MODE_U3;
2609 halmac_usb_mode = HALMAC_USB_MODE_U2;
2613 return halmac_usb_mode;
2616 u8 rtw_halmac_switch_usb_mode(struct dvobj_priv *d, enum RTW_USB_SPEED usb_mode)
2618 PHALMAC_ADAPTER mac;
2620 HALMAC_RET_STATUS status;
2622 HALMAC_USB_MODE halmac_usb_mode;
2624 adapter = dvobj_get_primary_adapter(d);
2625 mac = dvobj_to_halmac(d);
2626 api = HALMAC_GET_API(mac);
2627 halmac_usb_mode = _usb_mode_drv2halmac(usb_mode);
2628 status = api->halmac_set_hw_value(mac, HALMAC_HW_USB_MODE, (void *)&halmac_usb_mode);
2630 if (HALMAC_RET_SUCCESS != status)
2635 #endif /* CONFIG_USB_HCI */