1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 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 *******************************************************************************/
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 #include <rtl8723b_hal.h>
21 /* define SDIO_DEBUG_IO 1 */
26 /* The following mapping is for SDIO host local register space. */
28 /* Creadted by Roger, 2011.01.31. */
30 static void HalSdioGetCmdAddr8723BSdio(
31 struct adapter *padapter,
38 case SDIO_LOCAL_DEVICE_ID:
39 *pCmdAddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (Addr & SDIO_LOCAL_MSK));
42 case WLAN_IOREG_DEVICE_ID:
43 *pCmdAddr = ((WLAN_IOREG_DEVICE_ID << 13) | (Addr & WLAN_IOREG_MSK));
46 case WLAN_TX_HIQ_DEVICE_ID:
47 *pCmdAddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
50 case WLAN_TX_MIQ_DEVICE_ID:
51 *pCmdAddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
54 case WLAN_TX_LOQ_DEVICE_ID:
55 *pCmdAddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
58 case WLAN_RX0FF_DEVICE_ID:
59 *pCmdAddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (Addr & WLAN_RX0FF_MSK));
67 static u8 get_deviceid(u32 addr)
73 pseudoId = (u16)(addr >> 16);
76 devideId = SDIO_LOCAL_DEVICE_ID;
80 devideId = WLAN_IOREG_DEVICE_ID;
84 /* devideId = SDIO_FIRMWARE_FIFO; */
88 devideId = WLAN_TX_HIQ_DEVICE_ID;
92 devideId = WLAN_TX_MIQ_DEVICE_ID;
96 devideId = WLAN_TX_LOQ_DEVICE_ID;
100 devideId = WLAN_RX0FF_DEVICE_ID;
104 /* devideId = (u8)((addr >> 13) & 0xF); */
105 devideId = WLAN_IOREG_DEVICE_ID;
114 *HalSdioGetCmdAddr8723BSdio()
116 static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset)
123 deviceId = get_deviceid(addr);
127 case SDIO_LOCAL_DEVICE_ID:
128 offset = addr & SDIO_LOCAL_MSK;
131 case WLAN_TX_HIQ_DEVICE_ID:
132 case WLAN_TX_MIQ_DEVICE_ID:
133 case WLAN_TX_LOQ_DEVICE_ID:
134 offset = addr & WLAN_FIFO_MSK;
137 case WLAN_RX0FF_DEVICE_ID:
138 offset = addr & WLAN_RX0FF_MSK;
141 case WLAN_IOREG_DEVICE_ID:
143 deviceId = WLAN_IOREG_DEVICE_ID;
144 offset = addr & WLAN_IOREG_MSK;
147 ftaddr = (deviceId << 13) | offset;
150 *pdeviceId = deviceId;
157 static u8 sdio_read8(struct intf_hdl *pintfhdl, u32 addr)
162 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
163 val = sd_read8(pintfhdl, ftaddr, NULL);
167 static u16 sdio_read16(struct intf_hdl *pintfhdl, u32 addr)
173 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
174 sd_cmd52_read(pintfhdl, ftaddr, 2, (u8 *)&le_tmp);
175 val = le16_to_cpu(le_tmp);
179 static u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
181 struct adapter *padapter;
191 padapter = pintfhdl->padapter;
192 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
194 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
196 ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
197 (false == bMacPwrCtrlOn) ||
198 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
200 err = sd_cmd52_read(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
204 val = le32_to_cpu(le_tmp);
209 DBG_8192C(KERN_ERR "%s: Mac Power off, Read FAIL(%d)! addr = 0x%x\n", __func__, err, addr);
210 return SDIO_ERR_VAL32;
214 /* 4 bytes alignment */
215 shift = ftaddr & 0x3;
217 val = sd_read32(pintfhdl, ftaddr, NULL);
221 ptmpbuf = (u8 *)rtw_malloc(8);
222 if (NULL == ptmpbuf) {
223 DBG_8192C(KERN_ERR "%s: Allocate memory FAIL!(size =8) addr = 0x%x\n", __func__, addr);
224 return SDIO_ERR_VAL32;
228 sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
229 memcpy(&le_tmp, ptmpbuf+shift, 4);
230 val = le32_to_cpu(le_tmp);
237 static s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
239 struct adapter *padapter;
247 padapter = pintfhdl->padapter;
250 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
252 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
254 ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
255 (false == bMacPwrCtrlOn) ||
256 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
258 err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
262 /* 4 bytes alignment */
263 shift = ftaddr & 0x3;
265 err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
272 ptmpbuf = rtw_malloc(n);
276 err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
278 memcpy(pbuf, ptmpbuf+shift, cnt);
284 static s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
289 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
290 sd_write8(pintfhdl, ftaddr, val, &err);
295 static s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
301 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
302 le_tmp = cpu_to_le16(val);
303 err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8 *)&le_tmp);
308 static s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
310 struct adapter *padapter;
319 padapter = pintfhdl->padapter;
322 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
324 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
326 ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
328 (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
330 le_tmp = cpu_to_le32(val);
331 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
335 /* 4 bytes alignment */
336 shift = ftaddr & 0x3;
338 sd_write32(pintfhdl, ftaddr, val, &err);
340 le_tmp = cpu_to_le32(val);
341 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
346 static s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
348 struct adapter *padapter;
356 padapter = pintfhdl->padapter;
359 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
361 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
363 ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
364 (false == bMacPwrCtrlOn) ||
365 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
367 err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
371 shift = ftaddr & 0x3;
373 err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
380 ptmpbuf = rtw_malloc(n);
383 err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
388 memcpy(ptmpbuf+shift, pbuf, cnt);
389 err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
395 static u8 sdio_f0_read8(struct intf_hdl *pintfhdl, u32 addr)
397 return sd_f0_read8(pintfhdl, addr, NULL);
400 static void sdio_read_mem(
401 struct intf_hdl *pintfhdl,
409 err = sdio_readN(pintfhdl, addr, cnt, rmem);
410 /* TODO: Report error is err not zero */
413 static void sdio_write_mem(
414 struct intf_hdl *pintfhdl,
420 sdio_writeN(pintfhdl, addr, cnt, wmem);
426 *Round read size to block size,
427 *and make sure data transfer will be done in one command.
430 *pintfhdl a pointer of intf_hdl
433 *rmem address to put data
439 static u32 sdio_read_port(
440 struct intf_hdl *pintfhdl,
446 struct adapter *padapter;
448 struct hal_com_data *phal;
450 #ifdef SDIO_DYNAMIC_ALLOC_MEM
456 padapter = pintfhdl->padapter;
457 psdio = &adapter_to_dvobj(padapter)->intf_data;
458 phal = GET_HAL_DATA(padapter);
460 HalSdioGetCmdAddr8723BSdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
463 if (cnt > psdio->block_transfer_len)
464 cnt = _RND(cnt, psdio->block_transfer_len);
465 /* cnt = sdio_align_size(cnt); */
468 #ifdef SDIO_DYNAMIC_ALLOC_MEM
470 mem = rtw_malloc(cnt);
472 DBG_8192C(KERN_WARNING "%s: allocate memory %d bytes fail!\n", __func__, cnt);
477 /* in this case, caller should gurante the buffer is big enough */
478 /* to receive data after alignment */
482 err = _sd_read(pintfhdl, addr, cnt, mem);
484 #ifdef SDIO_DYNAMIC_ALLOC_MEM
485 if ((oldcnt != cnt) && (oldmem)) {
486 memcpy(oldmem, mem, oldcnt);
499 *Align write size block size,
500 *and make sure data could be written in one command.
503 *pintfhdl a pointer of intf_hdl
506 *wmem data pointer to write
512 static u32 sdio_write_port(
513 struct intf_hdl *pintfhdl,
519 struct adapter *padapter;
522 struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
524 padapter = pintfhdl->padapter;
525 psdio = &adapter_to_dvobj(padapter)->intf_data;
527 if (padapter->hw_init_completed == false) {
528 DBG_871X("%s [addr = 0x%x cnt =%d] padapter->hw_init_completed == false\n", __func__, addr, cnt);
533 HalSdioGetCmdAddr8723BSdio(padapter, addr, cnt >> 2, &addr);
535 if (cnt > psdio->block_transfer_len)
536 cnt = _RND(cnt, psdio->block_transfer_len);
537 /* cnt = sdio_align_size(cnt); */
539 err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
543 err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS
551 void sdio_set_intf_ops(struct adapter *padapter, struct _io_ops *pops)
553 pops->_read8 = &sdio_read8;
554 pops->_read16 = &sdio_read16;
555 pops->_read32 = &sdio_read32;
556 pops->_read_mem = &sdio_read_mem;
557 pops->_read_port = &sdio_read_port;
559 pops->_write8 = &sdio_write8;
560 pops->_write16 = &sdio_write16;
561 pops->_write32 = &sdio_write32;
562 pops->_writeN = &sdio_writeN;
563 pops->_write_mem = &sdio_write_mem;
564 pops->_write_port = &sdio_write_port;
566 pops->_sd_f0_read8 = sdio_f0_read8;
570 * Todo: align address to 4 bytes.
572 static s32 _sdio_local_read(
573 struct adapter *padapter,
579 struct intf_hdl *pintfhdl;
586 pintfhdl = &padapter->iopriv.intf;
588 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
590 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
591 if (false == bMacPwrCtrlOn) {
592 err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
597 ptmpbuf = (u8 *)rtw_malloc(n);
601 err = _sd_read(pintfhdl, addr, n, ptmpbuf);
603 memcpy(pbuf, ptmpbuf, cnt);
611 * Todo: align address to 4 bytes.
614 struct adapter *padapter,
620 struct intf_hdl *pintfhdl;
626 pintfhdl = &padapter->iopriv.intf;
628 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
630 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
632 (false == bMacPwrCtrlOn) ||
633 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
635 err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
640 ptmpbuf = (u8 *)rtw_malloc(n);
644 err = sd_read(pintfhdl, addr, n, ptmpbuf);
646 memcpy(pbuf, ptmpbuf, cnt);
654 * Todo: align address to 4 bytes.
656 s32 sdio_local_write(
657 struct adapter *padapter,
663 struct intf_hdl *pintfhdl;
669 DBG_8192C("%s, address must be 4 bytes alignment\n", __func__);
672 DBG_8192C("%s, size must be the multiple of 4\n", __func__);
674 pintfhdl = &padapter->iopriv.intf;
676 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
678 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
680 (false == bMacPwrCtrlOn) ||
681 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
683 err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
687 ptmpbuf = (u8 *)rtw_malloc(cnt);
691 memcpy(ptmpbuf, pbuf, cnt);
693 err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
700 u8 SdioLocalCmd52Read1Byte(struct adapter *padapter, u32 addr)
703 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
705 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
706 sd_cmd52_read(pintfhdl, addr, 1, &val);
711 static u16 SdioLocalCmd52Read2Byte(struct adapter *padapter, u32 addr)
714 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
716 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
717 sd_cmd52_read(pintfhdl, addr, 2, (u8 *)&val);
719 return le16_to_cpu(val);
722 static u32 SdioLocalCmd53Read4Byte(struct adapter *padapter, u32 addr)
727 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
730 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
731 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
732 if (!bMacPwrCtrlOn || adapter_to_pwrctl(padapter)->bFwCurrentInPSMode) {
733 sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&le_tmp);
734 val = le32_to_cpu(le_tmp);
736 val = sd_read32(pintfhdl, addr, NULL);
741 void SdioLocalCmd52Write1Byte(struct adapter *padapter, u32 addr, u8 v)
743 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
745 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
746 sd_cmd52_write(pintfhdl, addr, 1, &v);
749 static void SdioLocalCmd52Write4Byte(struct adapter *padapter, u32 addr, u32 v)
751 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
754 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
755 le_tmp = cpu_to_le32(v);
756 sd_cmd52_write(pintfhdl, addr, 4, (u8 *)&le_tmp);
759 static s32 ReadInterrupt8723BSdio(struct adapter *padapter, u32 *phisr)
768 himr = GET_HAL_DATA(padapter)->sdio_himr;
770 /* decide how many bytes need to be read */
778 while (hisr_len != 0) {
780 val8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR+hisr_len);
781 hisr |= (val8 << (8*hisr_len));
791 /* Initialize SDIO Host Interrupt Mask configuration variables for future use. */
794 /* Using SDIO Local register ONLY for configuration. */
796 /* Created by Roger, 2011.02.11. */
798 void InitInterrupt8723BSdio(struct adapter *padapter)
800 struct hal_com_data *pHalData;
803 pHalData = GET_HAL_DATA(padapter);
804 pHalData->sdio_himr = (u32)( \
805 SDIO_HIMR_RX_REQUEST_MSK |
807 /* SDIO_HIMR_TXERR_MSK | */
808 /* SDIO_HIMR_RXERR_MSK | */
809 /* SDIO_HIMR_TXFOVW_MSK | */
810 /* SDIO_HIMR_RXFOVW_MSK | */
811 /* SDIO_HIMR_TXBCNOK_MSK | */
812 /* SDIO_HIMR_TXBCNERR_MSK | */
813 /* SDIO_HIMR_BCNERLY_INT_MSK | */
814 /* SDIO_HIMR_C2HCMD_MSK | */
815 /* SDIO_HIMR_HSISR_IND_MSK | */
816 /* SDIO_HIMR_GTINT3_IND_MSK | */
817 /* SDIO_HIMR_GTINT4_IND_MSK | */
818 /* SDIO_HIMR_PSTIMEOUT_MSK | */
819 /* SDIO_HIMR_OCPINT_MSK | */
820 /* SDIO_HIMR_ATIMEND_MSK | */
821 /* SDIO_HIMR_ATIMEND_E_MSK | */
822 /* SDIO_HIMR_CTWEND_MSK | */
828 /* Initialize System Host Interrupt Mask configuration variables for future use. */
830 /* Created by Roger, 2011.08.03. */
832 void InitSysInterrupt8723BSdio(struct adapter *padapter)
834 struct hal_com_data *pHalData;
837 pHalData = GET_HAL_DATA(padapter);
839 pHalData->SysIntrMask = ( \
840 /* HSIMR_GPIO12_0_INT_EN | */
841 /* HSIMR_SPS_OCP_INT_EN | */
842 /* HSIMR_RON_INT_EN | */
843 /* HSIMR_PDNINT_EN | */
844 /* HSIMR_GPIO9_INT_EN | */
851 /* Clear corresponding SDIO Host ISR interrupt service. */
854 /* Using SDIO Local register ONLY for configuration. */
856 /* Created by Roger, 2011.02.11. */
858 void ClearInterrupt8723BSdio(struct adapter *padapter)
860 struct hal_com_data *pHalData;
864 if (true == padapter->bSurpriseRemoved)
867 pHalData = GET_HAL_DATA(padapter);
868 clear = rtw_zmalloc(4);
870 /* Clear corresponding HISR Content if needed */
871 *(__le32 *)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
872 if (*(__le32 *)clear) {
873 /* Perform write one clear operation */
874 sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
883 /* Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
886 /* 1. Using SDIO Local register ONLY for configuration. */
887 /* 2. PASSIVE LEVEL */
889 /* Created by Roger, 2011.02.11. */
891 void EnableInterrupt8723BSdio(struct adapter *padapter)
893 struct hal_com_data *pHalData;
897 pHalData = GET_HAL_DATA(padapter);
899 himr = cpu_to_le32(pHalData->sdio_himr);
900 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
906 "%s: enable SDIO HIMR = 0x%08X\n",
912 /* Update current system IMR settings */
913 tmp = rtw_read32(padapter, REG_HSIMR);
914 rtw_write32(padapter, REG_HSIMR, tmp | pHalData->SysIntrMask);
920 "%s: enable HSIMR = 0x%08X\n",
922 pHalData->SysIntrMask
927 /* <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
928 /* So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
931 rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
936 /* Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
939 /* Using SDIO Local register ONLY for configuration. */
941 /* Created by Roger, 2011.02.11. */
943 void DisableInterrupt8723BSdio(struct adapter *padapter)
947 himr = cpu_to_le32(SDIO_HIMR_DISABLED);
948 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
953 /* Using 0x100 to check the power status of FW. */
956 /* Using SDIO Local register ONLY for configuration. */
958 /* Created by Isaac, 2013.09.10. */
960 u8 CheckIPSStatus(struct adapter *padapter)
963 "%s(): Read 0x100 = 0x%02x 0x86 = 0x%02x\n",
965 rtw_read8(padapter, 0x100),
966 rtw_read8(padapter, 0x86)
969 if (rtw_read8(padapter, 0x100) == 0xEA)
975 static struct recv_buf *sd_recv_rxfifo(struct adapter *padapter, u32 size)
979 struct recv_priv *precvpriv;
980 struct recv_buf *precvbuf;
983 /* Patch for some SDIO Host 4 bytes issue */
985 readsize = RND4(size);
987 /* 3 1. alloc recvbuf */
988 precvpriv = &padapter->recvpriv;
989 precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
990 if (precvbuf == NULL) {
991 DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__);
996 if (precvbuf->pskb == NULL) {
997 SIZE_PTR tmpaddr = 0;
998 SIZE_PTR alignment = 0;
1000 precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1002 if (precvbuf->pskb) {
1003 precvbuf->pskb->dev = padapter->pnetdev;
1005 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
1006 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
1007 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
1010 if (precvbuf->pskb == NULL) {
1011 DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, readsize);
1016 /* 3 3. read data from rxfifo */
1017 preadbuf = precvbuf->pskb->data;
1018 ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1020 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __func__));
1025 /* 3 4. init recvbuf */
1026 precvbuf->len = size;
1027 precvbuf->phead = precvbuf->pskb->head;
1028 precvbuf->pdata = precvbuf->pskb->data;
1029 skb_set_tail_pointer(precvbuf->pskb, size);
1030 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1031 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1036 static void sd_rxhandler(struct adapter *padapter, struct recv_buf *precvbuf)
1038 struct recv_priv *precvpriv;
1039 struct __queue *ppending_queue;
1041 precvpriv = &padapter->recvpriv;
1042 ppending_queue = &precvpriv->recv_buf_pending_queue;
1044 /* 3 1. enqueue recvbuf */
1045 rtw_enqueue_recvbuf(precvbuf, ppending_queue);
1047 /* 3 2. schedule tasklet */
1048 tasklet_schedule(&precvpriv->recv_tasklet);
1051 void sd_int_dpc(struct adapter *padapter)
1053 struct hal_com_data *phal;
1054 struct dvobj_priv *dvobj;
1055 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
1056 struct pwrctrl_priv *pwrctl;
1059 phal = GET_HAL_DATA(padapter);
1060 dvobj = adapter_to_dvobj(padapter);
1061 pwrctl = dvobj_to_pwrctl(dvobj);
1063 if (phal->sdio_hisr & SDIO_HISR_AVAL) {
1066 _sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 4, freepage);
1067 up(&(padapter->xmitpriv.xmit_sema));
1070 if (phal->sdio_hisr & SDIO_HISR_CPWM1) {
1071 struct reportpwrstate_parm report;
1074 _cancel_timer(&(pwrctl->pwr_rpwm_timer), &bcancelled);
1076 report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8723B);
1078 /* cpwm_int_hdl(padapter, &report); */
1079 _set_workitem(&(pwrctl->cpwm_event));
1082 if (phal->sdio_hisr & SDIO_HISR_TXERR) {
1086 status = rtw_malloc(4);
1088 addr = REG_TXDMA_STATUS;
1089 HalSdioGetCmdAddr8723BSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1090 _sd_read(pintfhdl, addr, 4, status);
1091 _sd_write(pintfhdl, addr, 4, status);
1092 DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
1095 DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1099 if (phal->sdio_hisr & SDIO_HISR_TXBCNOK) {
1100 DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
1103 if (phal->sdio_hisr & SDIO_HISR_TXBCNERR) {
1104 DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__);
1106 #ifndef CONFIG_C2H_PACKET_EN
1107 if (phal->sdio_hisr & SDIO_HISR_C2HCMD) {
1108 struct c2h_evt_hdr_88xx *c2h_evt;
1110 DBG_8192C("%s: C2H Command\n", __func__);
1111 c2h_evt = (struct c2h_evt_hdr_88xx *)rtw_zmalloc(16);
1112 if (c2h_evt != NULL) {
1113 if (rtw_hal_c2h_evt_read(padapter, (u8 *)c2h_evt) == _SUCCESS) {
1114 if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
1115 /* Handle CCX report here */
1116 rtw_hal_c2h_handler(padapter, (u8 *)c2h_evt);
1117 kfree((u8 *)c2h_evt);
1119 rtw_c2h_wk_cmd(padapter, (u8 *)c2h_evt);
1125 /* Error handling for malloc fail */
1126 if (rtw_cbuf_push(padapter->evtpriv.c2h_queue, NULL) != _SUCCESS)
1127 DBG_871X("%s rtw_cbuf_push fail\n", __func__);
1128 _set_workitem(&padapter->evtpriv.c2h_wk);
1133 if (phal->sdio_hisr & SDIO_HISR_RXFOVW) {
1134 DBG_8192C("%s: Rx Overflow\n", __func__);
1137 if (phal->sdio_hisr & SDIO_HISR_RXERR) {
1138 DBG_8192C("%s: Rx Error\n", __func__);
1141 if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
1142 struct recv_buf *precvbuf;
1143 int alloc_fail_time = 0;
1146 /* DBG_8192C("%s: RX Request, size =%d\n", __func__, phal->SdioRxFIFOSize); */
1147 phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1149 phal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(padapter, SDIO_REG_RX0_REQ_LEN);
1150 if (phal->SdioRxFIFOSize != 0) {
1151 precvbuf = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize);
1153 sd_rxhandler(padapter, precvbuf);
1156 DBG_871X("precvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time);
1157 if (alloc_fail_time >= 10)
1160 phal->SdioRxFIFOSize = 0;
1165 ReadInterrupt8723BSdio(padapter, &hisr);
1166 hisr &= SDIO_HISR_RX_REQUEST;
1171 if (alloc_fail_time == 10)
1172 DBG_871X("exit because alloc memory failed more than 10 times\n");
1177 void sd_int_hdl(struct adapter *padapter)
1179 struct hal_com_data *phal;
1183 (padapter->bDriverStopped == true) ||
1184 (padapter->bSurpriseRemoved == true)
1188 phal = GET_HAL_DATA(padapter);
1190 phal->sdio_hisr = 0;
1191 ReadInterrupt8723BSdio(padapter, &phal->sdio_hisr);
1193 if (phal->sdio_hisr & phal->sdio_himr) {
1196 phal->sdio_hisr &= phal->sdio_himr;
1199 v32 = phal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
1201 SdioLocalCmd52Write4Byte(padapter, SDIO_REG_HISR, v32);
1204 sd_int_dpc(padapter);
1206 RT_TRACE(_module_hci_ops_c_, _drv_err_,
1207 ("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
1208 __func__, phal->sdio_hisr, phal->sdio_himr));
1214 /* Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
1217 /* 1. Running at PASSIVE_LEVEL */
1218 /* 2. RT_TX_SPINLOCK is NOT acquired. */
1220 /* Created by Roger, 2011.01.28. */
1222 u8 HalQueryTxBufferStatus8723BSdio(struct adapter *padapter)
1224 struct hal_com_data *phal;
1229 phal = GET_HAL_DATA(padapter);
1231 NumOfFreePage = SdioLocalCmd53Read4Byte(padapter, SDIO_REG_FREE_TXPG);
1233 /* spin_lock_bh(&phal->SdioTxFIFOFreePageLock); */
1234 memcpy(phal->SdioTxFIFOFreePage, &NumOfFreePage, 4);
1235 RT_TRACE(_module_hci_ops_c_, _drv_notice_,
1236 ("%s: Free page for HIQ(%#x), MIDQ(%#x), LOWQ(%#x), PUBQ(%#x)\n",
1238 phal->SdioTxFIFOFreePage[HI_QUEUE_IDX],
1239 phal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
1240 phal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
1241 phal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
1242 /* spin_unlock_bh(&phal->SdioTxFIFOFreePageLock); */
1249 /* Query SDIO Local register to get the current number of TX OQT Free Space. */
1251 u8 HalQueryTxOQTBufferStatus8723BSdio(struct adapter *padapter)
1253 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1255 pHalData->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_OQT_FREE_PG);
1259 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1260 u8 RecvOnePkt(struct adapter *padapter, u32 size)
1262 struct recv_buf *precvbuf;
1263 struct dvobj_priv *psddev;
1264 PSDIO_DATA psdio_data;
1265 struct sdio_func *func;
1269 DBG_871X("+%s: size: %d+\n", __func__, size);
1271 if (padapter == NULL) {
1272 DBG_871X(KERN_ERR "%s: padapter is NULL!\n", __func__);
1276 psddev = adapter_to_dvobj(padapter);
1277 psdio_data = &psddev->intf_data;
1278 func = psdio_data->func;
1281 sdio_claim_host(func);
1282 precvbuf = sd_recv_rxfifo(padapter, size);
1285 /* printk("Completed Recv One Pkt.\n"); */
1286 sd_rxhandler(padapter, precvbuf);
1291 sdio_release_host(func);
1293 DBG_871X("-%s-\n", __func__);
1296 #endif /* CONFIG_WOWLAN */