diff options
Diffstat (limited to 'drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio')
5 files changed, 8786 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_led.c b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_led.c new file mode 100755 index 00000000..06c90c55 --- /dev/null +++ b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_led.c @@ -0,0 +1,124 @@ +/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTL8189ES_LED_C_
+
+#include "drv_types.h"
+#include "rtl8188e_hal.h"
+
+//================================================================================
+// LED object.
+//================================================================================
+
+
+//================================================================================
+// Prototype of protected function.
+//================================================================================
+
+//================================================================================
+// LED_819xUsb routines.
+//================================================================================
+
+//
+// Description:
+// Turn on LED according to LedPin specified.
+//
+void
+SwLedOn(
+ _adapter *padapter,
+ PLED_871x pLed
+)
+{
+ u8 LedCfg;
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+
+ if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE))
+ {
+ return;
+ }
+
+ pLed->bLedOn = _TRUE;
+}
+
+
+//
+// Description:
+// Turn off LED according to LedPin specified.
+//
+void
+SwLedOff(
+ _adapter *padapter,
+ PLED_871x pLed
+)
+{
+ u8 LedCfg;
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+
+ if((padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE))
+ {
+ goto exit;
+ }
+
+exit:
+ pLed->bLedOn = _FALSE;
+
+}
+
+//================================================================================
+// Default LED behavior.
+//================================================================================
+
+//
+// Description:
+// Initialize all LED_871x objects.
+//
+void
+rtl8188es_InitSwLeds(
+ _adapter *padapter
+ )
+{
+ struct led_priv *pledpriv = &(padapter->ledpriv);
+
+#if 0
+ pledpriv->LedControlHandler = LedControl871x;
+
+ InitLed871x(padapter, &(pledpriv->SwLed0), LED_PIN_LED0);
+
+ InitLed871x(padapter,&(pledpriv->SwLed1), LED_PIN_LED1);
+#endif
+}
+
+
+//
+// Description:
+// DeInitialize all LED_819xUsb objects.
+//
+void
+rtl8188es_DeInitSwLeds(
+ _adapter *padapter
+ )
+{
+#if 0
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+
+ DeInitLed871x( &(ledpriv->SwLed0) );
+ DeInitLed871x( &(ledpriv->SwLed1) );
+#endif
+}
+
diff --git a/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_recv.c b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_recv.c new file mode 100755 index 00000000..06807f97 --- /dev/null +++ b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_recv.c @@ -0,0 +1,852 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#define _RTL8189ES_RECV_C_ + +#include <drv_conf.h> + +#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS) +#error "Shall be Linux or Windows, but not both!\n" +#endif + +#include <drv_types.h> +#include <recv_osdep.h> +#include <rtl8188e_hal.h> + +static void rtl8188es_recv_tasklet(void *priv); + +static s32 initrecvbuf(struct recv_buf *precvbuf, PADAPTER padapter) +{ + _rtw_init_listhead(&precvbuf->list); + _rtw_spinlock_init(&precvbuf->recvbuf_lock); + + precvbuf->adapter = padapter; + + return _SUCCESS; +} + +static void freerecvbuf(struct recv_buf *precvbuf) +{ + _rtw_spinlock_free(&precvbuf->recvbuf_lock); +} + +/* + * Initialize recv private variable for hardware dependent + * 1. recv buf + * 2. recv tasklet + * + */ +s32 rtl8188es_init_recv_priv(PADAPTER padapter) +{ + s32 res; + u32 i, n; + struct recv_priv *precvpriv; + struct recv_buf *precvbuf; + + + res = _SUCCESS; + precvpriv = &padapter->recvpriv; + + //3 1. init recv buffer + _rtw_init_queue(&precvpriv->free_recv_buf_queue); + _rtw_init_queue(&precvpriv->recv_buf_pending_queue); + + n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; + precvpriv->pallocated_recv_buf = rtw_zmalloc(n); + if (precvpriv->pallocated_recv_buf == NULL) { + res = _FAIL; + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n")); + goto exit; + } + + precvpriv->precv_buf = (u8*)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4); + + // init each recv buffer + precvbuf = (struct recv_buf*)precvpriv->precv_buf; + for (i = 0; i < NR_RECVBUFF; i++) + { + res = initrecvbuf(precvbuf, padapter); + if (res == _FAIL) + break; + + res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf); + if (res == _FAIL) { + freerecvbuf(precvbuf); + break; + } + +#ifdef CONFIG_SDIO_RX_COPY + if (precvbuf->pskb == NULL) { + SIZE_PTR tmpaddr=0; + SIZE_PTR alignment=0; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html + precvbuf->pskb = __dev_alloc_skb(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL); +#else + precvbuf->pskb = __netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL); +#endif + + if(precvbuf->pskb) + { + precvbuf->pskb->dev = padapter->pnetdev; + + tmpaddr = (SIZE_PTR)precvbuf->pskb->data; + alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); + skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); + + precvbuf->phead = precvbuf->pskb->head; + precvbuf->pdata = precvbuf->pskb->data; + precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); + precvbuf->pend = skb_end_pointer(precvbuf->pskb); + precvbuf->len = 0; + } + + if (precvbuf->pskb == NULL) { + DBG_871X("%s: alloc_skb fail!\n", __FUNCTION__); + } + } +#endif + + rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue); + + precvbuf++; + } + precvpriv->free_recv_buf_queue_cnt = i; + + if (res == _FAIL) + goto initbuferror; + + //3 2. init tasklet +#ifdef PLATFORM_LINUX + tasklet_init(&precvpriv->recv_tasklet, + (void(*)(unsigned long))rtl8188es_recv_tasklet, + (unsigned long)padapter); +#endif + + goto exit; + +initbuferror: + precvbuf = (struct recv_buf*)precvpriv->precv_buf; + if (precvbuf) { + n = precvpriv->free_recv_buf_queue_cnt; + precvpriv->free_recv_buf_queue_cnt = 0; + for (i = 0; i < n ; i++) + { + rtw_list_delete(&precvbuf->list); + rtw_os_recvbuf_resource_free(padapter, precvbuf); + freerecvbuf(precvbuf); + precvbuf++; + } + precvpriv->precv_buf = NULL; + } + + if (precvpriv->pallocated_recv_buf) { + n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; + rtw_mfree(precvpriv->pallocated_recv_buf, n); + precvpriv->pallocated_recv_buf = NULL; + } + +exit: + return res; +} + +/* + * Free recv private variable of hardware dependent + * 1. recv buf + * 2. recv tasklet + * + */ +void rtl8188es_free_recv_priv(PADAPTER padapter) +{ + u32 i, n; + struct recv_priv *precvpriv; + struct recv_buf *precvbuf; + + + precvpriv = &padapter->recvpriv; + + //3 1. kill tasklet +#ifdef PLATFORM_LINUX + tasklet_kill(&precvpriv->recv_tasklet); +#endif + + //3 2. free all recv buffers + precvbuf = (struct recv_buf*)precvpriv->precv_buf; + if (precvbuf) { + n = NR_RECVBUFF; + precvpriv->free_recv_buf_queue_cnt = 0; + for (i = 0; i < n ; i++) + { + rtw_list_delete(&precvbuf->list); + rtw_os_recvbuf_resource_free(padapter, precvbuf); + freerecvbuf(precvbuf); + precvbuf++; + } + precvpriv->precv_buf = NULL; + } + + if (precvpriv->pallocated_recv_buf) { + n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; + rtw_mfree(precvpriv->pallocated_recv_buf, n); + precvpriv->pallocated_recv_buf = NULL; + } +} + +#ifdef CONFIG_SDIO_RX_COPY +static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf *precvbuf, struct phy_stat *pphy_status) +{ + s32 ret=_SUCCESS; +#ifdef CONFIG_CONCURRENT_MODE + u8 *primary_myid, *secondary_myid, *paddr1; + union recv_frame *precvframe_if2 = NULL; + _adapter *primary_padapter = precvframe->u.hdr.adapter; + _adapter *secondary_padapter = primary_padapter->pbuddy_adapter; + struct recv_priv *precvpriv = &primary_padapter->recvpriv; + _queue *pfree_recv_queue = &precvpriv->free_recv_queue; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(primary_padapter); + + if(!secondary_padapter) + return ret; + + paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data); + + if(IS_MCAST(paddr1) == _FALSE)//unicast packets + { + //primary_myid = myid(&primary_padapter->eeprompriv); + secondary_myid = myid(&secondary_padapter->eeprompriv); + + if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN)) + { + //change to secondary interface + precvframe->u.hdr.adapter = secondary_padapter; + } + + //ret = recv_entry(precvframe); + + } + else // Handle BC/MC Packets + { + //clone/copy to if2 + _pkt *pkt_copy = NULL; + struct rx_pkt_attrib *pattrib = NULL; + + precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue); + + if(!precvframe_if2) + return _FAIL; + + precvframe_if2->u.hdr.adapter = secondary_padapter; + _rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib)); + pattrib = &precvframe_if2->u.hdr.attrib; + + //driver need to set skb len for skb_copy(). + //If skb->len is zero, skb_copy() will not copy data from original skb. + skb_put(precvframe->u.hdr.pkt, pattrib->pkt_len); + + pkt_copy = skb_copy( precvframe->u.hdr.pkt, GFP_ATOMIC); + if (pkt_copy == NULL) + { + if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)) + { + DBG_8192C("pre_recv_entry(): skb_copy fail , drop frag frame \n"); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + return ret; + } + + pkt_copy = skb_clone( precvframe->u.hdr.pkt, GFP_ATOMIC); + if(pkt_copy == NULL) + { + DBG_8192C("pre_recv_entry(): skb_clone fail , drop frame\n"); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + return ret; + } + } + + pkt_copy->dev = secondary_padapter->pnetdev; + + precvframe_if2->u.hdr.pkt = pkt_copy; + precvframe_if2->u.hdr.rx_head = pkt_copy->head; + precvframe_if2->u.hdr.rx_data = pkt_copy->data; + precvframe_if2->u.hdr.rx_tail = skb_tail_pointer(pkt_copy); + precvframe_if2->u.hdr.rx_end = skb_end_pointer(pkt_copy); + precvframe_if2->u.hdr.len = pkt_copy->len; + + //recvframe_put(precvframe_if2, pattrib->pkt_len); + + if ( pHalData->ReceiveConfig & RCR_APPFCS) + recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN); + + if (pattrib->physt) + update_recvframe_phyinfo_88e(precvframe_if2, pphy_status); + + if(rtw_recv_entry(precvframe_if2) != _SUCCESS) + { + RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, + ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n")); + } + } + + if (precvframe->u.hdr.attrib.physt) + update_recvframe_phyinfo_88e(precvframe, pphy_status); + ret = rtw_recv_entry(precvframe); + +#endif + + return ret; + +} + +static void rtl8188es_recv_tasklet(void *priv) +{ + PADAPTER padapter; + PHAL_DATA_TYPE pHalData; + struct recv_priv *precvpriv; + struct recv_buf *precvbuf; + union recv_frame *precvframe; + struct recv_frame_hdr *phdr; + struct rx_pkt_attrib *pattrib; + _irqL irql; + u8 *ptr; + u32 pkt_offset, skb_len, alloc_sz; + s32 transfer_len; + _pkt *pkt_copy = NULL; + struct phy_stat *pphy_status = NULL; + u8 shift_sz = 0, rx_report_sz = 0; + + + padapter = (PADAPTER)priv; + pHalData = GET_HAL_DATA(padapter); + precvpriv = &padapter->recvpriv; + + do { + if ((padapter->bDriverStopped == _TRUE)||(padapter->bSurpriseRemoved== _TRUE)) + { + DBG_8192C("recv_tasklet => bDriverStopped or bSurpriseRemoved \n"); + break; + } + + precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue); + if (NULL == precvbuf) break; + + transfer_len = (s32)precvbuf->len; + ptr = precvbuf->pdata; + + do { + precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); + if (precvframe == NULL) { + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: no enough recv frame!\n",__FUNCTION__)); + rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); + + // The case of can't allocte recvframe should be temporary, + // schedule again and hope recvframe is available next time. +#ifdef PLATFORM_LINUX + tasklet_schedule(&precvpriv->recv_tasklet); +#endif + return; + } + + //rx desc parsing + update_recvframe_attrib_88e(precvframe, (struct recv_stat*)ptr); + + pattrib = &precvframe->u.hdr.attrib; + + // fix Hardware RX data error, drop whole recv_buffer + if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) + { + #if !(MP_DRIVER==1) + DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__); + #endif + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + break; + } + + if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) + rx_report_sz = RXDESC_SIZE + 4 + pattrib->drvinfo_sz; + else + rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz; + + pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len; + + if ((pattrib->pkt_len==0) || (pkt_offset>transfer_len)) { + DBG_8192C("%s()-%d: RX Warning!,pkt_len==0 or pkt_offset(%d)> transfoer_len(%d) \n", __FUNCTION__, __LINE__, pkt_offset, transfer_len); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + break; + } + + if ((pattrib->crc_err) || (pattrib->icv_err)) + { + DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + } + else + { + // Modified by Albert 20101213 + // For 8 bytes IP header alignment. + if (pattrib->qos) // Qos data, wireless lan header length is 26 + { + shift_sz = 6; + } + else + { + shift_sz = 0; + } + + skb_len = pattrib->pkt_len; + + // for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. + // modify alloc_sz for recvive crc error packet by thomas 2011-06-02 + if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){ + //alloc_sz = 1664; //1664 is 128 alignment. + if(skb_len <= 1650) + alloc_sz = 1664; + else + alloc_sz = skb_len + 14; + } + else { + alloc_sz = skb_len; + // 6 is for IP header 8 bytes alignment in QoS packet case. + // 8 is for skb->data 4 bytes alignment. + alloc_sz += 14; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html + pkt_copy = dev_alloc_skb(alloc_sz); +#else + pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz); +#endif + if(pkt_copy) + { + pkt_copy->dev = padapter->pnetdev; + precvframe->u.hdr.pkt = pkt_copy; + skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address + skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz. + _rtw_memcpy(pkt_copy->data, (ptr + rx_report_sz + pattrib->shift_sz), skb_len); + precvframe->u.hdr.rx_head = pkt_copy->head; + precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data; + precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy); + } + else + { + if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)) + { + DBG_8192C("rtl8188es_recv_tasklet: alloc_skb fail , drop frag frame \n"); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + break; + } + + precvframe->u.hdr.pkt = skb_clone(precvbuf->pskb, GFP_ATOMIC); + if(precvframe->u.hdr.pkt) + { + _pkt *pkt_clone = precvframe->u.hdr.pkt; + + pkt_clone->data = ptr + rx_report_sz + pattrib->shift_sz; + skb_reset_tail_pointer(pkt_clone); + precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail + = pkt_clone->data; + precvframe->u.hdr.rx_end = pkt_clone->data + skb_len; + } + else + { + DBG_8192C("rtl8188es_recv_tasklet: skb_clone fail\n"); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + break; + } + } + + recvframe_put(precvframe, skb_len); + //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); + + if (pHalData->ReceiveConfig & RCR_APPFCS) + recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN); + + // update drv info + if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) { + //rtl8723s_update_bassn(padapter, (ptr + RXDESC_SIZE)); + } + + if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet + { + pphy_status = (struct phy_stat *)(ptr + (rx_report_sz - pattrib->drvinfo_sz)); + +#ifdef CONFIG_CONCURRENT_MODE + if(rtw_buddy_adapter_up(padapter)) + { + if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)pphy_status) != _SUCCESS) + { + RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, + ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n")); + } + } + else +#endif + { + if (pattrib->physt) + update_recvframe_phyinfo_88e(precvframe, (struct phy_stat*)pphy_status); + + if (rtw_recv_entry(precvframe) != _SUCCESS) + { + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__)); + } + } + } + else{ // pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP + + //enqueue recvframe to txrtp queue + if(pattrib->pkt_rpt_type == TX_REPORT1){ + //DBG_8192C("rx CCX \n"); + //CCX-TXRPT ack for xmit mgmt frames. + handle_txrpt_ccx_88e(padapter, precvframe->u.hdr.rx_data); + } + else if(pattrib->pkt_rpt_type == TX_REPORT2){ + //printk("rx TX RPT \n"); + ODM_RA_TxRPT2Handle_8188E( + &pHalData->odmpriv, + precvframe->u.hdr.rx_data, + pattrib->pkt_len, + pattrib->MacIDValidEntry[0], + pattrib->MacIDValidEntry[1] + ); + + } + /* + else if(pattrib->pkt_rpt_type == HIS_REPORT){ + printk("rx USB HISR \n"); + }*/ + + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + + } + } + + // Page size of receive package is 128 bytes alignment =>DMA AGG + // refer to _InitTransferPageSize() + pkt_offset = _RND128(pkt_offset); + transfer_len -= pkt_offset; + ptr += pkt_offset; + precvframe = NULL; + pkt_copy = NULL; + }while(transfer_len>0); + + precvbuf->len = 0; + + rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); + } while (1); + +} +#else +static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf *precvbuf, struct phy_stat *pphy_status) +{ + s32 ret=_SUCCESS; +#ifdef CONFIG_CONCURRENT_MODE + u8 *primary_myid, *secondary_myid, *paddr1; + union recv_frame *precvframe_if2 = NULL; + _adapter *primary_padapter = precvframe->u.hdr.adapter; + _adapter *secondary_padapter = primary_padapter->pbuddy_adapter; + struct recv_priv *precvpriv = &primary_padapter->recvpriv; + _queue *pfree_recv_queue = &precvpriv->free_recv_queue; + u8 *pbuf = precvframe->u.hdr.rx_head; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(primary_padapter); + + if(!secondary_padapter) + return ret; + + paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data); + + if(IS_MCAST(paddr1) == _FALSE)//unicast packets + { + //primary_myid = myid(&primary_padapter->eeprompriv); + secondary_myid = myid(&secondary_padapter->eeprompriv); + + if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN)) + { + //change to secondary interface + precvframe->u.hdr.adapter = secondary_padapter; + } + + //ret = recv_entry(precvframe); + + } + else // Handle BC/MC Packets + { + //clone/copy to if2 + u8 shift_sz = 0; + u32 alloc_sz, skb_len; + _pkt *pkt_copy = NULL; + struct rx_pkt_attrib *pattrib = NULL; + + precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue); + + if(!precvframe_if2) + return _FAIL; + + precvframe_if2->u.hdr.adapter = secondary_padapter; + _rtw_init_listhead(&precvframe_if2->u.hdr.list); + precvframe_if2->u.hdr.precvbuf = NULL; //can't access the precvbuf for new arch. + precvframe_if2->u.hdr.len=0; + _rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib)); + pattrib = &precvframe_if2->u.hdr.attrib; + + pkt_copy = skb_copy( precvframe->u.hdr.pkt, GFP_ATOMIC); + if (pkt_copy == NULL) + { + RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("%s: no enough memory to allocate SKB!\n",__FUNCTION__)); + rtw_free_recvframe(precvframe_if2, &precvpriv->free_recv_queue); + rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); + + // The case of can't allocte skb is serious and may never be recovered, + // once bDriverStopped is enable, this task should be stopped. + if (secondary_padapter->bDriverStopped == _FALSE) +#ifdef PLATFORM_LINUX + tasklet_schedule(&precvpriv->recv_tasklet); +#endif + return ret; + } + pkt_copy->dev = secondary_padapter->pnetdev; + + + + if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){ + //alloc_sz = 1664; //1664 is 128 alignment. + if(skb_len <= 1650) + alloc_sz = 1664; + else + alloc_sz = skb_len + 14; + } + else { + alloc_sz = skb_len; + // 6 is for IP header 8 bytes alignment in QoS packet case. + // 8 is for skb->data 4 bytes alignment. + alloc_sz += 14; + } + +#if 1 + precvframe_if2->u.hdr.pkt = pkt_copy; + precvframe_if2->u.hdr.rx_head = pkt_copy->head; + precvframe_if2->u.hdr.rx_data = precvframe_if2->u.hdr.rx_tail = pkt_copy->data; + precvframe_if2->u.hdr.rx_end = pkt_copy->data + alloc_sz; +#endif + recvframe_put(precvframe_if2, pkt_offset); + recvframe_pull(precvframe_if2, RXDESC_SIZE + pattrib->drvinfo_sz); + + if ( pHalData->ReceiveConfig & RCR_APPFCS) + recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN); + + if (pattrib->physt) + update_recvframe_phyinfo_88e(precvframe_if2, pphy_status); + + if(rtw_recv_entry(precvframe_if2) != _SUCCESS) + { + RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, + ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n")); + } + } + + if (precvframe->u.hdr.attrib.physt) + update_recvframe_phyinfo_88e(precvframe, (struct phy_stat*)pphy_status); + ret = rtw_recv_entry(precvframe); + +#endif + + return ret; + +} + +static void rtl8188es_recv_tasklet(void *priv) +{ + PADAPTER padapter; + PHAL_DATA_TYPE pHalData; + struct recv_priv *precvpriv; + struct recv_buf *precvbuf; + union recv_frame *precvframe; + struct recv_frame_hdr *phdr; + struct rx_pkt_attrib *pattrib; + u8 *ptr; + _pkt *ppkt; + u32 pkt_offset; + _irqL irql; +#ifdef CONFIG_CONCURRENT_MODE + struct recv_stat *prxstat; +#endif + + padapter = (PADAPTER)priv; + pHalData = GET_HAL_DATA(padapter); + precvpriv = &padapter->recvpriv; + + do { + precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue); + if (NULL == precvbuf) break; + + ptr = precvbuf->pdata; + + while (ptr < precvbuf->ptail) + { + precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); + if (precvframe == NULL) { + RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: no enough recv frame!\n",__FUNCTION__)); + rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); + + // The case of can't allocte recvframe should be temporary, + // schedule again and hope recvframe is available next time. +#ifdef PLATFORM_LINUX + tasklet_schedule(&precvpriv->recv_tasklet); +#endif + return; + } + + phdr = &precvframe->u.hdr; + pattrib = &phdr->attrib; + + //rx desc parsing + update_recvframe_attrib_88e(precvframe, (struct recv_stat*)ptr); +#ifdef CONFIG_CONCURRENT_MODE + prxstat = (struct recv_stat*)ptr; +#endif + // fix Hardware RX data error, drop whole recv_buffer + if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) + { + //#if !(MP_DRIVER==1) + if (padapter->registrypriv.mp_mode == 0) + DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__); + //#endif + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + break; + } + + pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len; + + if ((ptr + pkt_offset) > precvbuf->ptail) { + DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + break; + } + + if ((pattrib->crc_err) || (pattrib->icv_err)) + { + DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + } + else + { + ppkt = skb_clone(precvbuf->pskb, GFP_ATOMIC); + if (ppkt == NULL) + { + RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("%s: no enough memory to allocate SKB!\n",__FUNCTION__)); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); + + // The case of can't allocte skb is serious and may never be recovered, + // once bDriverStopped is enable, this task should be stopped. + if (padapter->bDriverStopped == _FALSE) { +#ifdef PLATFORM_LINUX + tasklet_schedule(&precvpriv->recv_tasklet); +#endif + } + + return; + } + + phdr->pkt = ppkt; + phdr->len = 0; + phdr->rx_head = precvbuf->phead; + phdr->rx_data = phdr->rx_tail = precvbuf->pdata; + phdr->rx_end = precvbuf->pend; + + recvframe_put(precvframe, pkt_offset); + recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz); + + if (pHalData->ReceiveConfig & RCR_APPFCS) + recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN); + + // move to drv info position + ptr += RXDESC_SIZE; + + // update drv info + if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) { +// rtl8723s_update_bassn(padapter, pdrvinfo); + ptr += 4; + } + + if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet + { +#ifdef CONFIG_CONCURRENT_MODE + if(rtw_buddy_adapter_up(padapter)) + { + if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS) + { + RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, + ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n")); + } + } + else +#endif + { + if (pattrib->physt) + update_recvframe_phyinfo_88e(precvframe, (struct phy_stat*)ptr); + + if (rtw_recv_entry(precvframe) != _SUCCESS) + { + RT_TRACE(_module_rtl871x_recv_c_,_drv_err_, + ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n")); + } + } + } + else{ // pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP + + //enqueue recvframe to txrtp queue + if(pattrib->pkt_rpt_type == TX_REPORT1){ + DBG_8192C("rx CCX \n"); + } + else if(pattrib->pkt_rpt_type == TX_REPORT2){ + //DBG_8192C("rx TX RPT \n"); + ODM_RA_TxRPT2Handle_8188E( + &pHalData->odmpriv, + precvframe->u.hdr.rx_data, + pattrib->pkt_len, + pattrib->MacIDValidEntry[0], + pattrib->MacIDValidEntry[1] + ); + + } + /* + else if(pattrib->pkt_rpt_type == HIS_REPORT){ + DBG_8192C("rx USB HISR \n"); + }*/ + + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + + } + } + + // Page size of receive package is 128 bytes alignment =>DMA AGG + // refer to _InitTransferPageSize() + pkt_offset = _RND128(pkt_offset); + precvbuf->pdata += pkt_offset; + ptr = precvbuf->pdata; + + } + + dev_kfree_skb_any(precvbuf->pskb); + precvbuf->pskb = NULL; + rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); + + } while (1); + +} +#endif + diff --git a/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_xmit.c b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_xmit.c new file mode 100755 index 00000000..8fe70f10 --- /dev/null +++ b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/rtl8189es_xmit.c @@ -0,0 +1,1691 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#define _RTL8189ES_XMIT_C_ + +#include <drv_conf.h> +#include <osdep_service.h> +#include <drv_types.h> +#include <sdio_ops.h> +#include <rtl8188e_hal.h> + +static void fill_txdesc_sectype(struct pkt_attrib *pattrib, PTXDESC ptxdesc) +{ + if ((pattrib->encrypt > 0) && !pattrib->bswenc) + { + switch (pattrib->encrypt) + { + // SEC_TYPE + case _WEP40_: + case _WEP104_: + case _TKIP_: + case _TKIP_WTMIC_: + ptxdesc->sectype = 1; + break; +#ifdef CONFIG_WAPI_SUPPORT + case _SMS4_: + ptxdesc->sectype = 2; + break; +#endif + case _AES_: + ptxdesc->sectype = 3; + break; + + case _NO_PRIVACY_: + default: + break; + } + } +} + + + static void fill_txdesc_vcs(struct pkt_attrib *pattrib, PTXDESC ptxdesc) +{ + //DBG_8192C("cvs_mode=%d\n", pattrib->vcs_mode); + + switch (pattrib->vcs_mode) + { + case RTS_CTS: + ptxdesc->rtsen = 1; + break; + + case CTS_TO_SELF: + ptxdesc->cts2self = 1; + break; + + case NONE_VCS: + default: + break; + } + + if(pattrib->vcs_mode) { + ptxdesc->hw_rts_en = 1; // ENABLE HW RTS + + // Set RTS BW + if(pattrib->ht_en) + { + if (pattrib->bwmode & HT_CHANNEL_WIDTH_40) + ptxdesc->rts_bw = 1; + + switch (pattrib->ch_offset) + { + case HAL_PRIME_CHNL_OFFSET_DONT_CARE: + ptxdesc->rts_sc = 0; + break; + + case HAL_PRIME_CHNL_OFFSET_LOWER: + ptxdesc->rts_sc = 1; + break; + + case HAL_PRIME_CHNL_OFFSET_UPPER: + ptxdesc->rts_sc = 2; + break; + + default: + ptxdesc->rts_sc = 3; // Duplicate + break; + } + } + } +} + +static void fill_txdesc_phy(struct pkt_attrib *pattrib, PTXDESC ptxdesc) +{ + //DBG_8192C("bwmode=%d, ch_off=%d\n", pattrib->bwmode, pattrib->ch_offset); + + if (pattrib->ht_en) + { + if (pattrib->bwmode & HT_CHANNEL_WIDTH_40) + ptxdesc->data_bw = 1; + + switch (pattrib->ch_offset) + { + case HAL_PRIME_CHNL_OFFSET_DONT_CARE: + ptxdesc->data_sc = 0; + break; + + case HAL_PRIME_CHNL_OFFSET_LOWER: + ptxdesc->data_sc = 1; + break; + + case HAL_PRIME_CHNL_OFFSET_UPPER: + ptxdesc->data_sc = 2; + break; + + default: + ptxdesc->data_sc = 3; // Duplicate + break; + } + } +} + +static void rtl8188e_cal_txdesc_chksum(struct tx_desc *ptxdesc) +{ + u16 *usPtr = (u16*)ptxdesc; + u32 count = 16; // (32 bytes / 2 bytes per XOR) => 16 times + u32 index; + u16 checksum = 0; + + + // Clear first + ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); + + for (index = 0; index < count; index++) { + checksum ^= le16_to_cpu(*(usPtr + index)); + } + + ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff); +} +// +// Description: In normal chip, we should send some packet to Hw which will be used by Fw +// in FW LPS mode. The function is to fill the Tx descriptor of this packets, then +// Fw can tell Hw to send these packet derectly. +// +void rtl8188e_fill_fake_txdesc( + PADAPTER padapter, + u8* pDesc, + u32 BufferLen, + u8 IsPsPoll, + u8 IsBTQosNull) +{ + struct tx_desc *ptxdesc; + + + // Clear all status + ptxdesc = (struct tx_desc*)pDesc; + _rtw_memset(pDesc, 0, TXDESC_SIZE); + + //offset 0 + ptxdesc->txdw0 |= cpu_to_le32( OWN | FSG | LSG); //own, bFirstSeg, bLastSeg; + + ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); //32 bytes for TX Desc + + ptxdesc->txdw0 |= cpu_to_le32(BufferLen&0x0000ffff); // Buffer size + command header + + //offset 4 + ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT<<QSEL_SHT)&0x00001f00); // Fixed queue of Mgnt queue + + //Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. + if (IsPsPoll) + { + ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR); + } + else + { + ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); // Hw set sequence number + ptxdesc->txdw3 |= cpu_to_le32((8 <<28)); //set bit3 to 1. Suugested by TimChen. 2009.12.29. + } + + if (_TRUE == IsBTQosNull) + { + ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); // BT NULL + } + + //offset 16 + ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // USB interface drop packet if the checksum of descriptor isn't correct. + // Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). + rtl8188e_cal_txdesc_chksum(ptxdesc); +#endif +} + + +#define SDIO_TX_AGG_MAX (5) +//#define CONFIG_FIX_CORE_DUMP ==> have bug +//#define DBG_EMINFO + +#if 0 +void rtl8188e_cal_txdesc_chksum(struct tx_desc *ptxdesc) +{ + u16 *usPtr = (u16*)ptxdesc; + u32 count = 16; // (32 bytes / 2 bytes per XOR) => 16 times + u32 index; + u16 checksum = 0; + + + // Clear first + ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); + + for (index = 0; index < count; index++) { + checksum ^= le16_to_cpu(*(usPtr + index)); + } + + ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff); +} + +static void fill_txdesc_sectype(struct pkt_attrib *pattrib, PTXDESC ptxdesc) +{ + if ((pattrib->encrypt > 0) && !pattrib->bswenc) + { + switch (pattrib->encrypt) + { + // SEC_TYPE + case _WEP40_: + case _WEP104_: + case _TKIP_: + case _TKIP_WTMIC_: + ptxdesc->sectype = 1; + break; + + case _AES_: + ptxdesc->sectype = 3; + break; + + case _NO_PRIVACY_: + default: + break; + } + } +} + +static void fill_txdesc_vcs(struct pkt_attrib *pattrib, PTXDESC ptxdesc) +{ + //DBG_8192C("cvs_mode=%d\n", pattrib->vcs_mode); + + switch (pattrib->vcs_mode) + { + case RTS_CTS: + ptxdesc->rtsen = 1; + break; + + case CTS_TO_SELF: + ptxdesc->cts2self = 1; + break; + + case NONE_VCS: + default: + break; + } + + if (pattrib->vcs_mode) + ptxdesc->hw_rts_en = 1; // ENABLE HW RTS +} + +static void fill_txdesc_phy(struct pkt_attrib *pattrib, PTXDESC ptxdesc) +{ + //DBG_8192C("bwmode=%d, ch_off=%d\n", pattrib->bwmode, pattrib->ch_offset); + + if (pattrib->ht_en) + { + if (pattrib->bwmode & HT_CHANNEL_WIDTH_40) + ptxdesc->data_bw = 1; + + switch (pattrib->ch_offset) + { + case HAL_PRIME_CHNL_OFFSET_DONT_CARE: + ptxdesc->data_sc = 0; + break; + + case HAL_PRIME_CHNL_OFFSET_LOWER: + ptxdesc->data_sc = 1; + break; + + case HAL_PRIME_CHNL_OFFSET_UPPER: + ptxdesc->data_sc = 2; + break; + + default: + ptxdesc->data_sc = 3; // Duplicate + break; + } + } +} +#endif + +void rtl8188es_fill_default_txdesc( + struct xmit_frame *pxmitframe, + u8 *pbuf) +{ + PADAPTER padapter; + HAL_DATA_TYPE *pHalData; + struct mlme_ext_priv *pmlmeext; + struct mlme_ext_info *pmlmeinfo; + struct dm_priv *pdmpriv; + struct pkt_attrib *pattrib; + PTXDESC ptxdesc; + s32 bmcst; + + + padapter = pxmitframe->padapter; + pHalData = GET_HAL_DATA(padapter); + //pdmpriv = &pHalData->dmpriv; + pmlmeext = &padapter->mlmeextpriv; + pmlmeinfo = &(pmlmeext->mlmext_info); + + pattrib = &pxmitframe->attrib; + bmcst = IS_MCAST(pattrib->ra); + + ptxdesc = (PTXDESC)pbuf; + +#ifdef CONFIG_CONCURRENT_MODE + if(rtw_buddy_adapter_up(padapter) && padapter->adapter_type > PRIMARY_ADAPTER) + pHalData = GET_HAL_DATA(padapter->pbuddy_adapter); +#endif //CONFIG_CONCURRENT_MODE + + if (pxmitframe->frame_tag == DATA_FRAMETAG) + { + ptxdesc->macid = pattrib->mac_id; // CAM_ID(MAC_ID) + + if (pattrib->ampdu_en == _TRUE) + ptxdesc->agg_en = 1; // AGG EN + else + ptxdesc->bk = 1; // AGG BK + + ptxdesc->qsel = pattrib->qsel; + ptxdesc->rate_id = pattrib->raid; + + fill_txdesc_sectype(pattrib, ptxdesc); + + ptxdesc->seq = pattrib->seqnum; + + //todo: qos_en + + ptxdesc->userate = 1; // driver uses rate + + if ((pattrib->ether_type != 0x888e) && + (pattrib->ether_type != 0x0806) && + (pattrib->dhcp_pkt != 1)) + { + // Non EAP & ARP & DHCP type data packet + + fill_txdesc_vcs(pattrib, ptxdesc); + fill_txdesc_phy(pattrib, ptxdesc); + + ptxdesc->rtsrate = 8; // RTS Rate=24M + ptxdesc->data_ratefb_lmt = 0x1F; + ptxdesc->rts_ratefb_lmt = 0xF; + #if (RATE_ADAPTIVE_SUPPORT == 1) + if(pattrib->ht_en){ + ptxdesc->sgi = ODM_RA_GetShortGI_8188E(&pHalData->odmpriv,pattrib->mac_id); + } + ptxdesc->datarate = ODM_RA_GetDecisionRate_8188E(&pHalData->odmpriv,pattrib->mac_id); + + //for debug + #if 0 + if(padapter->fix_rate!= 0xFF){ + ptxdesc->datarate = padapter->fix_rate; + } + #endif + #if (POWER_TRAINING_ACTIVE==1) + ptxdesc->pwr_status = ODM_RA_GetHwPwrStatus_8188E(&pHalData->odmpriv,pattrib->mac_id); + #endif + #else + ptxdesc->datarate = 0x13; //MCS7 + ptxdesc->sgi = 1; // SGI + if(padapter->fix_rate!= 0xFF){//modify datat by iwpriv + ptxdesc->datarate = padapter->fix_rate; + } + #endif + + + } + else + { + // EAP data packet and ARP and DHCP packet. + // Use the 1M or 6M data rate to send the EAP/ARP packet. + // This will maybe make the handshake smooth. + + ptxdesc->bk = 1; // AGG BK + + if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) + ptxdesc->data_short = 1;// DATA_SHORT + + ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); + } + + ptxdesc->usb_txagg_num = pxmitframe->agg_num; + } + else if (pxmitframe->frame_tag == MGNT_FRAMETAG) + { +// RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("%s: MGNT_FRAMETAG\n", __FUNCTION__)); + + ptxdesc->macid = pattrib->mac_id; // CAM_ID(MAC_ID) + ptxdesc->qsel = pattrib->qsel; + ptxdesc->rate_id = pattrib->raid; // Rate ID + ptxdesc->seq = pattrib->seqnum; + ptxdesc->userate = 1; // driver uses rate, 1M + ptxdesc->rty_lmt_en = 1; // retry limit enable + ptxdesc->data_rt_lmt = 6; // retry limit = 6 + +#ifdef CONFIG_XMIT_ACK + //CCX-TXRPT ack for xmit mgmt frames. + if (pxmitframe->ack_report) { + #ifdef DBG_CCX + static u16 ccx_sw = 0x123; + txdesc_set_ccx_sw_88e(ptxdesc, ccx_sw); + DBG_871X("%s set ccx, sw:0x%03x\n", __func__, ccx_sw); + ccx_sw = (ccx_sw+1)%0xfff; + #endif + ptxdesc->ccx = 1; + } +#endif //CONFIG_XMIT_ACK + +#ifdef CONFIG_INTEL_PROXIM + if((padapter->proximity.proxim_on==_TRUE)&&(pattrib->intel_proxim==_TRUE)){ + DBG_871X("\n %s pattrib->rate=%d\n",__FUNCTION__,pattrib->rate); + ptxdesc->datarate = pattrib->rate; + } + else +#endif + { + ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); + } + } + else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) + { + RT_TRACE(_module_hal_xmit_c_, _drv_warning_, ("%s: TXAGG_FRAMETAG\n", __FUNCTION__)); + } +#ifdef CONFIG_MP_INCLUDED + else if (pxmitframe->frame_tag == MP_FRAMETAG) + { + struct tx_desc *pdesc; + + pdesc = (struct tx_desc*)ptxdesc; + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("%s: MP_FRAMETAG\n", __FUNCTION__)); + fill_txdesc_for_mp(padapter, pdesc); + + pdesc->txdw0 = le32_to_cpu(pdesc->txdw0); + pdesc->txdw1 = le32_to_cpu(pdesc->txdw1); + pdesc->txdw2 = le32_to_cpu(pdesc->txdw2); + pdesc->txdw3 = le32_to_cpu(pdesc->txdw3); + pdesc->txdw4 = le32_to_cpu(pdesc->txdw4); + pdesc->txdw5 = le32_to_cpu(pdesc->txdw5); + pdesc->txdw6 = le32_to_cpu(pdesc->txdw6); + pdesc->txdw7 = le32_to_cpu(pdesc->txdw7); + } +#endif // CONFIG_MP_INCLUDED + else + { + RT_TRACE(_module_hal_xmit_c_, _drv_warning_, ("%s: frame_tag=0x%x\n", __FUNCTION__, pxmitframe->frame_tag)); + + ptxdesc->macid = 4; // CAM_ID(MAC_ID) + ptxdesc->rate_id = 6; // Rate ID + ptxdesc->seq = pattrib->seqnum; + ptxdesc->userate = 1; // driver uses rate + ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); + } + + ptxdesc->pktlen = pattrib->last_txcmdsz; + if (pxmitframe->frame_tag == DATA_FRAMETAG){ + #ifdef CONFIG_TX_EARLY_MODE + ptxdesc->offset = TXDESC_SIZE +EARLY_MODE_INFO_SIZE ; + ptxdesc->pkt_offset = 0x01; + #else + ptxdesc->offset = TXDESC_SIZE ; + ptxdesc->pkt_offset = 0; + #endif + } + else{ + ptxdesc->offset = TXDESC_SIZE ; + } + + if (bmcst) ptxdesc->bmc = 1; + ptxdesc->ls = 1; + ptxdesc->fs = 1; + ptxdesc->own = 1; + + // 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. + // (1) The sequence number of each non-Qos frame / broadcast / multicast / + // mgnt frame should be controled by Hw because Fw will also send null data + // which we cannot control when Fw LPS enable. + // --> default enable non-Qos data sequense number. 2010.06.23. by tynli. + // (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. + // (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. + // 2010.06.23. Added by tynli. + if (!pattrib->qos_en) + { + // Hw set sequence number + ptxdesc->hwseq_en = 1; // HWSEQ_EN + ptxdesc->hwseq_sel = 0; // HWSEQ_SEL + } + +} + +/* + * Description: + * + * Parameters: + * pxmitframe xmitframe + * pbuf where to fill tx desc + */ +void rtl8188es_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf) +{ + struct tx_desc *pdesc; + + + pdesc = (struct tx_desc*)pbuf; + _rtw_memset(pdesc, 0, sizeof(struct tx_desc)); + + rtl8188es_fill_default_txdesc(pxmitframe, pbuf); + + pdesc->txdw0 = cpu_to_le32(pdesc->txdw0); + pdesc->txdw1 = cpu_to_le32(pdesc->txdw1); + pdesc->txdw2 = cpu_to_le32(pdesc->txdw2); + pdesc->txdw3 = cpu_to_le32(pdesc->txdw3); + pdesc->txdw4 = cpu_to_le32(pdesc->txdw4); + pdesc->txdw5 = cpu_to_le32(pdesc->txdw5); + pdesc->txdw6 = cpu_to_le32(pdesc->txdw6); + pdesc->txdw7 = cpu_to_le32(pdesc->txdw7); + + rtl8188e_cal_txdesc_chksum(pdesc); +} + +static inline u32 ffaddr2deviceId(struct dvobj_priv *pdvobj, u32 addr) +{ + return pdvobj->Queue2Pipe[addr]; +} + +#ifdef CONFIG_SDIO_REDUCE_TX_POLLING +static u8 rtl8188es_query_tx_freepage(_adapter *padapter, struct xmit_buf *pxmitbuf) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + u8 TxRequiredPageNum = 0; + u8 DedicatedPgNum = 0; + u8 RequiredPublicFreePgNum = 0; + u8 PageIdx = 0; + u8 CheckStep = 0; + u8 bResult = _TRUE; + u8 bUpdatePageNum = _FALSE; + u32 deviceId; + + + TxRequiredPageNum = pxmitbuf->pg_num; + + deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr); + + // translate fifo addr to queue index + switch (deviceId) { + case WLAN_TX_HIQ_DEVICE_ID: + PageIdx = HI_QUEUE_IDX; + break; + + case WLAN_TX_MIQ_DEVICE_ID: + PageIdx = MID_QUEUE_IDX; + break; + + case WLAN_TX_LOQ_DEVICE_ID: + PageIdx = LOW_QUEUE_IDX; + break; + } + + do { + if ((padapter->bSurpriseRemoved == _TRUE) || (padapter->bDriverStopped == _TRUE)){ + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, + ("%s: bSurpriseRemoved(update TX FIFO page)\n", __FUNCTION__)); + break; + } + + // The number of page which public page is included is available . + if ((pHalData->SdioTxFIFOFreePage[PageIdx]+pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]) > (TxRequiredPageNum+1)) { + DedicatedPgNum = pHalData->SdioTxFIFOFreePage[PageIdx]; + if (TxRequiredPageNum <= DedicatedPgNum) { + pHalData->SdioTxFIFOFreePage[PageIdx] -= TxRequiredPageNum; + break; + } else { + pHalData->SdioTxFIFOFreePage[PageIdx] = 0; + RequiredPublicFreePgNum = TxRequiredPageNum - DedicatedPgNum; + pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= RequiredPublicFreePgNum; + break; + } + } else { // Total number of page is NOT available, so update current FIFO status. + if (!bUpdatePageNum) { + bResult = HalQueryTxBufferStatus8189ESdio(padapter); // Set to default value. + bUpdatePageNum = _TRUE; + } else { + bResult = _FALSE; + } + } + }while(++CheckStep < 2); // step1: user page variables, step2: physical page number + + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("%s(): HIQ(%#x), MIQ(%#x), LOQ(%#x), PUBQ(%#x)\n", + __FUNCTION__, + pHalData->SdioTxFIFOFreePage[HI_QUEUE_IDX], + pHalData->SdioTxFIFOFreePage[MID_QUEUE_IDX], + pHalData->SdioTxFIFOFreePage[LOW_QUEUE_IDX], + pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX])); + + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("%s(): TxRequiredPageNum(%d) is available to send?(%d)\n", + __FUNCTION__, TxRequiredPageNum, bResult)); + + return bResult; +} +#else +static u8 rtl8188es_query_tx_freepage(_adapter *padapter, struct xmit_buf *pxmitbuf) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + u8 TxRequiredPageNum = 0; + u8 DedicatedPgNum = 0; + u8 RequiredPublicFreePgNum = 0; + u8 PageIdx = 0; + u8 bResult = _TRUE; + u32 n, deviceId; + + TxRequiredPageNum = pxmitbuf->pg_num; + + deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr); + + // translate fifo addr to queue index + switch (deviceId) { + case WLAN_TX_HIQ_DEVICE_ID: + PageIdx = HI_QUEUE_IDX; + break; + + case WLAN_TX_MIQ_DEVICE_ID: + PageIdx = MID_QUEUE_IDX; + break; + + case WLAN_TX_LOQ_DEVICE_ID: + PageIdx = LOW_QUEUE_IDX; + break; + } + + // check if hardware tx fifo page is enough + n = 0; + do { + if ((padapter->bSurpriseRemoved == _TRUE) || (padapter->bDriverStopped == _TRUE)){ + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, + ("%s: bSurpriseRemoved(update TX FIFO page)\n", __FUNCTION__)); + break; + } + + // The number of page which public page is included is available . + if ((pHalData->SdioTxFIFOFreePage[PageIdx]+pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]) > (TxRequiredPageNum+1)) { + DedicatedPgNum = pHalData->SdioTxFIFOFreePage[PageIdx]; + if (TxRequiredPageNum <= DedicatedPgNum) { + pHalData->SdioTxFIFOFreePage[PageIdx] -= TxRequiredPageNum; + break; + } else { + pHalData->SdioTxFIFOFreePage[PageIdx] = 0; + RequiredPublicFreePgNum = TxRequiredPageNum - DedicatedPgNum; + pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= RequiredPublicFreePgNum; + break; + } + } + + n++; + if ((n % 60) == 0) {//or 80 + //DBG_871X("%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n", + // __func__, n, pxmitbuf->len, pxmitbuf->agg_num, pframe->pg_num, freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]); + rtw_msleep_os(10); + rtw_yield_os(); + } + + // Total number of page is NOT available, so update current FIFO status + HalQueryTxBufferStatus8189ESdio(padapter); + } while (1); + + return bResult; +} +#endif + +//todo: static +s32 rtl8188es_dequeue_writeport(PADAPTER padapter, u8 *freePage) +{ + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct xmit_buf *pxmitbuf; + PADAPTER pri_padapter = padapter; + s32 ret = 0; + +#ifdef CONFIG_CONCURRENT_MODE + if (padapter->adapter_type > 0) + pri_padapter = padapter->pbuddy_adapter; + + if(rtw_buddy_adapter_up(padapter)) + ret = check_buddy_fwstate( padapter, _FW_UNDER_SURVEY); +#endif + + ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY); + + if (_TRUE == ret) + pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv); + else + pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv); + + if (pxmitbuf == NULL) + return _TRUE; + +query_free_page: + // check if hardware tx fifo page is enough + if( _FALSE == rtl8188es_query_tx_freepage(pri_padapter, pxmitbuf)) + { + rtw_msleep_os(1); + goto query_free_page; + } + + if ((padapter->bSurpriseRemoved == _TRUE) + || (padapter->bDriverStopped == _TRUE) +#ifdef CONFIG_CONCURRENT_MODE + ||((padapter->pbuddy_adapter) + && ((padapter->pbuddy_adapter->bSurpriseRemoved) ||(padapter->pbuddy_adapter->bDriverStopped))) +#endif + ){ + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, + ("%s: bSurpriseRemoved(wirte port)\n", __FUNCTION__)); + goto free_xmitbuf; + } + + rtw_write_port(padapter, ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr), pxmitbuf->len, (u8 *)pxmitbuf); + +free_xmitbuf: + //rtw_free_xmitframe(pxmitpriv, pframe); + //pxmitbuf->priv_data = NULL; + rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + +#ifdef CONFIG_SDIO_TX_TASKLET + tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); +#endif + + return _FAIL; +} + +/* + * Description + * Transmit xmitbuf to hardware tx fifo + * + * Return + * _SUCCESS ok + * _FAIL something error + */ +s32 rtl8188es_xmit_buf_handler(PADAPTER padapter) +{ + struct mlme_priv *pmlmepriv; + struct xmit_priv *pxmitpriv; + struct xmit_buf *pxmitbuf; + struct xmit_frame *pframe; + u8 *freePage; + u32 requiredPage; + u8 PageIdx , queue_empty; + _irqL irql; + u32 n; + s32 ret; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); +#ifdef CONFIG_CONCURRENT_MODE + s32 buddy_rm_stop = _FAIL; +#endif + + pmlmepriv = &padapter->mlmepriv; + pxmitpriv = &padapter->xmitpriv; + freePage = pHalData->SdioTxFIFOFreePage; + + ret = _rtw_down_sema(&pxmitpriv->xmit_sema); + if (ret == _FAIL) { + RT_TRACE(_module_hal_xmit_c_, _drv_emerg_, ("down SdioXmitBufSema fail!\n")); + return _FAIL; + } + +//#ifdef CONFIG_CONCURRENT_MODE +// if (padapter->pbuddy_adapter->bup){ +// if ((padapter->pbuddy_adapter->bSurpriseRemoved == _TRUE) || +// (padapter->pbuddy_adapter->bDriverStopped == _TRUE)) +// buddy_rm_stop = _TRUE; +// } +//#endif + if ((padapter->bSurpriseRemoved == _TRUE) || + (padapter->bDriverStopped == _TRUE) +//#ifdef CONFIG_CONCURRENT_MODE +// ||(buddy_rm_stop == _TRUE) +//#endif + ) { + +#ifdef CONFIG_LPS_LCLK + rtw_unregister_tx_alive(padapter); +#endif + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, + ("%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n", + __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved)); + return _FAIL; + } + +#ifdef CONFIG_LPS_LCLK + ret = rtw_register_tx_alive(padapter); + if (ret != _SUCCESS) return _SUCCESS; +#endif + + do { + queue_empty = rtl8188es_dequeue_writeport(padapter, freePage); +// dump secondary adapter xmitbuf +#ifdef CONFIG_CONCURRENT_MODE + if(rtw_buddy_adapter_up(padapter)) + queue_empty &= rtl8188es_dequeue_writeport(padapter->pbuddy_adapter, freePage); +#endif + + } while ( !queue_empty); + +#ifdef CONFIG_LPS_LCLK + rtw_unregister_tx_alive(padapter); +#endif + return _SUCCESS; +} + +#if 0 +/* + * Description: + * Aggregation packets and send to hardware + * + * Return: + * 0 Success + * -1 Hardware resource(TX FIFO) not ready + * -2 Software resource(xmitbuf) not ready + */ +#ifdef CONFIG_TX_EARLY_MODE +#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1 + #define EARLY_MODE_MAX_PKT_NUM 10 +#else + #define EARLY_MODE_MAX_PKT_NUM 5 +#endif + + +struct EMInfo{ + u8 EMPktNum; + u16 EMPktLen[EARLY_MODE_MAX_PKT_NUM]; +}; + + +void +InsertEMContent_8188E( + struct EMInfo *pEMInfo, + IN pu1Byte VirtualAddress) +{ + +#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1 + u1Byte index=0; + u4Byte dwtmp=0; +#endif + + _rtw_memset(VirtualAddress, 0, EARLY_MODE_INFO_SIZE); + if(pEMInfo->EMPktNum==0) + return; + + #ifdef DBG_EMINFO + { + int i; + DBG_8192C("\n%s ==> pEMInfo->EMPktNum =%d\n",__FUNCTION__,pEMInfo->EMPktNum); + for(i=0;i< EARLY_MODE_MAX_PKT_NUM;i++){ + DBG_8192C("%s ==> pEMInfo->EMPktLen[%d] =%d\n",__FUNCTION__,i,pEMInfo->EMPktLen[i]); + } + + } + #endif + +#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1 + SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum); + + if(pEMInfo->EMPktNum == 1){ + dwtmp = pEMInfo->EMPktLen[0]; + }else{ + dwtmp = pEMInfo->EMPktLen[0]; + dwtmp += ((dwtmp%4)?(4-dwtmp%4):0)+4; + dwtmp += pEMInfo->EMPktLen[1]; + } + SET_EARLYMODE_LEN0(VirtualAddress, dwtmp); + if(pEMInfo->EMPktNum <= 3){ + dwtmp = pEMInfo->EMPktLen[2]; + }else{ + dwtmp = pEMInfo->EMPktLen[2]; + dwtmp += ((dwtmp%4)?(4-dwtmp%4):0)+4; + dwtmp += pEMInfo->EMPktLen[3]; + } + SET_EARLYMODE_LEN1(VirtualAddress, dwtmp); + if(pEMInfo->EMPktNum <= 5){ + dwtmp = pEMInfo->EMPktLen[4]; + }else{ + dwtmp = pEMInfo->EMPktLen[4]; + dwtmp += ((dwtmp%4)?(4-dwtmp%4):0)+4; + dwtmp += pEMInfo->EMPktLen[5]; + } + SET_EARLYMODE_LEN2_1(VirtualAddress, dwtmp&0xF); + SET_EARLYMODE_LEN2_2(VirtualAddress, dwtmp>>4); + if(pEMInfo->EMPktNum <= 7){ + dwtmp = pEMInfo->EMPktLen[6]; + }else{ + dwtmp = pEMInfo->EMPktLen[6]; + dwtmp += ((dwtmp%4)?(4-dwtmp%4):0)+4; + dwtmp += pEMInfo->EMPktLen[7]; + } + SET_EARLYMODE_LEN3(VirtualAddress, dwtmp); + if(pEMInfo->EMPktNum <= 9){ + dwtmp = pEMInfo->EMPktLen[8]; + }else{ + dwtmp = pEMInfo->EMPktLen[8]; + dwtmp += ((dwtmp%4)?(4-dwtmp%4):0)+4; + dwtmp += pEMInfo->EMPktLen[9]; + } + SET_EARLYMODE_LEN4(VirtualAddress, dwtmp); +#else + SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum); + SET_EARLYMODE_LEN0(VirtualAddress, pEMInfo->EMPktLen[0]); + SET_EARLYMODE_LEN1(VirtualAddress, pEMInfo->EMPktLen[1]); + SET_EARLYMODE_LEN2_1(VirtualAddress, pEMInfo->EMPktLen[2]&0xF); + SET_EARLYMODE_LEN2_2(VirtualAddress, pEMInfo->EMPktLen[2]>>4); + SET_EARLYMODE_LEN3(VirtualAddress, pEMInfo->EMPktLen[3]); + SET_EARLYMODE_LEN4(VirtualAddress, pEMInfo->EMPktLen[4]); +#endif + //RT_PRINT_DATA(COMP_SEND, DBG_LOUD, "EMHdr:", VirtualAddress, 8); + +} + + + +void UpdateEarlyModeInfo8188E(struct xmit_priv *pxmitpriv,struct xmit_buf *pxmitbuf ) +{ + //_adapter *padapter, struct xmit_frame *pxmitframe,struct tx_servq *ptxservq + int index,j; + u16 offset,pktlen; + PTXDESC ptxdesc; + + u8 *pmem,*pEMInfo_mem; + s8 node_num_0=0,node_num_1=0; + struct EMInfo eminfo; + struct agg_pkt_info *paggpkt; + struct xmit_frame *pframe = (struct xmit_frame*)pxmitbuf->priv_data; + pmem= pframe->buf_addr; + + #ifdef DBG_EMINFO + DBG_8192C("\n%s ==> agg_num:%d\n",__FUNCTION__, pframe->agg_num); + for(index=0;index<pframe->agg_num;index++){ + offset = pxmitpriv->agg_pkt[index].offset; + pktlen = pxmitpriv->agg_pkt[index].pkt_len; + DBG_8192C("%s ==> agg_pkt[%d].offset=%d\n",__FUNCTION__,index,offset); + DBG_8192C("%s ==> agg_pkt[%d].pkt_len=%d\n",__FUNCTION__,index,pktlen); + } + #endif + + if( pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) + { + node_num_0 = pframe->agg_num; + node_num_1= EARLY_MODE_MAX_PKT_NUM-1; + } + + for(index=0;index<pframe->agg_num;index++){ + offset = pxmitpriv->agg_pkt[index].offset; + pktlen = pxmitpriv->agg_pkt[index].pkt_len; + + _rtw_memset(&eminfo,0,sizeof(struct EMInfo)); + if( pframe->agg_num > EARLY_MODE_MAX_PKT_NUM){ + if(node_num_0 > EARLY_MODE_MAX_PKT_NUM){ + eminfo.EMPktNum = EARLY_MODE_MAX_PKT_NUM; + node_num_0--; + } + else{ + eminfo.EMPktNum = node_num_1; + node_num_1--; + } + } + else{ + eminfo.EMPktNum = pframe->agg_num-(index+1); + } + for(j=0;j< eminfo.EMPktNum ;j++){ + eminfo.EMPktLen[j] = pxmitpriv->agg_pkt[index+1+j].pkt_len+4;//CRC + } + + if(pmem){ + ptxdesc = (PTXDESC)(pmem+offset); + pEMInfo_mem = pmem+offset+TXDESC_SIZE; + #ifdef DBG_EMINFO + DBG_8192C("%s ==> desc.pkt_len=%d\n",__FUNCTION__,ptxdesc->pktlen); + #endif + InsertEMContent_8188E(&eminfo,pEMInfo_mem); + } + + + } + _rtw_memset(pxmitpriv->agg_pkt,0,sizeof(struct agg_pkt_info)*MAX_AGG_PKT_NUM); + +} +#endif + +#endif + +#ifdef CONFIG_SDIO_TX_TASKLET +static s32 xmit_xmitframes(PADAPTER padapter, struct xmit_priv *pxmitpriv) +{ + s32 ret; + _irqL irqL; + struct xmit_buf *pxmitbuf; + struct hw_xmit *phwxmit = pxmitpriv->hwxmits; + struct tx_servq *ptxservq = NULL; + _list *xmitframe_plist = NULL, *xmitframe_phead = NULL; + struct xmit_frame *pxmitframe = NULL, *pfirstframe = NULL; + u32 pbuf = 0; // next pkt address + u32 pbuf_tail = 0; // last pkt tail + u32 txlen = 0; //packet length, except TXDESC_SIZE and PKT_OFFSET + u32 total_len = 0; + u8 ac_index = 0; + u8 bfirst = _TRUE;//first aggregation xmitframe + u8 bulkstart = _FALSE; +#ifdef CONFIG_TX_EARLY_MODE + u8 pkt_index=0; +#endif + + pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); + if (pxmitbuf == NULL) { + RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: xmit_buf is not enough!\n", __FUNCTION__)); + return _FALSE; + } + + do { + //3 1. pick up first frame + if(bfirst) + { + pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); + if (pxmitframe == NULL) { + // no more xmit frame, release xmit buffer + rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + return _FALSE; + } + + pxmitframe->pxmitbuf = pxmitbuf; + pxmitframe->buf_addr = pxmitbuf->pbuf; + pxmitbuf->priv_data = pxmitframe; + pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe); + + pfirstframe = pxmitframe; + + _enter_critical_bh(&pxmitpriv->lock, &irqL); + ptxservq = rtw_get_sta_pending(padapter, pfirstframe->attrib.psta, pfirstframe->attrib.priority, (u8 *)(&ac_index)); + _exit_critical_bh(&pxmitpriv->lock, &irqL); + } + //3 2. aggregate same priority and same DA(AP or STA) frames + else + { + // dequeue same priority packet from station tx queue + _enter_critical_bh(&pxmitpriv->lock, &irqL); + + if (_rtw_queue_empty(&ptxservq->sta_pending) == _FALSE) + { + xmitframe_phead = get_list_head(&ptxservq->sta_pending); + xmitframe_plist = get_next(xmitframe_phead); + + pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); + + // check xmit_buf size enough or not + txlen = TXDESC_SIZE + + #ifdef CONFIG_TX_EARLY_MODE + EARLY_MODE_INFO_SIZE + + #endif + rtw_wlan_pkt_size(pxmitframe); + + if (pbuf + _RND8(txlen) > MAX_XMITBUF_SZ) + { + bulkstart = _TRUE; + } + else + { + rtw_list_delete(&pxmitframe->list); + ptxservq->qcnt--; + phwxmit[ac_index].accnt--; + + //Remove sta node when there is no pending packets. + if (_rtw_queue_empty(&ptxservq->sta_pending) == _TRUE) + rtw_list_delete(&ptxservq->tx_pending); + } + } + else + { + bulkstart = _TRUE; + } + + _exit_critical_bh(&pxmitpriv->lock, &irqL); + + if(bulkstart) + { + break; + } + + pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf; + + pxmitframe->agg_num = 0; // not first frame of aggregation + } + + ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); + if (ret == _FAIL) { + DBG_871X("%s: coalesce FAIL!", __FUNCTION__); + rtw_free_xmitframe(pxmitpriv, pxmitframe); + continue; + } + + // always return ndis_packet after rtw_xmitframe_coalesce + //rtw_os_xmit_complete(padapter, pxmitframe); + +#ifdef CONFIG_TX_EARLY_MODE + pxmitpriv->agg_pkt[pkt_index].pkt_len = pxmitframe->attrib.last_txcmdsz; //get from rtw_xmitframe_coalesce + pxmitpriv->agg_pkt[pkt_index].offset = _RND8(pxmitframe->attrib.last_txcmdsz+ TXDESC_SIZE+EARLY_MODE_INFO_SIZE); + pkt_index++; +#endif + + if(bfirst) + { + txlen = TXDESC_SIZE + + #ifdef CONFIG_TX_EARLY_MODE + EARLY_MODE_INFO_SIZE + + #endif + pxmitframe->attrib.last_txcmdsz; + + total_len = txlen; + + pxmitframe->pg_num = (txlen + 127)/128; + pxmitbuf->pg_num = (txlen + 127)/128; + pbuf_tail = txlen; + pbuf = _RND8(pbuf_tail); + bfirst = _FALSE; + } + else + { + rtl8188es_update_txdesc(pxmitframe, pxmitframe->buf_addr); + + // don't need xmitframe any more + rtw_free_xmitframe(pxmitpriv, pxmitframe); + + pxmitframe->pg_num = (txlen + 127)/128; + //pfirstframe->pg_num += pxmitframe->pg_num; + pxmitbuf->pg_num += (txlen + 127)/128; + + total_len += txlen; + + // handle pointer and stop condition + pbuf_tail = pbuf + txlen; + pbuf = _RND8(pbuf_tail); + + pfirstframe->agg_num++; + #ifdef SDIO_TX_AGG_MAX + if(pfirstframe->agg_num >= SDIO_TX_AGG_MAX) + break; + #endif + } + }while(1); + + //3 3. update first frame txdesc + rtl8188es_update_txdesc(pfirstframe, pfirstframe->buf_addr); +#ifdef CONFIG_TX_EARLY_MODE + UpdateEarlyModeInfo8188E(pxmitpriv,pxmitbuf ); +#endif + + // + pxmitbuf->agg_num = pfirstframe->agg_num; + pxmitbuf->priv_data = NULL; + + //3 4. write xmit buffer to USB FIFO + pxmitbuf->len = pbuf_tail; + enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf); + + //3 5. update statisitc + rtw_count_tx_stats(padapter, pfirstframe, total_len); + + rtw_free_xmitframe(pxmitpriv, pfirstframe); + + //rtw_yield_os(); + + return _TRUE; +} + +void rtl8188es_xmit_tasklet(void *priv) +{ + int ret = _FALSE; + _adapter *padapter = (_adapter*)priv; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + + while(1) + { + if ((padapter->bDriverStopped == _TRUE)||(padapter->bSurpriseRemoved== _TRUE) || (padapter->bWritePortCancel == _TRUE)) + { + DBG_871X("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n"); + break; + } + + ret = xmit_xmitframes(padapter, pxmitpriv); + if(ret==_FALSE) + break; + + } +} +#else +static s32 xmit_xmitframes(PADAPTER padapter, struct xmit_priv *pxmitpriv) +{ + u32 err, agg_num=0; + u8 pkt_index=0; + struct hw_xmit *hwxmits, *phwxmit; + u8 idx, hwentry; + _irqL irql; + struct tx_servq *ptxservq; + _list *sta_plist, *sta_phead, *frame_plist, *frame_phead; + struct xmit_frame *pxmitframe; + _queue *pframe_queue; + struct xmit_buf *pxmitbuf; + u32 txlen; + s32 ret; + int inx[4]; + + + err = 0; + hwxmits = pxmitpriv->hwxmits; + hwentry = pxmitpriv->hwxmit_entry; + ptxservq = NULL; + pxmitframe = NULL; + pframe_queue = NULL; + pxmitbuf = NULL; + + if (padapter->registrypriv.wifi_spec == 1) { + for(idx=0; idx<4; idx++) + inx[idx] = pxmitpriv->wmm_para_seq[idx]; + } else { + inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; + } + + // 0(VO), 1(VI), 2(BE), 3(BK) + for (idx = 0; idx < hwentry; idx++) + { + phwxmit = hwxmits + inx[idx]; + +// _enter_critical(&hwxmits->sta_queue->lock, &irqL0); + _enter_critical_bh(&pxmitpriv->lock, &irql); + + sta_phead = get_list_head(phwxmit->sta_queue); + sta_plist = get_next(sta_phead); + + while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE) + { + ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending); + + sta_plist = get_next(sta_plist); + + pframe_queue = &ptxservq->sta_pending; + +// _enter_critical(&pframe_queue->lock, &irqL1); + //_enter_critical_bh(&pxmitpriv->lock, &irql); + + frame_phead = get_list_head(pframe_queue); + frame_plist = get_next(frame_phead); + + while (rtw_end_of_queue_search(frame_phead, frame_plist) == _FALSE) + { + pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list); + // check xmit_buf size enough or not + #ifdef CONFIG_TX_EARLY_MODE + txlen = TXDESC_SIZE +EARLY_MODE_INFO_SIZE+ rtw_wlan_pkt_size(pxmitframe); + #else + txlen = TXDESC_SIZE + rtw_wlan_pkt_size(pxmitframe); + #endif + if ((NULL == pxmitbuf) || + ((pxmitbuf->ptail + txlen) > pxmitbuf->pend) + #ifdef SDIO_TX_AGG_MAX + || (agg_num>= SDIO_TX_AGG_MAX) + #endif + ) + { + if (pxmitbuf) { + struct xmit_frame *pframe; + pframe = (struct xmit_frame*)pxmitbuf->priv_data; + pframe->agg_num = agg_num; + pxmitbuf->agg_num = agg_num; + //DBG_8192C("==> agg_num:%d\n",agg_num); + rtl8188es_update_txdesc(pframe, pframe->buf_addr); + #ifdef CONFIG_TX_EARLY_MODE + UpdateEarlyModeInfo8188E(pxmitpriv, pxmitbuf); + #endif + rtw_free_xmitframe(pxmitpriv, pframe); + pxmitbuf->priv_data = NULL; + enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf); + //rtw_yield_os(); + } + + pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); + if (pxmitbuf == NULL) { + RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: xmit_buf is not enough!\n", __FUNCTION__)); + err = -2; + break; + } + agg_num = 0; + pkt_index =0; + } + + // ok to send, remove frame from queue + + + frame_plist = get_next(frame_plist); + rtw_list_delete(&pxmitframe->list); + ptxservq->qcnt--; + phwxmit->accnt--; + + + if (agg_num == 0) { + pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe); + pxmitbuf->priv_data = (u8*)pxmitframe; + } + + // coalesce the xmitframe to xmitbuf + pxmitframe->pxmitbuf = pxmitbuf; + pxmitframe->buf_addr = pxmitbuf->ptail; + + ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); + if (ret == _FAIL) { + RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: coalesce FAIL!", __FUNCTION__)); + // Todo: error handler + rtw_free_xmitframe(pxmitpriv, pxmitframe); + } else { + agg_num++; + if (agg_num != 1) + rtl8188es_update_txdesc(pxmitframe, pxmitframe->buf_addr); + rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz); + #ifdef CONFIG_TX_EARLY_MODE + txlen = TXDESC_SIZE+ EARLY_MODE_INFO_SIZE+ pxmitframe->attrib.last_txcmdsz; + #else + txlen = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz; + #endif + pxmitframe->pg_num = (txlen + 127)/128; + pxmitbuf->pg_num += (txlen + 127)/128; + //if (agg_num != 1) + //((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; + + #ifdef CONFIG_TX_EARLY_MODE + pxmitpriv->agg_pkt[pkt_index].pkt_len = pxmitframe->attrib.last_txcmdsz; //get from rtw_xmitframe_coalesce + pxmitpriv->agg_pkt[pkt_index].offset = _RND8(pxmitframe->attrib.last_txcmdsz+ TXDESC_SIZE+EARLY_MODE_INFO_SIZE); + #endif + + pkt_index++; + pxmitbuf->ptail += _RND(txlen, 8); // round to 8 bytes alignment + pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen; + } + + if (agg_num != 1) + rtw_free_xmitframe(pxmitpriv, pxmitframe); + pxmitframe = NULL; + } + + if (_rtw_queue_empty(pframe_queue)) { + rtw_list_delete(&ptxservq->tx_pending); + } + +// _exit_critical(&pframe_queue->lock, &irqL1); + //_exit_critical_bh(&pxmitpriv->lock, &irql); + + } + +// _exit_critical(&hwxmits->sta_queue->lock, &irqL0); + _exit_critical_bh(&pxmitpriv->lock, &irql); + + // dump xmit_buf to hw tx fifo + if (pxmitbuf) + { + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("pxmitbuf->len=%d enqueue\n",pxmitbuf->len)); + + if (pxmitbuf->len > 0) { + struct xmit_frame *pframe; + pframe = (struct xmit_frame*)pxmitbuf->priv_data; + pframe->agg_num = agg_num; + pxmitbuf->agg_num = agg_num; + rtl8188es_update_txdesc(pframe, pframe->buf_addr); + #ifdef CONFIG_TX_EARLY_MODE + UpdateEarlyModeInfo8188E(pxmitpriv,pxmitbuf ); + #endif + rtw_free_xmitframe(pxmitpriv, pframe); + pxmitbuf->priv_data = NULL; + enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf); + rtw_yield_os(); + } + else + rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + + pxmitbuf = NULL; + + } + + } + + return err; + +} + +/* + * Description + * Transmit xmitframe from queue + * + * Return + * _SUCCESS ok + * _FAIL something error + */ +s32 rtl8188es_xmit_handler(PADAPTER padapter) +{ + struct xmit_priv *pxmitpriv = &padapter->xmitpriv ; + s32 ret; + _irqL irql; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); +//#ifdef CONFIG_CONCURRENT_MODE +// s32 buddy_rm_stop = _FAIL; +//#endif + + +wait: + ret = _rtw_down_sema(&pHalData->SdioXmitSema); + if (_FAIL == ret) { + RT_TRACE(_module_hal_xmit_c_, _drv_emerg_, ("%s: down sema fail!\n", __FUNCTION__)); + return _FAIL; + } + +next: +//#ifdef CONFIG_CONCURRENT_MODE +// if (padapter->pbuddy_adapter){ +// if ((padapter->pbuddy_adapter->bSurpriseRemoved == _TRUE) || +// (padapter->pbuddy_adapter->bDriverStopped == _TRUE)) +// buddy_rm_stop = _TRUE; +// } +//#endif + if ((padapter->bSurpriseRemoved == _TRUE) || + (padapter->bDriverStopped == _TRUE) +//#ifdef CONFIG_CONCURRENT_MODE +// ||(buddy_rm_stop == _TRUE) +//#endif + ) { + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, + ("%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n", + __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved)); + return _FAIL; + } + _enter_critical_bh(&pxmitpriv->lock, &irql); + ret = rtw_txframes_pending(padapter); + _exit_critical_bh(&pxmitpriv->lock, &irql); + if (ret == 0) { + return _SUCCESS; + } + // dequeue frame and write to hardware + + ret = xmit_xmitframes(padapter, pxmitpriv); + if (ret == -2) { + rtw_msleep_os(1); + goto next; + } + _enter_critical_bh(&pxmitpriv->lock, &irql); + ret = rtw_txframes_pending(padapter); + _exit_critical_bh(&pxmitpriv->lock, &irql); + if (ret == 1) { + rtw_msleep_os(1); + goto next; + } + + return _SUCCESS; +} + +thread_return rtl8188es_xmit_thread(thread_context context) +{ + s32 ret; + PADAPTER padapter= (PADAPTER)context; + struct xmit_priv *pxmitpriv= &padapter->xmitpriv; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + ret = _SUCCESS; + + thread_enter("RTWHALXT"); + + DBG_871X("start %s\n", __FUNCTION__); + + do { + ret = rtl8188es_xmit_handler(padapter); + if (signal_pending(current)) { + flush_signals(current); + } + } while (_SUCCESS == ret); + + _rtw_up_sema(&pHalData->SdioXmitTerminateSema); + + RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("-%s\n", __FUNCTION__)); + DBG_871X("exit %s\n", __FUNCTION__); + + thread_exit(); +} +#endif + +#ifdef CONFIG_IOL_IOREG_CFG_DBG +#include <rtw_iol.h> +#endif +s32 rtl8188es_mgnt_xmit(PADAPTER padapter, struct xmit_frame *pmgntframe) +{ + s32 ret = _SUCCESS; + struct pkt_attrib *pattrib; + struct xmit_buf *pxmitbuf; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; + u8 pattrib_subtype; + + RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("+%s\n", __FUNCTION__)); + + pattrib = &pmgntframe->attrib; + pxmitbuf = pmgntframe->pxmitbuf; + + rtl8188es_update_txdesc(pmgntframe, pmgntframe->buf_addr); + + pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz; + //pmgntframe->pg_num = (pxmitbuf->len + 127)/128; // 128 is tx page size + pxmitbuf->pg_num = (pxmitbuf->len + 127)/128; // 128 is tx page size + pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len; + pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe); + + rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz); + pattrib_subtype = pattrib->subtype; + rtw_free_xmitframe(pxmitpriv, pmgntframe); + + pxmitbuf->priv_data = NULL; + + if((pattrib_subtype == WIFI_BEACON) || (GetFrameSubType(pframe)==WIFI_BEACON)) //dump beacon directly + { +#ifdef CONFIG_IOL_IOREG_CFG_DBG + rtw_IOL_cmd_buf_dump(padapter,pxmitbuf->len,pxmitbuf->pdata); +#endif + + rtw_write_port(padapter, ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr), pxmitbuf->len, (u8 *)pxmitbuf); + + //rtw_free_xmitframe(pxmitpriv, pmgntframe); + + //pxmitbuf->priv_data = NULL; + + rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + } + else + { + enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf); + } + + if (ret != _SUCCESS) + rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN); + + return ret; +} + +/* + * Description: + * Handle xmitframe(packet) come from rtw_xmit() + * + * Return: + * _TRUE dump packet directly ok + * _FALSE enqueue, temporary can't transmit packets to hardware + */ +s32 rtl8188es_hal_xmit(PADAPTER padapter, struct xmit_frame *pxmitframe) +{ + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + _irqL irql; + s32 err; + + //pxmitframe->attrib.qsel = pxmitframe->attrib.priority; + +#ifdef CONFIG_80211N_HT + if ((pxmitframe->frame_tag == DATA_FRAMETAG) && + (pxmitframe->attrib.ether_type != 0x0806) && + (pxmitframe->attrib.ether_type != 0x888e) && + (pxmitframe->attrib.dhcp_pkt != 1)) + { + if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE) + rtw_issue_addbareq_cmd(padapter, pxmitframe); + } +#endif + + _enter_critical_bh(&pxmitpriv->lock, &irql); + err = rtw_xmitframe_enqueue(padapter, pxmitframe); + _exit_critical_bh(&pxmitpriv->lock, &irql); + if (err != _SUCCESS) { + RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: enqueue xmitframe fail\n",__FUNCTION__)); + rtw_free_xmitframe(pxmitpriv, pxmitframe); + + // Trick, make the statistics correct + pxmitpriv->tx_pkts--; + pxmitpriv->tx_drop++; + return _TRUE; + } + +#ifdef CONFIG_SDIO_TX_TASKLET + tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); +#else + _rtw_up_sema(&pHalData->SdioXmitSema); +#endif + + return _FALSE; +} + +s32 rtl8188es_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe) +{ + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + s32 err; + + if ((err=rtw_xmitframe_enqueue(padapter, pxmitframe)) != _SUCCESS) + { + rtw_free_xmitframe(pxmitpriv, pxmitframe); + + // Trick, make the statistics correct + pxmitpriv->tx_pkts--; + pxmitpriv->tx_drop++; + } + else + { +#ifdef CONFIG_SDIO_TX_TASKLET + tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); +#else + _rtw_up_sema(&pHalData->SdioXmitSema); +#endif + } + + return err; + +} + + +/* + * Return + * _SUCCESS start thread ok + * _FAIL start thread fail + * + */ +s32 rtl8188es_init_xmit_priv(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + +#ifdef CONFIG_SDIO_TX_TASKLET +#ifdef PLATFORM_LINUX + tasklet_init(&pxmitpriv->xmit_tasklet, + (void(*)(unsigned long))rtl8188es_xmit_tasklet, + (unsigned long)padapter); +#endif +#else //CONFIG_SDIO_TX_TASKLET + + _rtw_init_sema(&pHalData->SdioXmitSema, 0); + _rtw_init_sema(&pHalData->SdioXmitTerminateSema, 0); +#endif //CONFIG_SDIO_TX_TASKLET + + _rtw_spinlock_init(&pHalData->SdioTxFIFOFreePageLock); + +#ifdef CONFIG_TX_EARLY_MODE + pHalData->bEarlyModeEnable = padapter->registrypriv.early_mode; +#endif + + return _SUCCESS; +} + +void rtl8188es_free_xmit_priv(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + _rtw_spinlock_free(&pHalData->SdioTxFIFOFreePageLock); +} + diff --git a/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/sdio_halinit.c b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/sdio_halinit.c new file mode 100755 index 00000000..4a607a59 --- /dev/null +++ b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/sdio_halinit.c @@ -0,0 +1,4179 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#define _SDIO_HALINIT_C_ + +#include <drv_conf.h> +#include <osdep_service.h> +#include <drv_types.h> + +#ifndef CONFIG_SDIO_HCI +#error "CONFIG_SDIO_HCI shall be on!\n" +#endif + +#include <rtw_efuse.h> +#include <rtl8188e_hal.h> +#include <rtl8188e_led.h> +#include <HalPwrSeqCmd.h> +#include <Hal8188EPwrSeq.h> +#include <sdio_ops.h> + +#ifdef CONFIG_EFUSE_CONFIG_FILE +#include <linux/fs.h> +#include <asm/uaccess.h> +#endif //CONFIG_EFUSE_CONFIG_FILE + + +/* + * Description: + * Call this function to make sure power on successfully + * + * Return: + * _SUCCESS enable success + * _FAIL enable fail + */ + +static int PowerOnCheck(PADAPTER padapter) +{ + u32 val_offset0, val_offset1, val_offset2, val_offset3; + u32 val_mix = 0; + u32 res = 0; + u8 ret = _FAIL; + int index = 0; + + val_offset0 = rtw_read8(padapter, REG_CR); + val_offset1 = rtw_read8(padapter, REG_CR+1); + val_offset2 = rtw_read8(padapter, REG_CR+2); + val_offset3 = rtw_read8(padapter, REG_CR+3); + + if (val_offset0 == 0xEA || val_offset1 == 0xEA || + val_offset2 == 0xEA || val_offset3 ==0xEA) { + DBG_871X("%s: power on fail, do Power on again\n", __func__); + return ret; + } + + val_mix = val_offset3 << 24 | val_mix; + val_mix = val_offset2 << 16 | val_mix; + val_mix = val_offset1 << 8 | val_mix; + val_mix = val_offset0 | val_mix; + + res = rtw_read32(padapter, REG_CR); + + DBG_871X("%s: val_mix:0x%08x, res:0x%08x\n", __func__, val_mix, res); + + while(index < 100) { + if (res == val_mix) { + DBG_871X("%s: 0x100 the result of cmd52 and cmd53 is the same.\n", __func__); + ret = _SUCCESS; + break; + } else { + DBG_871X("%s: 0x100 cmd52 and cmd53 is not the same(index:%d).\n", __func__, index); + res = rtw_read32(padapter, REG_CR); + index ++; + ret = _FAIL; + } + } + + if (ret) { + index = 0; + while(index < 100) { + rtw_write32(padapter, 0x1B8, 0x12345678); + res = rtw_read32(padapter, 0x1B8); + if (res == 0x12345678) { + DBG_871X("%s: 0x1B8 test Pass.\n", __func__); + ret = _SUCCESS; + break; + } else { + index ++; + DBG_871X("%s: 0x1B8 test Fail(index: %d).\n", __func__, index); + ret = _FAIL; + } + } + } else { + DBG_871X("%s: fail at cmd52, cmd53.\n", __func__); + } + return ret; +} + +#ifdef CONFIG_EXT_CLK +void EnableGpio5ClockReq(PADAPTER Adapter, u8 in_interrupt, u32 Enable) +{ + u32 value32; + HAL_DATA_TYPE *pHalData; + + pHalData = GET_HAL_DATA(Adapter); + if(IS_D_CUT(pHalData->VersionID)) + return; + + //dbgdump("%s Enable:%x time:%d", __RTL_FUNC__, Enable, rtw_get_current_time()); + + if(in_interrupt) + value32 = _sdio_read32(Adapter, REG_GPIO_PIN_CTRL); + else + value32 = rtw_read32(Adapter, REG_GPIO_PIN_CTRL); + + //open GPIO 5 + if (Enable) + value32 |= BIT(13);//5+8 + else + value32 &= ~BIT(13); + + //GPIO 5 out put + value32 |= BIT(21);//5+16 + + //if (Enable) + // rtw_write8(Adapter, REG_GPIO_PIN_CTRL + 1, 0x20); + //else + // rtw_write8(Adapter, REG_GPIO_PIN_CTRL + 1, 0x00); + + if(in_interrupt) + _sdio_write32(Adapter, REG_GPIO_PIN_CTRL, value32); + else + rtw_write32(Adapter, REG_GPIO_PIN_CTRL, value32); + +} //end of _rtl8192cs_disable_gpio() + +void _InitClockTo26MHz( + IN PADAPTER Adapter + ) +{ + u8 u1temp = 0; + HAL_DATA_TYPE *pHalData; + + pHalData = GET_HAL_DATA(Adapter); + + if(IS_D_CUT(pHalData->VersionID)) { + //FW special init + u1temp = rtw_read8(Adapter, REG_XCK_OUT_CTRL); + u1temp |= 0x18; + rtw_write8(Adapter, REG_XCK_OUT_CTRL, u1temp); + MSG_8192C("D cut version\n"); + } + + EnableGpio5ClockReq(Adapter, _FALSE, 1); + + //0x2c[3:0] = 5 will set clock to 26MHz + u1temp = rtw_read8(Adapter, REG_APE_PLL_CTRL_EXT); + u1temp = (u1temp & 0xF0) | 0x05; + rtw_write8(Adapter, REG_APE_PLL_CTRL_EXT, u1temp); +} +#endif + + +static void rtl8188es_interface_configure(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct registry_priv *pregistrypriv = &padapter->registrypriv; + BOOLEAN bWiFiConfig = pregistrypriv->wifi_spec; + + + pdvobjpriv->RtOutPipe[0] = WLAN_TX_HIQ_DEVICE_ID; + pdvobjpriv->RtOutPipe[1] = WLAN_TX_MIQ_DEVICE_ID; + pdvobjpriv->RtOutPipe[2] = WLAN_TX_LOQ_DEVICE_ID; + + if (bWiFiConfig) + pHalData->OutEpNumber = 2; + else + pHalData->OutEpNumber = SDIO_MAX_TX_QUEUE; + + switch(pHalData->OutEpNumber){ + case 3: + pHalData->OutEpQueueSel=TX_SELE_HQ| TX_SELE_LQ|TX_SELE_NQ; + break; + case 2: + pHalData->OutEpQueueSel=TX_SELE_HQ| TX_SELE_NQ; + break; + case 1: + pHalData->OutEpQueueSel=TX_SELE_HQ; + break; + default: + break; + } + + Hal_MappingOutPipe(padapter, pHalData->OutEpNumber); +} + +/* + * Description: + * Call power on sequence to enable card + * + * Return: + * _SUCCESS enable success + * _FAIL enable fail + */ +static u8 _CardEnable(PADAPTER padapter) +{ + u8 bMacPwrCtrlOn; + u8 ret; + + DBG_871X("=>%s\n", __FUNCTION__); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (bMacPwrCtrlOn == _FALSE) + { +#ifdef CONFIG_PLATFORM_SPRD + u8 val8; +#endif // CONFIG_PLATFORM_SPRD + + // RSV_CTRL 0x1C[7:0] = 0x00 + // unlock ISO/CLK/Power control register + rtw_write8(padapter, REG_RSV_CTRL, 0x0); + +#ifdef CONFIG_PLATFORM_SPRD +#ifdef CONFIG_EXT_CLK + _InitClockTo26MHz(padapter); +#endif //CONFIG_EXT_CLK + + val8 = rtw_read8(padapter, 0x4); + val8 = val8 & ~BIT(5); + rtw_write8(padapter, 0x4, val8); +#endif // CONFIG_PLATFORM_SPRD + + ret = HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, Rtl8188E_NIC_ENABLE_FLOW); + if (ret == _SUCCESS) { + u8 bMacPwrCtrlOn = _TRUE; + rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + } + else + { + DBG_871X(KERN_ERR "%s: run power on flow fail\n", __func__); + return _FAIL; + } + + } + else + { + ret = _SUCCESS; + } + + DBG_871X("<=%s\n", __FUNCTION__); + + return ret; + +} + +static u32 rtl8188es_InitPowerOn(PADAPTER padapter) +{ + u8 value8; + u16 value16; + u32 value32; + u8 ret; + + DBG_871X("=>%s\n", __FUNCTION__); + + ret = _CardEnable(padapter); + if (ret == _FAIL) { + return ret; + } + +/* + // Radio-Off Pin Trigger + value8 = rtw_read8(padapter, REG_GPIO_INTM+1); + value8 |= BIT(1); // Enable falling edge triggering interrupt + rtw_write8(padapter, REG_GPIO_INTM+1, value8); + value8 = rtw_read8(padapter, REG_GPIO_IO_SEL_2+1); + value8 |= BIT(1); + rtw_write8(padapter, REG_GPIO_IO_SEL_2+1, value8); +*/ + + // Enable power down and GPIO interrupt + value16 = rtw_read16(padapter, REG_APS_FSMCO); + value16 |= EnPDN; // Enable HW power down and RF on + rtw_write16(padapter, REG_APS_FSMCO, value16); + + + // Enable MAC DMA/WMAC/SCHEDULE/SEC block + value16 = rtw_read16(padapter, REG_CR); + value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN + | PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN); + // for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. + + rtw_write16(padapter, REG_CR, value16); + + + + // Enable CMD53 R/W Operation +// bMacPwrCtrlOn = TRUE; +// rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, (pu8)(&bMacPwrCtrlOn)); + + DBG_871X("<=%s\n", __FUNCTION__); + + return _SUCCESS; + +} + +static void _InitQueueReservedPage(PADAPTER padapter) +{ +#ifdef RTL8188ES_MAC_LOOPBACK + +//#define MAC_LOOPBACK_PAGE_NUM_PUBQ 0x26 +//#define MAC_LOOPBACK_PAGE_NUM_HPQ 0x0b +//#define MAC_LOOPBACK_PAGE_NUM_LPQ 0x0b +//#define MAC_LOOPBACK_PAGE_NUM_NPQ 0x0b // 71 pages=>9088 bytes, 8.875k + + rtw_write16(padapter, REG_RQPN_NPQ, 0x0b0b); + rtw_write32(padapter, REG_RQPN, 0x80260b0b); + +#else //TX_PAGE_BOUNDARY_LOOPBACK_MODE + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct registry_priv *pregistrypriv = &padapter->registrypriv; + u32 outEPNum = (u32)pHalData->OutEpNumber; + u32 numHQ = 0; + u32 numLQ = 0; + u32 numNQ = 0; + u32 numPubQ; + u32 value32; + u8 value8; + BOOLEAN bWiFiConfig = pregistrypriv->wifi_spec; + + if(bWiFiConfig) + { + if (pHalData->OutEpQueueSel & TX_SELE_HQ) + { + numHQ = 0x29; + } + + if (pHalData->OutEpQueueSel & TX_SELE_LQ) + { + numLQ = 0x1C; + } + + // NOTE: This step shall be proceed before writting REG_RQPN. + if (pHalData->OutEpQueueSel & TX_SELE_NQ) { + numNQ = 0x1C; + } + value8 = (u8)_NPQ(numNQ); + rtw_write8(padapter, REG_RQPN_NPQ, value8); + + numPubQ = 0xA9 - numHQ - numLQ - numNQ; + + // TX DMA + value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN; + rtw_write32(padapter, REG_RQPN, value32); + } + else + { + rtw_write16(padapter, REG_RQPN_NPQ, 0x0000); + rtw_write32(padapter,REG_RQPN, 0x80a00900); + } +#endif + return; +} + +static void _InitTxBufferBoundary(PADAPTER padapter, u8 txpktbuf_bndy) +{ + struct registry_priv *pregistrypriv = &padapter->registrypriv; + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + //u16 txdmactrl; + + rtw_write8(padapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtw_write8(padapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + rtw_write8(padapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); + rtw_write8(padapter, REG_TRXFF_BNDY, txpktbuf_bndy); + rtw_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy); + +} + +static VOID +_InitNormalChipRegPriority( + IN PADAPTER Adapter, + IN u16 beQ, + IN u16 bkQ, + IN u16 viQ, + IN u16 voQ, + IN u16 mgtQ, + IN u16 hiQ + ) +{ + u16 value16 = (rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7); + + value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) | + _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) | + _TXDMA_MGQ_MAP(mgtQ)| _TXDMA_HIQ_MAP(hiQ); + + rtw_write16(Adapter, REG_TRXDMA_CTRL, value16); +} + +static VOID +_InitNormalChipOneOutEpPriority( + IN PADAPTER Adapter + ) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + u16 value = 0; + switch(pHalData->OutEpQueueSel) + { + case TX_SELE_HQ: + value = QUEUE_HIGH; + break; + case TX_SELE_LQ: + value = QUEUE_LOW; + break; + case TX_SELE_NQ: + value = QUEUE_NORMAL; + break; + default: + //RT_ASSERT(FALSE,("Shall not reach here!\n")); + break; + } + + _InitNormalChipRegPriority(Adapter, + value, + value, + value, + value, + value, + value + ); + +} + +static VOID +_InitNormalChipTwoOutEpPriority( + IN PADAPTER Adapter + ) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct registry_priv *pregistrypriv = &Adapter->registrypriv; + u16 beQ,bkQ,viQ,voQ,mgtQ,hiQ; + + + u16 valueHi = 0; + u16 valueLow = 0; + + switch(pHalData->OutEpQueueSel) + { + case (TX_SELE_HQ | TX_SELE_LQ): + valueHi = QUEUE_HIGH; + valueLow = QUEUE_LOW; + break; + case (TX_SELE_NQ | TX_SELE_LQ): + valueHi = QUEUE_NORMAL; + valueLow = QUEUE_LOW; + break; + case (TX_SELE_HQ | TX_SELE_NQ): + valueHi = QUEUE_HIGH; + valueLow = QUEUE_NORMAL; + break; + default: + //RT_ASSERT(FALSE,("Shall not reach here!\n")); + break; + } + + if(!pregistrypriv->wifi_spec ){ + beQ = valueLow; + bkQ = valueLow; + viQ = valueHi; + voQ = valueHi; + mgtQ = valueHi; + hiQ = valueHi; + } + else{//for WMM ,CONFIG_OUT_EP_WIFI_MODE + beQ = valueLow; + bkQ = valueHi; + viQ = valueHi; + voQ = valueLow; + mgtQ = valueHi; + hiQ = valueHi; + } + + _InitNormalChipRegPriority(Adapter,beQ,bkQ,viQ,voQ,mgtQ,hiQ); + +} + +static VOID +_InitNormalChipThreeOutEpPriority( + IN PADAPTER padapter + ) +{ + struct registry_priv *pregistrypriv = &padapter->registrypriv; + u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; + + if (!pregistrypriv->wifi_spec){// typical setting + beQ = QUEUE_LOW; + bkQ = QUEUE_LOW; + viQ = QUEUE_NORMAL; + voQ = QUEUE_HIGH; + mgtQ = QUEUE_HIGH; + hiQ = QUEUE_HIGH; + } + else {// for WMM + beQ = QUEUE_LOW; + bkQ = QUEUE_NORMAL; + viQ = QUEUE_NORMAL; + voQ = QUEUE_HIGH; + mgtQ = QUEUE_HIGH; + hiQ = QUEUE_HIGH; + } + _InitNormalChipRegPriority(padapter,beQ,bkQ,viQ,voQ,mgtQ,hiQ); +} + +static VOID +_InitNormalChipQueuePriority( + IN PADAPTER Adapter + ) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + switch(pHalData->OutEpNumber) + { + case 1: + _InitNormalChipOneOutEpPriority(Adapter); + break; + case 2: + _InitNormalChipTwoOutEpPriority(Adapter); + break; + case 3: + _InitNormalChipThreeOutEpPriority(Adapter); + break; + default: + //RT_ASSERT(FALSE,("Shall not reach here!\n")); + break; + } + + +} + + +static void _InitQueuePriority(PADAPTER padapter) +{ + _InitNormalChipQueuePriority(padapter); +} + +static void _InitPageBoundary(PADAPTER padapter) +{ + // RX Page Boundary + u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E-1; + + rtw_write16(padapter, (REG_TRXFF_BNDY + 2), rxff_bndy); + +} + +static void _InitTransferPageSize(PADAPTER padapter) +{ + // Tx page size is always 128. + + u8 value8; + value8 = _PSRX(PBP_128) | _PSTX(PBP_128); + rtw_write8(padapter, REG_PBP, value8); +} + +void _InitDriverInfoSize(PADAPTER padapter, u8 drvInfoSize) +{ + rtw_write8(padapter, REG_RX_DRVINFO_SZ, drvInfoSize); +} + +void _InitNetworkType(PADAPTER padapter) +{ + u32 value32; + + value32 = rtw_read32(padapter, REG_CR); + + // TODO: use the other function to set network type +// value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AD_HOC); + value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP); + + rtw_write32(padapter, REG_CR, value32); +} + +void _InitWMACSetting(PADAPTER padapter) +{ + u16 value16; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + + //pHalData->ReceiveConfig = RCR_AAP | RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA | RCR_CBSSID_BCN | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_PHYSTS | RCR_APP_ICV | RCR_APP_MIC; + // don't turn on AAP, it will allow all packets to driver + pHalData->ReceiveConfig = RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA | RCR_CBSSID_BCN | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_PHYST_RXFF | RCR_APP_ICV | RCR_APP_MIC; + + rtw_write32(padapter, REG_RCR, pHalData->ReceiveConfig); + + // Accept all data frames + value16 = 0xFFFF; + rtw_write16(padapter, REG_RXFLTMAP2, value16); + + // 2010.09.08 hpfan + // Since ADF is removed from RCR, ps-poll will not be indicate to driver, + // RxFilterMap should mask ps-poll to gurantee AP mode can rx ps-poll. + value16 = 0x400; + rtw_write16(padapter, REG_RXFLTMAP1, value16); + + // Accept all management frames + value16 = 0xFFFF; + rtw_write16(padapter, REG_RXFLTMAP0, value16); + +} + +void _InitAdaptiveCtrl(PADAPTER padapter) +{ + u16 value16; + u32 value32; + + // Response Rate Set + value32 = rtw_read32(padapter, REG_RRSR); + value32 &= ~RATE_BITMAP_ALL; + value32 |= RATE_RRSR_CCK_ONLY_1M; + rtw_write32(padapter, REG_RRSR, value32); + + // CF-END Threshold + //m_spIoBase->rtw_write8(REG_CFEND_TH, 0x1); + + // SIFS (used in NAV) + value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10); + rtw_write16(padapter, REG_SPEC_SIFS, value16); + + // Retry Limit + value16 = _LRL(0x30) | _SRL(0x30); + rtw_write16(padapter, REG_RL, value16); +} + +void _InitEDCA(PADAPTER padapter) +{ + // Set Spec SIFS (used in NAV) + rtw_write16(padapter, REG_SPEC_SIFS, 0x100a); + rtw_write16(padapter, REG_MAC_SPEC_SIFS, 0x100a); + + // Set SIFS for CCK + rtw_write16(padapter, REG_SIFS_CTX, 0x100a); + + // Set SIFS for OFDM + rtw_write16(padapter, REG_SIFS_TRX, 0x100a); + + // TXOP + rtw_write32(padapter, REG_EDCA_BE_PARAM, 0x005EA42B); + rtw_write32(padapter, REG_EDCA_BK_PARAM, 0x0000A44F); + rtw_write32(padapter, REG_EDCA_VI_PARAM, 0x005EA324); + rtw_write32(padapter, REG_EDCA_VO_PARAM, 0x002FA226); +} + +void _InitRateFallback(PADAPTER padapter) +{ + // Set Data Auto Rate Fallback Retry Count register. + rtw_write32(padapter, REG_DARFRC, 0x00000000); + rtw_write32(padapter, REG_DARFRC+4, 0x10080404); + rtw_write32(padapter, REG_RARFRC, 0x04030201); + rtw_write32(padapter, REG_RARFRC+4, 0x08070605); + +} + +void _InitRetryFunction(PADAPTER padapter) +{ + u8 value8; + + value8 = rtw_read8(padapter, REG_FWHW_TXQ_CTRL); + value8 |= EN_AMPDU_RTY_NEW; + rtw_write8(padapter, REG_FWHW_TXQ_CTRL, value8); + + // Set ACK timeout + rtw_write8(padapter, REG_ACKTO, 0x40); +} + +static void HalRxAggr8188ESdio(PADAPTER padapter) +{ +#if 1 + struct registry_priv *pregistrypriv; + u8 valueDMATimeout; + u8 valueDMAPageCount; + + + pregistrypriv = &padapter->registrypriv; + + if (pregistrypriv->wifi_spec) + { + // 2010.04.27 hpfan + // Adjust RxAggrTimeout to close to zero disable RxAggr, suggested by designer + // Timeout value is calculated by 34 / (2^n) + valueDMATimeout = 0x0f; + valueDMAPageCount = 0x01; + } + else + { + valueDMATimeout = 0x06; + //valueDMAPageCount = 0x0F; + //valueDMATimeout = 0x0a; + valueDMAPageCount = 0x24; + } + + rtw_write8(padapter, REG_RXDMA_AGG_PG_TH+1, valueDMATimeout); + rtw_write8(padapter, REG_RXDMA_AGG_PG_TH, valueDMAPageCount); +#endif +} + +void sdio_AggSettingRxUpdate(PADAPTER padapter) +{ +#if 1 + //HAL_DATA_TYPE *pHalData; + u8 valueDMA; + + + //pHalData = GET_HAL_DATA(padapter); + + valueDMA = rtw_read8(padapter, REG_TRXDMA_CTRL); + valueDMA |= RXDMA_AGG_EN; + rtw_write8(padapter, REG_TRXDMA_CTRL, valueDMA); + +#if 0 + switch (RX_PAGE_SIZE_REG_VALUE) + { + case PBP_64: + pHalData->HwRxPageSize = 64; + break; + case PBP_128: + pHalData->HwRxPageSize = 128; + break; + case PBP_256: + pHalData->HwRxPageSize = 256; + break; + case PBP_512: + pHalData->HwRxPageSize = 512; + break; + case PBP_1024: + pHalData->HwRxPageSize = 1024; + break; + default: + RT_TRACE(_module_hci_hal_init_c_, _drv_err_, + ("%s: RX_PAGE_SIZE_REG_VALUE definition is incorrect!\n", __FUNCTION__)); + break; + } +#endif +#endif +} + +void _initSdioAggregationSetting(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + // Tx aggregation setting + //sdio_AggSettingTxUpdate(padapter); + + // Rx aggregation setting + HalRxAggr8188ESdio(padapter); + sdio_AggSettingRxUpdate(padapter); + + // 201/12/10 MH Add for USB agg mode dynamic switch. + pHalData->UsbRxHighSpeedMode = _FALSE; +} + + +void _InitOperationMode(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData; + struct mlme_ext_priv *pmlmeext; + u8 regBwOpMode = 0; + u32 regRATR = 0, regRRSR = 0; + u8 MinSpaceCfg; + + + pHalData = GET_HAL_DATA(padapter); + pmlmeext = &padapter->mlmeextpriv; + + //1 This part need to modified according to the rate set we filtered!! + // + // Set RRSR, RATR, and REG_BWOPMODE registers + // + switch(pmlmeext->cur_wireless_mode) + { + case WIRELESS_MODE_B: + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK; + regRRSR = RATE_ALL_CCK; + break; + case WIRELESS_MODE_A: +// RT_ASSERT(FALSE,("Error wireless a mode\n")); +#if 0 + regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ; + regRATR = RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_OFDM_AG; +#endif + break; + case WIRELESS_MODE_G: + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + break; + case WIRELESS_MODE_AUTO: +#if 0 + if (padapter->bInHctTest) + { + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + } + else +#endif + { + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + } + break; + case WIRELESS_MODE_N_24G: + // It support CCK rate by default. + // CCK rate will be filtered out only when associated AP does not support it. + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + break; + case WIRELESS_MODE_N_5G: +// RT_ASSERT(FALSE,("Error wireless mode")); +#if 0 + regBwOpMode = BW_OPMODE_5G; + regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_OFDM_AG; +#endif + break; + + default: //for MacOSX compiler warning. + break; + } + + rtw_write8(padapter, REG_BWOPMODE, regBwOpMode); + + // For Min Spacing configuration. + switch(pHalData->rf_type) + { + case RF_1T2R: + case RF_1T1R: + RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("Initializepadapter: RF_Type%s\n", (pHalData->rf_type==RF_1T1R? "(1T1R)":"(1T2R)"))); +// padapter->MgntInfo.MinSpaceCfg = (MAX_MSS_DENSITY_1T<<3); + MinSpaceCfg = (MAX_MSS_DENSITY_1T << 3); + break; + case RF_2T2R: + case RF_2T2R_GREEN: + RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("Initializepadapter:RF_Type(2T2R)\n")); +// padapter->MgntInfo.MinSpaceCfg = (MAX_MSS_DENSITY_2T<<3); + MinSpaceCfg = (MAX_MSS_DENSITY_2T << 3); + break; + } + +// rtw_write8(padapter, REG_AMPDU_MIN_SPACE, padapter->MgntInfo.MinSpaceCfg); + rtw_write8(padapter, REG_AMPDU_MIN_SPACE, MinSpaceCfg); +} + + +void _InitBeaconParameters(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData; + + + pHalData = GET_HAL_DATA(padapter); + + rtw_write16(padapter, REG_BCN_CTRL, 0x1010); + + // TODO: Remove these magic number + rtw_write16(padapter, REG_TBTT_PROHIBIT, 0x6404);// ms + rtw_write8(padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);//ms + rtw_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); + + // Suggested by designer timchen. Change beacon AIFS to the largest number + // beacause test chip does not contension before sending beacon. by tynli. 2009.11.03 + rtw_write16(padapter, REG_BCNTCFG, 0x660F); + + + pHalData->RegBcnCtrlVal = rtw_read8(padapter, REG_BCN_CTRL); + pHalData->RegTxPause = rtw_read8(padapter, REG_TXPAUSE); + pHalData->RegFwHwTxQCtrl = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2); + pHalData->RegReg542 = rtw_read8(padapter, REG_TBTT_PROHIBIT+2); + pHalData->RegCR_1 = rtw_read8(padapter, REG_CR+1); + +} + +void _InitBeaconMaxError(PADAPTER padapter, BOOLEAN InfraMode) +{ +#ifdef RTL8192CU_ADHOC_WORKAROUND_SETTING + rtw_write8(padapter, REG_BCN_MAX_ERR, 0xFF); +#endif +} + +void _InitInterrupt(PADAPTER padapter) +{ + + //HISR write one to clear + rtw_write32(padapter, REG_HISR_88E, 0xFFFFFFFF); + + // HIMR - turn all off + rtw_write32(padapter, REG_HIMR_88E, 0); + + // + // Initialize and enable SDIO Host Interrupt. + // + InitInterrupt8188ESdio(padapter); + + + // + // Initialize and enable system Host Interrupt. + // + //InitSysInterrupt8188ESdio(Adapter);//TODO: + + // + // Enable SDIO Host Interrupt. + // + //EnableInterrupt8188ESdio(padapter);//Move to sd_intf_start()/stop + +} + +void _InitRDGSetting(PADAPTER padapter) +{ + rtw_write8(padapter, REG_RD_CTRL, 0xFF); + rtw_write16(padapter, REG_RD_NAV_NXT, 0x200); + rtw_write8(padapter, REG_RD_RESP_PKT_TH, 0x05); +} + + +static void _InitRxSetting(PADAPTER padapter) +{ + rtw_write32(padapter, REG_MACID, 0x87654321); + rtw_write32(padapter, 0x0700, 0x87654321); +} + + +static void _InitRFType(PADAPTER padapter) +{ + struct registry_priv *pregpriv = &padapter->registrypriv; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + //BOOLEAN is92CU = IS_92C_SERIAL(pHalData->VersionID); + BOOLEAN is2T2R = IS_2T2R(pHalData->VersionID); + +#if DISABLE_BB_RF + pHalData->rf_chip = RF_PSEUDO_11N; + return; +#endif + + pHalData->rf_chip = RF_6052; + + //if (_FALSE == is92CU) { + if(_FALSE == is2T2R){ + pHalData->rf_type = RF_1T1R; + DBG_8192C("Set RF Chip ID to RF_6052 and RF type to 1T1R.\n"); + return; + } + + // TODO: Consider that EEPROM set 92CU to 1T1R later. + // Force to overwrite setting according to chip version. Ignore EEPROM setting. + //pHalData->RF_Type = is92CU ? RF_2T2R : RF_1T1R; + MSG_8192C("Set RF Chip ID to RF_6052 and RF type to %d.\n", pHalData->rf_type); +} + +// Set CCK and OFDM Block "ON" +static void _BBTurnOnBlock(PADAPTER padapter) +{ +#if (DISABLE_BB_RF) + return; +#endif + + PHY_SetBBReg(padapter, rFPGA0_RFMOD, bCCKEn, 0x1); + PHY_SetBBReg(padapter, rFPGA0_RFMOD, bOFDMEn, 0x1); +} + +#if 0 +static void _InitAntenna_Selection(PADAPTER padapter) +{ + rtw_write8(padapter, REG_LEDCFG2, 0x82); +} +#endif + +static void _InitPABias(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 pa_setting; + BOOLEAN is92C = IS_92C_SERIAL(pHalData->VersionID); + + //FIXED PA current issue + //efuse_one_byte_read(padapter, 0x1FA, &pa_setting); + pa_setting = EFUSE_Read1Byte(padapter, 0x1FA); + + //RT_TRACE(COMP_INIT, DBG_LOUD, ("_InitPABias 0x1FA 0x%x \n",pa_setting)); + + if(!(pa_setting & BIT0)) + { + PHY_SetRFReg(padapter, RF_PATH_A, 0x15, 0x0FFFFF, 0x0F406); + PHY_SetRFReg(padapter, RF_PATH_A, 0x15, 0x0FFFFF, 0x4F406); + PHY_SetRFReg(padapter, RF_PATH_A, 0x15, 0x0FFFFF, 0x8F406); + PHY_SetRFReg(padapter, RF_PATH_A, 0x15, 0x0FFFFF, 0xCF406); + //RT_TRACE(COMP_INIT, DBG_LOUD, ("PA BIAS path A\n")); + } + + if(!(pa_setting & BIT1) && is92C) + { + PHY_SetRFReg(padapter,RF_PATH_B, 0x15, 0x0FFFFF, 0x0F406); + PHY_SetRFReg(padapter,RF_PATH_B, 0x15, 0x0FFFFF, 0x4F406); + PHY_SetRFReg(padapter,RF_PATH_B, 0x15, 0x0FFFFF, 0x8F406); + PHY_SetRFReg(padapter,RF_PATH_B, 0x15, 0x0FFFFF, 0xCF406); + //RT_TRACE(COMP_INIT, DBG_LOUD, ("PA BIAS path B\n")); + } + + if(!(pa_setting & BIT4)) + { + pa_setting = rtw_read8(padapter, 0x16); + pa_setting &= 0x0F; + rtw_write8(padapter, 0x16, pa_setting | 0x80); + rtw_write8(padapter, 0x16, pa_setting | 0x90); + } +} + +#if 0 +VOID +_InitRDGSetting_8188E( + IN PADAPTER Adapter + ) +{ + PlatformEFIOWrite1Byte(Adapter,REG_RD_CTRL,0xFF); + PlatformEFIOWrite2Byte(Adapter, REG_RD_NAV_NXT, 0x200); + PlatformEFIOWrite1Byte(Adapter,REG_RD_RESP_PKT_TH,0x05); +} +#endif + +static u32 rtl8188es_hal_init(PADAPTER padapter) +{ + s32 ret; + u8 txpktbuf_bndy; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; + struct registry_priv *pregistrypriv = &padapter->registrypriv; + u8 is92C = IS_92C_SERIAL(pHalData->VersionID); + rt_rf_power_state eRfPowerStateToSet; + u8 value8; + u16 value16; + + u32 init_start_time = rtw_get_current_time(); + +#ifdef DBG_HAL_INIT_PROFILING + enum HAL_INIT_STAGES { + HAL_INIT_STAGES_BEGIN = 0, + HAL_INIT_STAGES_INIT_PW_ON, + HAL_INIT_STAGES_MISC01, + HAL_INIT_STAGES_DOWNLOAD_FW, + HAL_INIT_STAGES_MAC, + HAL_INIT_STAGES_BB, + HAL_INIT_STAGES_RF, + HAL_INIT_STAGES_EFUSE_PATCH, + HAL_INIT_STAGES_INIT_LLTT, + + HAL_INIT_STAGES_MISC02, + HAL_INIT_STAGES_TURN_ON_BLOCK, + HAL_INIT_STAGES_INIT_SECURITY, + HAL_INIT_STAGES_MISC11, + HAL_INIT_STAGES_INIT_HAL_DM, + //HAL_INIT_STAGES_RF_PS, + HAL_INIT_STAGES_IQK, + HAL_INIT_STAGES_PW_TRACK, + HAL_INIT_STAGES_LCK, + //HAL_INIT_STAGES_MISC21, + HAL_INIT_STAGES_INIT_PABIAS, + //HAL_INIT_STAGES_ANTENNA_SEL, + HAL_INIT_STAGES_MISC31, + HAL_INIT_STAGES_END, + HAL_INIT_STAGES_NUM + }; + + char * hal_init_stages_str[] = { + "HAL_INIT_STAGES_BEGIN", + "HAL_INIT_STAGES_INIT_PW_ON", + "HAL_INIT_STAGES_MISC01", + "HAL_INIT_STAGES_DOWNLOAD_FW", + "HAL_INIT_STAGES_MAC", + "HAL_INIT_STAGES_BB", + "HAL_INIT_STAGES_RF", + "HAL_INIT_STAGES_EFUSE_PATCH", + "HAL_INIT_STAGES_INIT_LLTT", + "HAL_INIT_STAGES_MISC02", + "HAL_INIT_STAGES_TURN_ON_BLOCK", + "HAL_INIT_STAGES_INIT_SECURITY", + "HAL_INIT_STAGES_MISC11", + "HAL_INIT_STAGES_INIT_HAL_DM", + //"HAL_INIT_STAGES_RF_PS", + "HAL_INIT_STAGES_IQK", + "HAL_INIT_STAGES_PW_TRACK", + "HAL_INIT_STAGES_LCK", + //"HAL_INIT_STAGES_MISC21", + "HAL_INIT_STAGES_INIT_PABIAS" + //"HAL_INIT_STAGES_ANTENNA_SEL", + "HAL_INIT_STAGES_MISC31", + "HAL_INIT_STAGES_END", + }; + + + int hal_init_profiling_i; + u32 hal_init_stages_timestamp[HAL_INIT_STAGES_NUM]; //used to record the time of each stage's starting point + + for(hal_init_profiling_i=0;hal_init_profiling_i<HAL_INIT_STAGES_NUM;hal_init_profiling_i++) + hal_init_stages_timestamp[hal_init_profiling_i]=0; + + #define HAL_INIT_PROFILE_TAG(stage) hal_init_stages_timestamp[(stage)]=rtw_get_current_time(); +#else + #define HAL_INIT_PROFILE_TAG(stage) do {} while(0) +#endif //DBG_HAL_INIT_PROFILING + + DBG_8192C("+rtl8188es_hal_init\n"); + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BEGIN); + // Disable Interrupt first. +// rtw_hal_disable_interrupt(padapter); +// DisableInterrupt8188ESdio(padapter); + +#ifdef CONFIG_WOWLAN + if(rtw_read8(padapter, REG_MCUFWDL)&BIT7 && + (padapter->pwrctrlpriv.wowlan_wake_reason & FWDecisionDisconnect)) { + u8 reg_val=0; + DBG_8192C("+Reset Entry+\n"); + rtw_write8(padapter, REG_MCUFWDL, 0x00); + _8051Reset88E(padapter); + //reset BB + reg_val = rtw_read8(padapter, REG_SYS_FUNC_EN); + reg_val &= ~(BIT(0) | BIT(1)); + rtw_write8(padapter, REG_SYS_FUNC_EN, reg_val); + //reset RF + rtw_write8(padapter, REG_RF_CTRL, 0); + //reset TRX path + rtw_write16(padapter, REG_CR, 0); + //reset MAC, Digital Core + reg_val = rtw_read8(padapter, REG_SYS_FUNC_EN+1); + reg_val &= ~(BIT(4) | BIT(7)); + rtw_write8(padapter, REG_SYS_FUNC_EN+1, reg_val); + reg_val = rtw_read8(padapter, REG_SYS_FUNC_EN+1); + reg_val |= BIT(4) | BIT(7); + rtw_write8(padapter, REG_SYS_FUNC_EN+1, reg_val); + DBG_8192C("-Reset Entry-\n"); + } +#endif //CONFIG_WOWLAN + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON); + ret = rtl8188es_InitPowerOn(padapter); + if (_FAIL == ret) { + RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("Failed to init Power On!\n")); + goto exit; + } + + ret = PowerOnCheck(padapter); + if (_FAIL == ret ) { + DBG_871X("Power on Fail! do it again\n"); + ret = rtl8188es_InitPowerOn(padapter); + if (_FAIL == ret) { + DBG_871X("Failed to init Power On!\n"); + goto exit; + } + } + DBG_871X("Power on ok!\n"); + + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC01); + if (!pregistrypriv->wifi_spec) { + txpktbuf_bndy = TX_PAGE_BOUNDARY_88E; + } else { + // for WMM + txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY_88E; + } + _InitQueueReservedPage(padapter); + _InitQueuePriority(padapter); + _InitPageBoundary(padapter); + _InitTransferPageSize(padapter); +#ifdef CONFIG_IOL_IOREG_CFG + _InitTxBufferBoundary(padapter, 0); +#endif + // + // Configure SDIO TxRx Control to enable Rx DMA timer masking. + // 2010.02.24. + // + value8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_TX_CTRL); + SdioLocalCmd52Write1Byte(padapter, SDIO_REG_TX_CTRL, 0x02); + + rtw_write8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1, 0); + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_DOWNLOAD_FW); +#if (MP_DRIVER == 1) + if (padapter->registrypriv.mp_mode == 1) + { + _InitRxSetting(padapter); + } +#endif //MP_DRIVER == 1 + { +#if 0 + padapter->bFWReady = _FALSE; //because no fw for test chip + pHalData->fw_ractrl = _FALSE; +#else +#ifdef CONFIG_WOWLAN + ret = rtl8188e_FirmwareDownload(padapter, _FALSE); +#else + ret = rtl8188e_FirmwareDownload(padapter); +#endif //CONFIG_WOWLAN + + if (ret != _SUCCESS) { + DBG_871X("%s: Download Firmware failed!!\n", __FUNCTION__); + padapter->bFWReady = _FALSE; + pHalData->fw_ractrl = _FALSE; + goto exit; + } else { + RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("Initializepadapter8192CSdio(): Download Firmware Success!!\n")); + padapter->bFWReady = _TRUE; + pHalData->fw_ractrl = _FALSE; + } +#endif + } + + rtl8188e_InitializeFirmwareVars(padapter); + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MAC); +#if (HAL_MAC_ENABLE == 1) + ret = PHY_MACConfig8188E(padapter); + if(ret != _SUCCESS){ +// RT_TRACE(COMP_INIT, DBG_LOUD, ("Initializepadapter8192CSdio(): Fail to configure MAC!!\n")); + goto exit; + } +#endif + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BB); + // + //d. Initialize BB related configurations. + // +#if (HAL_BB_ENABLE == 1) + ret = PHY_BBConfig8188E(padapter); + if(ret != _SUCCESS){ +// RT_TRACE(COMP_INIT, DBG_SERIOUS, ("Initializepadapter8192CSdio(): Fail to configure BB!!\n")); + goto exit; + } +#endif + + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_RF); + +#if (HAL_RF_ENABLE == 1) + ret = PHY_RFConfig8188E(padapter); + + if(ret != _SUCCESS){ +// RT_TRACE(COMP_INIT, DBG_LOUD, ("Initializepadapter8192CSdio(): Fail to configure RF!!\n")); + goto exit; + } +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_EFUSE_PATCH); +#if defined(CONFIG_IOL_EFUSE_PATCH) + ret = rtl8188e_iol_efuse_patch(padapter); + if(ret != _SUCCESS){ + DBG_871X("%s rtl8188e_iol_efuse_patch failed \n",__FUNCTION__); + goto exit; + } +#endif + _InitTxBufferBoundary(padapter, txpktbuf_bndy); +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_LLTT); + ret = InitLLTTable(padapter, txpktbuf_bndy); + if (_SUCCESS != ret) { + RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("Failed to init LLT Table!\n")); + goto exit; + } + +#if (RATE_ADAPTIVE_SUPPORT==1) + {//Enable TX Report + //Enable Tx Report Timer + value8 = rtw_read8(padapter, REG_TX_RPT_CTRL); + rtw_write8(padapter, REG_TX_RPT_CTRL, (value8|BIT1|BIT0)); + //Set MAX RPT MACID + rtw_write8(padapter, REG_TX_RPT_CTRL+1, 2);//FOR sta mode ,0: bc/mc ,1:AP + //Tx RPT Timer. Unit: 32us + rtw_write16(padapter, REG_TX_RPT_TIME, 0xCdf0); + } +#endif + +#if 0 + if(pHTInfo->bRDGEnable){ + _InitRDGSetting_8188E(Adapter); + } +#endif + +#ifdef CONFIG_TX_EARLY_MODE + if( pHalData->bEarlyModeEnable) + { + RT_TRACE(_module_hci_hal_init_c_, _drv_info_,("EarlyMode Enabled!!!\n")); + + value8 = rtw_read8(padapter, REG_EARLY_MODE_CONTROL); +#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1 + value8 = value8|0x1f; +#else + value8 = value8|0xf; +#endif + rtw_write8(padapter, REG_EARLY_MODE_CONTROL, value8); + + rtw_write8(padapter, REG_EARLY_MODE_CONTROL+3, 0x80); + + value8 = rtw_read8(padapter, REG_TCR+1); + value8 = value8|0x40; + rtw_write8(padapter,REG_TCR+1, value8); + } + else +#endif + { + rtw_write8(padapter, REG_EARLY_MODE_CONTROL, 0); + } + + +#if(SIC_ENABLE == 1) + SIC_Init(padapter); +#endif + + + if (pwrctrlpriv->reg_rfoff == _TRUE) { + pwrctrlpriv->rf_pwrstate = rf_off; + } + + // 2010/08/09 MH We need to check if we need to turnon or off RF after detecting + // HW GPIO pin. Before PHY_RFConfig8192C. + HalDetectPwrDownMode88E(padapter); + + + // Set RF type for BB/RF configuration + _InitRFType(padapter); + + // Save target channel + // <Roger_Notes> Current Channel will be updated again later. + pHalData->CurrentChannel = 1; + + + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC02); + // Get Rx PHY status in order to report RSSI and others. + _InitDriverInfoSize(padapter, 4); + hal_init_macaddr(padapter); + _InitNetworkType(padapter); + _InitWMACSetting(padapter); + _InitAdaptiveCtrl(padapter); + _InitEDCA(padapter); + _InitRateFallback(padapter); + _InitRetryFunction(padapter); + _initSdioAggregationSetting(padapter); + _InitOperationMode(padapter); + _InitBeaconParameters(padapter); + _InitBeaconMaxError(padapter, _TRUE); + _InitInterrupt(padapter); + + // Enable MACTXEN/MACRXEN block + value16 = rtw_read16(padapter, REG_CR); + value16 |= (MACTXEN | MACRXEN); + rtw_write8(padapter, REG_CR, value16); + +#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_TX_MCAST2UNI) + +#ifdef CONFIG_CHECK_AC_LIFETIME + // Enable lifetime check for the four ACs + rtw_write8(padapter, REG_LIFETIME_EN, 0x0F); +#endif // CONFIG_CHECK_AC_LIFETIME + +#ifdef CONFIG_TX_MCAST2UNI + rtw_write16(padapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400); // unit: 256us. 256ms + rtw_write16(padapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); // unit: 256us. 256ms +#else // CONFIG_TX_MCAST2UNI + rtw_write16(padapter, REG_PKT_VO_VI_LIFE_TIME, 0x3000); // unit: 256us. 3s + rtw_write16(padapter, REG_PKT_BE_BK_LIFE_TIME, 0x3000); // unit: 256us. 3s +#endif // CONFIG_TX_MCAST2UNI +#endif // CONFIG_CONCURRENT_MODE || CONFIG_TX_MCAST2UNI + + + + +#endif //HAL_RF_ENABLE == 1 + + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_TURN_ON_BLOCK); + _BBTurnOnBlock(padapter); + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_SECURITY); +#if 1 + invalidate_cam_all(padapter); +#else + CamResetAllEntry(padapter); + padapter->HalFunc.EnableHWSecCfgHandler(padapter); +#endif + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC11); + // 2010/12/17 MH We need to set TX power according to EFUSE content at first. + PHY_SetTxPowerLevel8188E(padapter, pHalData->CurrentChannel); + // Record original value for template. This is arough data, we can only use the data + // for power adjust. The value can not be adjustde according to different power!!! +// pHalData->OriginalCckTxPwrIdx = pHalData->CurrentCckTxPwrIdx; +// pHalData->OriginalOfdm24GTxPwrIdx = pHalData->CurrentOfdm24GTxPwrIdx; + +// Move by Neo for USB SS to below setp +//_RfPowerSave(padapter); +#if 0 //ANTENNA_SELECTION_STATIC_SETTING +#if 0 + if (!IS_92C_SERIAL( pHalData->VersionID) && (pHalData->AntDivCfg!=0)) +#else + if (IS_1T1R( pHalData->VersionID) && (pHalData->AntDivCfg!=0)) +#endif + { //for 88CU ,1T1R + _InitAntenna_Selection(padapter); + } +#endif + + // + // Disable BAR, suggested by Scott + // 2010.04.09 add by hpfan + // + rtw_write32(padapter, REG_BAR_MODE_CTRL, 0x0201ffff); + + // HW SEQ CTRL + // set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. + rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF); + + +#ifdef RTL8188ES_MAC_LOOPBACK + value8 = rtw_read8(padapter, REG_SYS_FUNC_EN); + value8 &= ~(FEN_BBRSTB|FEN_BB_GLB_RSTn); + rtw_write8(padapter, REG_SYS_FUNC_EN, value8);//disable BB, CCK/OFDM + + rtw_write8(padapter, REG_RD_CTRL, 0x0F); + rtw_write8(padapter, REG_RD_CTRL+1, 0xCF); + //rtw_write8(padapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, 0x80);//to check _InitPageBoundary() + rtw_write32(padapter, REG_CR, 0x0b0202ff);//0x100[28:24]=0x01011, enable mac loopback, no HW Security Eng. +#endif + + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_HAL_DM); + // InitHalDm(padapter); + rtl8188e_InitHalDm(padapter); + + +#if (MP_DRIVER == 1) + if (padapter->registrypriv.mp_mode == 1) + { + padapter->mppriv.channel = pHalData->CurrentChannel; + MPT_InitializeAdapter(padapter, padapter->mppriv.channel); + } + else +#endif //(MP_DRIVER == 1) + { + // + // 2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status + // and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not + // call init_adapter. May cause some problem?? + // + // Fix the bug that Hw/Sw radio off before S3/S4, the RF off action will not be executed + // in MgntActSet_RF_State() after wake up, because the value of pHalData->eRFPowerState + // is the same as eRfOff, we should change it to eRfOn after we config RF parameters. + // Added by tynli. 2010.03.30. + pwrctrlpriv->rf_pwrstate = rf_on; + RT_CLEAR_PS_LEVEL(pwrctrlpriv, RT_RF_OFF_LEVL_HALT_NIC); + + // 20100326 Joseph: Copy from GPIOChangeRFWorkItemCallBack() function to check HW radio on/off. + // 20100329 Joseph: Revise and integrate the HW/SW radio off code in initialization. +// pHalData->bHwRadioOff = _FALSE; + pwrctrlpriv->b_hw_radio_off = _FALSE; + eRfPowerStateToSet = rf_on; + + // 2010/-8/09 MH For power down module, we need to enable register block contrl reg at 0x1c. + // Then enable power down control bit of register 0x04 BIT4 and BIT15 as 1. + if(pHalData->pwrdown && eRfPowerStateToSet == rf_off) + { + // Enable register area 0x0-0xc. + rtw_write8(padapter, REG_RSV_CTRL, 0x0); + + // + // <Roger_Notes> We should configure HW PDn source for WiFi ONLY, and then + // our HW will be set in power-down mode if PDn source from all functions are configured. + // 2010.10.06. + // + if(IS_HARDWARE_TYPE_8723AS(padapter)) + { + value8 = rtw_read8(padapter, REG_MULTI_FUNC_CTRL); + rtw_write8(padapter, REG_MULTI_FUNC_CTRL, (value8|WL_HWPDN_EN)); + } + else + { + rtw_write16(padapter, REG_APS_FSMCO, 0x8812); + } + } + //DrvIFIndicateCurrentPhyStatus(padapter); // 2010/08/17 MH Disable to prevent BSOD. + + // 2010/08/26 MH Merge from 8192CE. + if(pwrctrlpriv->rf_pwrstate == rf_on) + { + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK); + if(pHalData->odmpriv.RFCalibrateInfo.bIQKInitialized){ +// PHY_IQCalibrate(padapter, _TRUE); + PHY_IQCalibrate_8188E(padapter,_TRUE); + } + else + { +// PHY_IQCalibrate(padapter, _FALSE); + PHY_IQCalibrate_8188E(padapter,_FALSE); + pHalData->odmpriv.RFCalibrateInfo.bIQKInitialized = _TRUE; + } + +// dm_CheckTXPowerTracking(padapter); +// PHY_LCCalibrate(padapter); + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_PW_TRACK); + ODM_TXPowerTrackingCheck(&pHalData->odmpriv ); + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK); + PHY_LCCalibrate_8188E(padapter); + + + } +} + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PABIAS); + //if(pHalData->eRFPowerState == eRfOn) + { + _InitPABias(padapter); + } + + // Init BT hw config. +// HALBT_InitHwConfig(padapter); + + +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC31); + // 2010/05/20 MH We need to init timer after update setting. Otherwise, we can not get correct inf setting. + // 2010/05/18 MH For SE series only now. Init GPIO detect time +#if 0 + if(pDevice->RegUsbSS) + { + RT_TRACE(COMP_INIT, DBG_LOUD, (" call GpioDetectTimerStart\n")); + GpioDetectTimerStart(padapter); // Disable temporarily + } +#endif + + // 2010/08/23 MH According to Alfred's suggestion, we need to to prevent HW enter + // suspend mode automatically. + //HwSuspendModeEnable92Cu(padapter, FALSE); + + // 2010/12/17 MH For TX power level OID modification from UI. +// padapter->HalFunc.GetTxPowerLevelHandler( padapter, &pHalData->DefaultTxPwrDbm ); + //DbgPrint("pHalData->DefaultTxPwrDbm = %d\n", pHalData->DefaultTxPwrDbm); + +// if(pHalData->SwBeaconType < HAL92CSDIO_DEFAULT_BEACON_TYPE) // The lowest Beacon Type that HW can support +// pHalData->SwBeaconType = HAL92CSDIO_DEFAULT_BEACON_TYPE; + + // + // Update current Tx FIFO page status. + // + HalQueryTxBufferStatus8189ESdio(padapter); + + + if(pregistrypriv->wifi_spec) + rtw_write16(padapter,REG_FAST_EDCA_CTRL ,0); + + + //TODO:Setting HW_VAR_NAV_UPPER !!!!!!!!!!!!!!!!!!!! + //rtw_hal_set_hwreg(Adapter, HW_VAR_NAV_UPPER, ((pu1Byte)&NavUpper)); + + if(IS_HARDWARE_TYPE_8188ES(padapter)) + { + value8= rtw_read8(padapter, 0x4d3); + rtw_write8(padapter, 0x4d3, (value8|0x1)); + } + + //pHalData->PreRpwmVal = PlatformEFSdioLocalCmd52Read1Byte(Adapter, SDIO_REG_HRPWM1)&0x80; + + + // enable Tx report. + rtw_write8(padapter, REG_FWHW_TXQ_CTRL+1, 0x0F); +/* + // Suggested by SD1 pisa. Added by tynli. 2011.10.21. + PlatformEFIOWrite1Byte(Adapter, REG_EARLY_MODE_CONTROL+3, 0x01); + +*/ //tynli_test_tx_report. + rtw_write16(padapter, REG_TX_RPT_TIME, 0x3DF0); + //RT_TRACE(COMP_INIT, DBG_TRACE, ("InitializeAdapter8188EUsb() <====\n")); + + + //enable tx DMA to drop the redundate data of packet + rtw_write16(padapter,REG_TXDMA_OFFSET_CHK, (rtw_read16(padapter,REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN)); + +//#debug print for checking compile flags + //DBG_8192C("RTL8188E_FPGA_TRUE_PHY_VERIFICATION=%d\n", RTL8188E_FPGA_TRUE_PHY_VERIFICATION); + DBG_8192C("DISABLE_BB_RF=%d\n", DISABLE_BB_RF); + DBG_8192C("IS_HARDWARE_TYPE_8188ES=%d\n", IS_HARDWARE_TYPE_8188ES(padapter)); +//# + +#ifdef CONFIG_PLATFORM_SPRD + // For Power Consumption, set all GPIO pin to ouput mode + //0x44~0x47 (GPIO 0~7), Note:GPIO5 is enabled for controlling external 26MHz request + rtw_write8(padapter, GPIO_IO_SEL, 0xFF);//Reg0x46, set to o/p mode + + //0x42~0x43 (GPIO 8~11) + value8 = rtw_read8(padapter, REG_GPIO_IO_SEL); + rtw_write8(padapter, REG_GPIO_IO_SEL, (value8<<4)|value8); + value8 = rtw_read8(padapter, REG_GPIO_IO_SEL+1); + rtw_write8(padapter, REG_GPIO_IO_SEL+1, value8|0x0F);//Reg0x43 +#endif //CONFIG_PLATFORM_SPRD + + +#ifdef CONFIG_XMIT_ACK + //ack for xmit mgmt frames. + rtw_write32(padapter, REG_FWHW_TXQ_CTRL, rtw_read32(padapter, REG_FWHW_TXQ_CTRL)|BIT(12)); +#endif //CONFIG_XMIT_ACK + + + + //RT_TRACE(COMP_INIT, DBG_LOUD, ("<---Initializepadapter8192CSdio()\n")); + DBG_8192C("-rtl8188es_hal_init\n"); + +exit: +HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END); + + DBG_871X("%s in %dms\n", __FUNCTION__, rtw_get_passing_time_ms(init_start_time)); + + #ifdef DBG_HAL_INIT_PROFILING + hal_init_stages_timestamp[HAL_INIT_STAGES_END]=rtw_get_current_time(); + + for(hal_init_profiling_i=0;hal_init_profiling_i<HAL_INIT_STAGES_NUM-1;hal_init_profiling_i++) { + DBG_871X("DBG_HAL_INIT_PROFILING: %35s, %u, %5u, %5u\n" + , hal_init_stages_str[hal_init_profiling_i] + , hal_init_stages_timestamp[hal_init_profiling_i] + , (hal_init_stages_timestamp[hal_init_profiling_i+1]-hal_init_stages_timestamp[hal_init_profiling_i]) + , rtw_get_time_interval_ms(hal_init_stages_timestamp[hal_init_profiling_i], hal_init_stages_timestamp[hal_init_profiling_i+1]) + ); + } + #endif + + return ret; + +} + +static void CardDisableRTL8188ESdio(PADAPTER padapter) +{ + u8 u1bTmp; + u16 u2bTmp; + u32 u4bTmp; + u8 bMacPwrCtrlOn; + u8 ret; +#ifdef CONFIG_PLATFORM_SPRD + struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; +#endif //CONFIG_PLATFORM_SPRD + + DBG_871X("=>%s\n", __FUNCTION__); + + + //Stop Tx Report Timer. 0x4EC[Bit1]=b'0 + u1bTmp = rtw_read8(padapter, REG_TX_RPT_CTRL); + rtw_write8(padapter, REG_TX_RPT_CTRL, u1bTmp&(~BIT1)); + + // stop rx + rtw_write8(padapter,REG_CR, 0x0); + + +#ifdef CONFIG_EXT_CLK //for sprd For Power Consumption. + EnableGpio5ClockReq(padapter, _FALSE, 0); +#endif //CONFIG_EXT_CLK + +#if 1 + // For Power Consumption. + u1bTmp = rtw_read8(padapter, GPIO_IN); + rtw_write8(padapter, GPIO_OUT, u1bTmp); + rtw_write8(padapter, GPIO_IO_SEL, 0xFF);//Reg0x46 + + u1bTmp = rtw_read8(padapter, REG_GPIO_IO_SEL); + rtw_write8(padapter, REG_GPIO_IO_SEL, (u1bTmp<<4)|u1bTmp); + u1bTmp = rtw_read8(padapter, REG_GPIO_IO_SEL+1); + rtw_write8(padapter, REG_GPIO_IO_SEL+1, u1bTmp|0x0F);//Reg0x43 +#endif + + + // Run LPS WL RFOFF flow + ret = HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, Rtl8188E_NIC_LPS_ENTER_FLOW); + if (ret == _FALSE) { + DBG_871X("%s: run RF OFF flow fail!\n", __func__); + } + + // ==== Reset digital sequence ====== + + u1bTmp = rtw_read8(padapter, REG_MCUFWDL); + if ((u1bTmp & RAM_DL_SEL) && padapter->bFWReady) //8051 RAM code + { + //rtl8723a_FirmwareSelfReset(padapter); + //_8051Reset88E(padapter); + + // Reset MCU 0x2[10]=0. + u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1); + u1bTmp &= ~BIT(2); // 0x2[10], FEN_CPUEN + rtw_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp); + } + + //u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1); + //u1bTmp &= ~BIT(2); // 0x2[10], FEN_CPUEN + //rtw_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp); + + // MCUFWDL 0x80[1:0]=0 + // reset MCU ready status + rtw_write8(padapter, REG_MCUFWDL, 0); + + //==== Reset digital sequence end ====== + + + bMacPwrCtrlOn = _FALSE; // Disable CMD53 R/W + rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + + +/* + if((pMgntInfo->RfOffReason & RF_CHANGE_BY_HW) && pHalData->pwrdown) + {// Power Down + + // Card disable power action flow + ret = HalPwrSeqCmdParsing(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, Rtl8188E_NIC_PDN_FLOW); + } + else +*/ +#ifdef CONFIG_PLATFORM_SPRD + // for sprd, it will enable power down mode when enter suspend and remove driver, so needn't call card disable flow. + //if(pwrpriv->bInSuspend != _TRUE) + if(pwrpriv->bpower_saving == _TRUE) // when bpower_saving == _TRUE at this moment is only indicate driver is going to IPS Mode. +#endif //CONFIG_PLATFORM_SPRD + { // Non-Power Down + + // Card disable power action flow + ret = HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, Rtl8188E_NIC_DISABLE_FLOW); + + + if (ret == _FALSE) { + DBG_871X("%s: run CARD DISABLE flow fail!\n", __func__); + } + } + + +/* + // Reset MCU IO Wrapper, added by Roger, 2011.08.30 + u1bTmp = rtw_read8(padapter, REG_RSV_CTRL+1); + u1bTmp &= ~BIT(0); + rtw_write8(padapter, REG_RSV_CTRL+1, u1bTmp); + u1bTmp = rtw_read8(padapter, REG_RSV_CTRL+1); + u1bTmp |= BIT(0); + rtw_write8(padapter, REG_RSV_CTRL+1, u1bTmp); +*/ + + + // RSV_CTRL 0x1C[7:0]=0x0E + // lock ISO/CLK/Power control register + rtw_write8(padapter, REG_RSV_CTRL, 0x0E); + + padapter->bFWReady = _FALSE; + DBG_871X("<=%s\n", __FUNCTION__); + +} + +static u32 rtl8188es_hal_deinit(PADAPTER padapter) +{ + DBG_871X("=>%s\n", __FUNCTION__); + + if (padapter->hw_init_completed == _TRUE) + CardDisableRTL8188ESdio(padapter); + + DBG_871X("<=%s\n", __FUNCTION__); + + return _SUCCESS; +} + +static u32 rtl8188es_inirp_init(PADAPTER padapter) +{ + u32 status; + +_func_enter_; + + status = _SUCCESS; + +_func_exit_; + + return status; +} + +static u32 rtl8188es_inirp_deinit(PADAPTER padapter) +{ + RT_TRACE(_module_hci_hal_init_c_,_drv_info_,("+rtl8188es_inirp_deinit\n")); + + RT_TRACE(_module_hci_hal_init_c_,_drv_info_,("-rtl8188es_inirp_deinit\n")); + + return _SUCCESS; +} + +static void rtl8188es_init_default_value(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData; + struct pwrctrl_priv *pwrctrlpriv; + struct dm_priv *pdmpriv; + u8 i; + + pHalData = GET_HAL_DATA(padapter); + pwrctrlpriv = &padapter->pwrctrlpriv; + pdmpriv = &pHalData->dmpriv; + + + //init default value + pHalData->fw_ractrl = _FALSE; + if(!pwrctrlpriv->bkeepfwalive) + pHalData->LastHMEBoxNum = 0; + + //init dm default value + pHalData->odmpriv.RFCalibrateInfo.bIQKInitialized = _FALSE; + pHalData->odmpriv.RFCalibrateInfo.TM_Trigger = 0;//for IQK + //pdmpriv->binitialized = _FALSE; +// pdmpriv->prv_traffic_idx = 3; +// pdmpriv->initialize = 0; + pHalData->pwrGroupCnt = 0; + pHalData->PGMaxGroup= 13; + pHalData->odmpriv.RFCalibrateInfo.ThermalValue_HP_index = 0; + for(i = 0; i < HP_THERMAL_NUM; i++) + pHalData->odmpriv.RFCalibrateInfo.ThermalValue_HP[i] = 0; + + // interface related variable + pHalData->SdioRxFIFOCnt = 0; +} + +// +// Description: +// We should set Efuse cell selection to WiFi cell in default. +// +// Assumption: +// PASSIVE_LEVEL +// +// Added by Roger, 2010.11.23. +// +static void _EfuseCellSel( + IN PADAPTER padapter + ) +{ + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + u32 value32; + + //if(INCLUDE_MULTI_FUNC_BT(padapter)) + { + value32 = rtw_read32(padapter, EFUSE_TEST); + value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0); + rtw_write32(padapter, EFUSE_TEST, value32); + } +} + +static VOID +_ReadRFType( + IN PADAPTER Adapter + ) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + +#if DISABLE_BB_RF + pHalData->rf_chip = RF_PSEUDO_11N; +#else + pHalData->rf_chip = RF_6052; +#endif +} + +static void +Hal_EfuseParsePIDVID_8188ES( + IN PADAPTER pAdapter, + IN u8* hwinfo, + IN BOOLEAN AutoLoadFail + ) +{ +// HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + // + // <Roger_Notes> The PID/VID info was parsed from CISTPL_MANFID Tuple in CIS area before. + // VID is parsed from Manufacture code field and PID is parsed from Manufacture information field. + // 2011.04.01. + // + +// RT_TRACE(COMP_INIT, DBG_LOUD, ("EEPROM VID = 0x%4x\n", pHalData->EEPROMVID)); +// RT_TRACE(COMP_INIT, DBG_LOUD, ("EEPROM PID = 0x%4x\n", pHalData->EEPROMPID)); +} + +static void +Hal_EfuseParseMACAddr_8188ES( + IN PADAPTER padapter, + IN u8* hwinfo, + IN BOOLEAN AutoLoadFail + ) +{ + u16 i, usValue; + u8 sMacAddr[6] = {0x00, 0xE0, 0x4C, 0x81, 0x88, 0x77}; + EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + + if (AutoLoadFail) + { +// sMacAddr[5] = (u1Byte)GetRandomNumber(1, 254); + for (i=0; i<6; i++) + pEEPROM->mac_addr[i] = sMacAddr[i]; + } + else + { + //Read Permanent MAC address + _rtw_memcpy(pEEPROM->mac_addr, &hwinfo[EEPROM_MAC_ADDR_88ES], ETH_ALEN); + + } +// NicIFSetMacAddress(pAdapter, pAdapter->PermanentAddress); + + DBG_871X("Hal_EfuseParseMACAddr_8188ES: Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + pEEPROM->mac_addr[0], pEEPROM->mac_addr[1], + pEEPROM->mac_addr[2], pEEPROM->mac_addr[3], + pEEPROM->mac_addr[4], pEEPROM->mac_addr[5]); +} + + +#ifdef CONFIG_EFUSE_CONFIG_FILE +static u32 Hal_readPGDataFromConfigFile( + PADAPTER padapter) +{ + u32 i; + struct file *fp; + mm_segment_t fs; + u8 temp[3]; + loff_t pos = 0; + EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + u8 *PROMContent = pEEPROM->efuse_eeprom_data; + + + temp[2] = 0; // add end of string '\0' + + fp = filp_open("/system/etc/wifi/wifi_efuse.map", O_RDWR, 0644); + if (IS_ERR(fp)) { + pEEPROM->bloadfile_fail_flag = _TRUE; + DBG_871X("Error, Efuse configure file doesn't exist.\n"); + return _FAIL; + } + + fs = get_fs(); + set_fs(KERNEL_DS); + + DBG_871X("Efuse configure file:\n"); + for (i=0; i<HWSET_MAX_SIZE_88E; i++) { + vfs_read(fp, temp, 2, &pos); + PROMContent[i] = simple_strtoul(temp, NULL, 16 ); + pos += 1; // Filter the space character + DBG_871X("%02X \n", PROMContent[i]); + } + DBG_871X("\n"); + set_fs(fs); + + filp_close(fp, NULL); + pEEPROM->bloadfile_fail_flag = _FALSE; + return _SUCCESS; +} + +static void +Hal_ReadMACAddrFromFile_8188ES( + PADAPTER padapter + ) +{ + u32 i; + struct file *fp; + mm_segment_t fs; + u8 source_addr[18]; + loff_t pos = 0; + u32 curtime = rtw_get_current_time(); + EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + u8 *head, *end; + + u8 null_mac_addr[ETH_ALEN] = {0, 0, 0,0, 0, 0}; + u8 multi_mac_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + _rtw_memset(source_addr, 0, 18); + _rtw_memset(pEEPROM->mac_addr, 0, ETH_ALEN); + + fp = filp_open("/data/wifimac.txt", O_RDWR, 0644); + if (IS_ERR(fp)) { + pEEPROM->bloadmac_fail_flag = _TRUE; + DBG_871X("Error, wifi mac address file doesn't exist.\n"); + } else { + fs = get_fs(); + set_fs(KERNEL_DS); + + DBG_871X("wifi mac address:\n"); + vfs_read(fp, source_addr, 18, &pos); + source_addr[17] = ':'; + + head = end = source_addr; + for (i=0; i<ETH_ALEN; i++) { + while (end && (*end != ':') ) + end++; + + if (end && (*end == ':') ) + *end = '\0'; + + pEEPROM->mac_addr[i] = simple_strtoul(head, NULL, 16 ); + + if (end) { + end++; + head = end; + } + DBG_871X("%02x \n", pEEPROM->mac_addr[i]); + } + DBG_871X("\n"); + set_fs(fs); + pEEPROM->bloadmac_fail_flag = _FALSE; + filp_close(fp, NULL); + } + + if ( (_rtw_memcmp(pEEPROM->mac_addr, null_mac_addr, ETH_ALEN)) || + (_rtw_memcmp(pEEPROM->mac_addr, multi_mac_addr, ETH_ALEN)) ) { + pEEPROM->mac_addr[0] = 0x00; + pEEPROM->mac_addr[1] = 0xe0; + pEEPROM->mac_addr[2] = 0x4c; + pEEPROM->mac_addr[3] = (u8)(curtime & 0xff) ; + pEEPROM->mac_addr[4] = (u8)((curtime>>8) & 0xff) ; + pEEPROM->mac_addr[5] = (u8)((curtime>>16) & 0xff) ; + } + + DBG_871X("Hal_ReadMACAddrFromFile_8188ES: Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + pEEPROM->mac_addr[0], pEEPROM->mac_addr[1], + pEEPROM->mac_addr[2], pEEPROM->mac_addr[3], + pEEPROM->mac_addr[4], pEEPROM->mac_addr[5]); +} +#endif //CONFIG_EFUSE_CONFIG_FILE + +static VOID +readAdapterInfo_8188ES( + IN PADAPTER padapter + ) +{ + EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + + /* parse the eeprom/efuse content */ + Hal_EfuseParseIDCode88E(padapter, pEEPROM->efuse_eeprom_data); + Hal_EfuseParsePIDVID_8188ES(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + +#ifdef CONFIG_EFUSE_CONFIG_FILE + Hal_ReadMACAddrFromFile_8188ES(padapter); +#else //CONFIG_EFUSE_CONFIG_FILE + Hal_EfuseParseMACAddr_8188ES(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); +#endif //CONFIG_EFUSE_CONFIG_FILE + + Hal_ReadPowerSavingMode88E(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + Hal_ReadTxPowerInfo88E(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + Hal_EfuseParseEEPROMVer88E(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + rtl8188e_EfuseParseChnlPlan(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + Hal_EfuseParseXtal_8188E(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + Hal_EfuseParseCustomerID88E(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + //Hal_ReadAntennaDiversity88E(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + Hal_EfuseParseBoardType88E(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + Hal_ReadThermalMeter_88E(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); + // + // The following part initialize some vars by PG info. + // + Hal_InitChannelPlan(padapter); +#ifdef CONFIG_WOWLAN + Hal_DetectWoWMode(padapter); +#endif //CONFIG_WOWLAN +#ifdef CONFIG_RF_GAIN_OFFSET + Hal_ReadRFGainOffset(padapter, pEEPROM->efuse_eeprom_data, pEEPROM->bautoload_fail_flag); +#endif //CONFIG_RF_GAIN_OFFSET +} + +static void _ReadPROMContent( + IN PADAPTER padapter + ) +{ + EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + u8 eeValue; + + /* check system boot selection */ + eeValue = rtw_read8(padapter, REG_9346CR); + pEEPROM->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? _TRUE : _FALSE; + pEEPROM->bautoload_fail_flag = (eeValue & EEPROM_EN) ? _FALSE : _TRUE; + + DBG_871X("%s: 9346CR=0x%02X, Boot from %s, Autoload %s\n", + __FUNCTION__, eeValue, + (pEEPROM->EepromOrEfuse ? "EEPROM" : "EFUSE"), + (pEEPROM->bautoload_fail_flag ? "Fail" : "OK")); + +// pHalData->EEType = IS_BOOT_FROM_EEPROM(Adapter) ? EEPROM_93C46 : EEPROM_BOOT_EFUSE; + +#ifdef CONFIG_EFUSE_CONFIG_FILE + Hal_readPGDataFromConfigFile(padapter); +#else //CONFIG_EFUSE_CONFIG_FILE + Hal_InitPGData88E(padapter); +#endif //CONFIG_EFUSE_CONFIG_FILE + readAdapterInfo_8188ES(padapter); +} + +static VOID +_InitOtherVariable( + IN PADAPTER Adapter + ) +{ + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + + //if(Adapter->bInHctTest){ + // pMgntInfo->PowerSaveControl.bInactivePs = FALSE; + // pMgntInfo->PowerSaveControl.bIPSModeBackup = FALSE; + // pMgntInfo->PowerSaveControl.bLeisurePs = FALSE; + // pMgntInfo->keepAliveLevel = 0; + //} + + +} + +// +// Description: +// Read HW adapter information by E-Fuse or EEPROM according CR9346 reported. +// +// Assumption: +// PASSIVE_LEVEL (SDIO interface) +// +// +static s32 _ReadAdapterInfo8188ES(PADAPTER padapter) +{ + u32 start; + + + RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+_ReadAdapterInfo8188ES\n")); + + // before access eFuse, make sure card enable has been called + if(_CardEnable(padapter) == _FAIL) + { + DBG_871X(KERN_ERR "%s: run power on flow fail\n", __func__); + return _FAIL; + } + + start = rtw_get_current_time(); + +// Efuse_InitSomeVar(Adapter); +// pHalData->VersionID = ReadChipVersion(Adapter); +// _EfuseCellSel(padapter); + + _ReadRFType(padapter);//rf_chip -> _InitRFType() + _ReadPROMContent(padapter); + + // 2010/10/25 MH THe function must be called after borad_type & IC-Version recognize. + //ReadSilmComboMode(Adapter); + _InitOtherVariable(padapter); + + + //MSG_8192C("%s()(done), rf_chip=0x%x, rf_type=0x%x\n", __FUNCTION__, pHalData->rf_chip, pHalData->rf_type); + MSG_8192C("<==== ReadAdapterInfo8188ES in %d ms\n", rtw_get_passing_time_ms(start)); + + return _SUCCESS; +} + +static void ReadAdapterInfo8188ES(PADAPTER padapter) +{ + // Read EEPROM size before call any EEPROM function + padapter->EepromAddressSize = GetEEPROMSize8188E(padapter); + + _ReadAdapterInfo8188ES(padapter); +} + +static void ResumeTxBeacon(PADAPTER padapter) +{ + HAL_DATA_TYPE* pHalData = GET_HAL_DATA(padapter); + + // 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value + // which should be read from register to a global variable. + + RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+ResumeTxBeacon\n")); + + rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl) | BIT6); + pHalData->RegFwHwTxQCtrl |= BIT6; + rtw_write8(padapter, REG_TBTT_PROHIBIT+1, 0xff); + pHalData->RegReg542 |= BIT0; + rtw_write8(padapter, REG_TBTT_PROHIBIT+2, pHalData->RegReg542); +} + +static void StopTxBeacon(PADAPTER padapter) +{ + HAL_DATA_TYPE* pHalData = GET_HAL_DATA(padapter); + + // 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value + // which should be read from register to a global variable. + + RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+StopTxBeacon\n")); + + rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl) & (~BIT6)); + pHalData->RegFwHwTxQCtrl &= (~BIT6); + rtw_write8(padapter, REG_TBTT_PROHIBIT+1, 0x64); + pHalData->RegReg542 &= ~(BIT0); + rtw_write8(padapter, REG_TBTT_PROHIBIT+2, pHalData->RegReg542); + + CheckFwRsvdPageContent(padapter); // 2010.06.23. Added by tynli. +} + +// todo static +void hw_var_set_opmode(PADAPTER Adapter, u8 variable, u8* val) +{ + u8 val8; + u8 mode = *((u8 *)val); + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + +#ifdef CONFIG_CONCURRENT_MODE + if(Adapter->iface_type == IFACE_PORT1) + { + // disable Port1 TSF update + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)|BIT(4)); + + // set net_type + val8 = rtw_read8(Adapter, MSR)&0x03; + val8 |= (mode<<2); + rtw_write8(Adapter, MSR, val8); + + DBG_871X("%s()-%d mode = %d\n", __FUNCTION__, __LINE__, mode); + + if((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) + { + if(!check_buddy_mlmeinfo_state(Adapter, WIFI_FW_AP_STATE)) + { + #ifdef CONFIG_INTERRUPT_BASED_TXBCN + + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + rtw_write8(Adapter, REG_DRVERLYINT, 0x05);//restore early int time to 5ms + UpdateInterruptMask8188ESdio(Adapter, 0, SDIO_HIMR_BCNERLY_INT_MSK); + #endif // CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + UpdateInterruptMask8188ESdio(Adapter, 0, (SDIO_HIMR_TXBCNOK_MSK|SDIO_HIMR_TXBCNERR_MSK)); + #endif// CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + + #endif //CONFIG_INTERRUPT_BASED_TXBCN + + + StopTxBeacon(Adapter); + } + + rtw_write8(Adapter,REG_BCN_CTRL_1, 0x19);//disable atim wnd + //rtw_write8(Adapter,REG_BCN_CTRL_1, 0x18); + } + else if((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_)*/) + { + ResumeTxBeacon(Adapter); + rtw_write8(Adapter,REG_BCN_CTRL_1, 0x1a); + } + else if(mode == _HW_STATE_AP_) + { +#ifdef CONFIG_INTERRUPT_BASED_TXBCN + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + UpdateInterruptMask8188ESdio(Adapter, SDIO_HIMR_BCNERLY_INT_MSK, 0); + #endif//CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + UpdateInterruptMask8188ESdio(Adapter, (SDIO_HIMR_TXBCNOK_MSK|SDIO_HIMR_TXBCNERR_MSK), 0); + #endif//CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + +#endif //CONFIG_INTERRUPT_BASED_TXBCN + + ResumeTxBeacon(Adapter); + + rtw_write8(Adapter, REG_BCN_CTRL_1, 0x12); + + //enable SW Beacon + rtw_write32(Adapter, REG_CR, rtw_read32(Adapter, REG_CR)|BIT(8)); + + //Set RCR + //rtw_write32(padapter, REG_RCR, 0x70002a8e);//CBSSID_DATA must set to 0 + rtw_write32(Adapter, REG_RCR, 0x7000208e);//CBSSID_DATA must set to 0,Reject ICV_ERROR packets + + //enable to rx data frame + rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); + //enable to rx ps-poll + rtw_write16(Adapter, REG_RXFLTMAP1, 0x0400); + + //Beacon Control related register for first time + rtw_write8(Adapter, REG_BCNDMATIM, 0x02); // 2ms + + //rtw_write8(Adapter, REG_BCN_MAX_ERR, 0xFF); + rtw_write8(Adapter, REG_ATIMWND_1, 0x0a); // 10ms for port1 + rtw_write16(Adapter, REG_BCNTCFG, 0x00); + rtw_write16(Adapter, REG_TBTT_PROHIBIT, 0xff04); + rtw_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);// +32767 (~32ms) + + //reset TSF2 + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(1)); + + + //BIT4 - If set 0, hw will clr bcnq when tx becon ok/fail or port 1 + rtw_write8(Adapter, REG_MBID_NUM, rtw_read8(Adapter, REG_MBID_NUM)|BIT(3)|BIT(4)); + //enable BCN1 Function for if2 + //don't enable update TSF1 for if2 (due to TSF update when beacon/probe rsp are received) + rtw_write8(Adapter, REG_BCN_CTRL_1, (DIS_TSF_UDT0_NORMAL_CHIP|EN_BCN_FUNCTION | EN_TXBCN_RPT|BIT(1))); + +#ifdef CONFIG_CONCURRENT_MODE + if(check_buddy_fwstate(Adapter, WIFI_FW_NULL_STATE)) + rtw_write8(Adapter, REG_BCN_CTRL, + rtw_read8(Adapter, REG_BCN_CTRL) & ~EN_BCN_FUNCTION); +#endif + //BCN1 TSF will sync to BCN0 TSF with offset(0x518) if if1_sta linked + //rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)|BIT(5)); + //rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(3)); + + //dis BCN0 ATIM WND if if1 is station + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(0)); + +#ifdef CONFIG_TSF_RESET_OFFLOAD + // Reset TSF for STA+AP concurrent mode + if ( check_buddy_fwstate(Adapter, (WIFI_STATION_STATE|WIFI_ASOC_STATE)) ) { + if (reset_tsf(Adapter, IFACE_PORT1) == _FALSE) + DBG_871X("ERROR! %s()-%d: Reset port1 TSF fail\n", + __FUNCTION__, __LINE__); + } +#endif // CONFIG_TSF_RESET_OFFLOAD + } + } + else +#endif //CONFIG_CONCURRENT_MODE + { + // disable Port0 TSF update + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(4)); + + // set net_type + val8 = rtw_read8(Adapter, MSR)&0x0c; + val8 |= mode; + rtw_write8(Adapter, MSR, val8); + + DBG_871X("%s()-%d mode = %d\n", __FUNCTION__, __LINE__, mode); + + if((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) + { +#ifdef CONFIG_CONCURRENT_MODE + if(!check_buddy_mlmeinfo_state(Adapter, WIFI_FW_AP_STATE)) +#endif //CONFIG_CONCURRENT_MODE + { + #ifdef CONFIG_INTERRUPT_BASED_TXBCN + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + rtw_write8(Adapter, REG_DRVERLYINT, 0x05);//restore early int time to 5ms + UpdateInterruptMask8188ESdio(Adapter, 0, SDIO_HIMR_BCNERLY_INT_MSK); + #endif//CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + UpdateInterruptMask8188ESdio(Adapter, 0, (SDIO_HIMR_TXBCNOK_MSK|SDIO_HIMR_TXBCNERR_MSK)); + #endif //CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + #endif //CONFIG_INTERRUPT_BASED_TXBCN + StopTxBeacon(Adapter); + } + + rtw_write8(Adapter,REG_BCN_CTRL, 0x19);//disable atim wnd + //rtw_write8(Adapter,REG_BCN_CTRL, 0x18); + } + else if((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_)*/) + { + ResumeTxBeacon(Adapter); + rtw_write8(Adapter,REG_BCN_CTRL, 0x1a); + } + else if(mode == _HW_STATE_AP_) + { + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + UpdateInterruptMask8188ESdio(Adapter, SDIO_HIMR_BCNERLY_INT_MSK, 0); + #endif//CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + UpdateInterruptMask8188ESdio(Adapter, (SDIO_HIMR_TXBCNOK_MSK|SDIO_HIMR_TXBCNERR_MSK), 0); + #endif//CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR +#endif //CONFIG_INTERRUPT_BASED_TXBCN + + + ResumeTxBeacon(Adapter); + + rtw_write8(Adapter, REG_BCN_CTRL, 0x12); + + //enable SW Beacon + rtw_write32(Adapter, REG_CR, rtw_read32(Adapter, REG_CR)|BIT(8)); + + //Set RCR + //rtw_write32(padapter, REG_RCR, 0x70002a8e);//CBSSID_DATA must set to 0 + rtw_write32(Adapter, REG_RCR, 0x7000208e);//CBSSID_DATA must set to 0,reject ICV_ERR packet + //enable to rx data frame + rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); + //enable to rx ps-poll + rtw_write16(Adapter, REG_RXFLTMAP1, 0x0400); + + //Beacon Control related register for first time + rtw_write8(Adapter, REG_BCNDMATIM, 0x02); // 2ms + + //rtw_write8(Adapter, REG_BCN_MAX_ERR, 0xFF); + rtw_write8(Adapter, REG_ATIMWND, 0x0a); // 10ms + rtw_write16(Adapter, REG_BCNTCFG, 0x00); + rtw_write16(Adapter, REG_TBTT_PROHIBIT, 0xff04); + rtw_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);// +32767 (~32ms) + + //reset TSF + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(0)); + + //BIT3 - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 + rtw_write8(Adapter, REG_MBID_NUM, rtw_read8(Adapter, REG_MBID_NUM)|BIT(3)|BIT(4)); + + //enable BCN0 Function for if1 + //don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) + rtw_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP|EN_BCN_FUNCTION | EN_TXBCN_RPT|BIT(1))); + +#ifdef CONFIG_CONCURRENT_MODE + if(check_buddy_fwstate(Adapter, WIFI_FW_NULL_STATE)) + rtw_write8(Adapter, REG_BCN_CTRL_1, + rtw_read8(Adapter, REG_BCN_CTRL_1) & ~EN_BCN_FUNCTION); +#endif + + //dis BCN1 ATIM WND if if2 is station + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)|BIT(0)); +#ifdef CONFIG_TSF_RESET_OFFLOAD + // Reset TSF for STA+AP concurrent mode + if ( check_buddy_fwstate(Adapter, (WIFI_STATION_STATE|WIFI_ASOC_STATE)) ) { + if (reset_tsf(Adapter, IFACE_PORT0) == _FALSE) + DBG_871X("ERROR! %s()-%d: Reset port0 TSF fail\n", + __FUNCTION__, __LINE__); + } +#endif // CONFIG_TSF_RESET_OFFLOAD + } + } + +} + +static void hw_var_set_macaddr(PADAPTER Adapter, u8 variable, u8* val) +{ + u8 idx = 0; + u32 reg_macid; + +#ifdef CONFIG_CONCURRENT_MODE + if(Adapter->iface_type == IFACE_PORT1) + { + reg_macid = REG_MACID1; + } + else +#endif + { + reg_macid = REG_MACID; + } + + for(idx = 0 ; idx < 6; idx++) + { + rtw_write8(Adapter, (reg_macid+idx), val[idx]); + } + +} + +static void hw_var_set_bssid(PADAPTER Adapter, u8 variable, u8* val) +{ + u8 idx = 0; + u32 reg_bssid; + + +#ifdef CONFIG_CONCURRENT_MODE + if(Adapter->iface_type == IFACE_PORT1) + { + reg_bssid = REG_BSSID1; + } + else +#endif + { + reg_bssid = REG_BSSID; + } + +printk("hw_var_set_bssid reg=%x \n", reg_bssid); + + for(idx = 0 ; idx < 6; idx++) + { + rtw_write8(Adapter, (reg_bssid+idx), val[idx]); + } + +} + +static void hw_var_set_bcn_func(PADAPTER Adapter, u8 variable, u8* val) +{ + u32 bcn_ctrl_reg; + +#ifdef CONFIG_CONCURRENT_MODE + if(Adapter->iface_type == IFACE_PORT1) + { + bcn_ctrl_reg = REG_BCN_CTRL_1; + } + else +#endif + { + bcn_ctrl_reg = REG_BCN_CTRL; + } + + if(*((u8 *)val)) + { + rtw_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT)); + } + else + { + rtw_write8(Adapter, bcn_ctrl_reg, rtw_read8(Adapter, bcn_ctrl_reg)&(~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); + } + + +} + +static void hw_var_set_correct_tsf(PADAPTER Adapter, u8 variable, u8* val) +{ +#ifdef CONFIG_CONCURRENT_MODE + u64 tsf; + struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + PADAPTER pbuddy_adapter = Adapter->pbuddy_adapter; + + //tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue % (pmlmeinfo->bcn_interval*1024)) -1024; //us + tsf = pmlmeext->TSFValue - rtw_modular64(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) -1024; //us + + if(((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) + { + //pHalData->RegTxPause |= STOP_BCNQ;BIT(6) + //rtw_write8(Adapter, REG_TXPAUSE, (rtw_read8(Adapter, REG_TXPAUSE)|BIT(6))); + StopTxBeacon(Adapter); + } + + if(Adapter->iface_type == IFACE_PORT1) + { + //disable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)&(~BIT(3))); + + rtw_write32(Adapter, REG_TSFTR1, tsf); + rtw_write32(Adapter, REG_TSFTR1+4, tsf>>32); + //enable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)|BIT(3)); + // Update buddy port's TSF if it is SoftAP for beacon TX issue! + if ( (pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE + && check_buddy_fwstate(Adapter, WIFI_AP_STATE) + ) { + //disable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(3))); + + rtw_write32(Adapter, REG_TSFTR, tsf); + rtw_write32(Adapter, REG_TSFTR+4, tsf>>32); + + //enable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(3)); +#ifdef CONFIG_TSF_RESET_OFFLOAD + // Update buddy port's TSF(TBTT) if it is SoftAP for beacon TX issue! + if (reset_tsf(Adapter, IFACE_PORT0) == _FALSE) + DBG_871X("ERROR! %s()-%d: Reset port0 TSF fail\n", + __FUNCTION__, __LINE__); + +#endif // CONFIG_TSF_RESET_OFFLOAD + } + + } + else + { + //disable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(3))); + + rtw_write32(Adapter, REG_TSFTR, tsf); + rtw_write32(Adapter, REG_TSFTR+4, tsf>>32); + + //enable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(3)); + // Update buddy port's TSF if it is SoftAP for beacon TX issue! + if ( (pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE + && check_buddy_fwstate(Adapter, WIFI_AP_STATE) + ) { + //disable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)&(~BIT(3))); + + rtw_write32(Adapter, REG_TSFTR1, tsf); + rtw_write32(Adapter, REG_TSFTR1+4, tsf>>32); + + //enable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)|BIT(3)); +#ifdef CONFIG_TSF_RESET_OFFLOAD + // Update buddy port's TSF if it is SoftAP for beacon TX issue! + if (reset_tsf(Adapter, IFACE_PORT1) == _FALSE) + DBG_871X("ERROR! %s()-%d: Reset port1 TSF fail\n", + __FUNCTION__, __LINE__); +#endif // CONFIG_TSF_RESET_OFFLOAD + } + } + + + if(((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) + { + //pHalData->RegTxPause &= (~STOP_BCNQ); + //rtw_write8(Adapter, REG_TXPAUSE, (rtw_read8(Adapter, REG_TXPAUSE)&(~BIT(6)))); + ResumeTxBeacon(Adapter); + } +#endif +} + +static void hw_var_set_mlme_disconnect(PADAPTER Adapter, u8 variable, u8* val) +{ +#ifdef CONFIG_CONCURRENT_MODE + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + PADAPTER pbuddy_adapter = Adapter->pbuddy_adapter; + + + if(check_buddy_mlmeinfo_state(Adapter, _HW_STATE_NOLINK_)) + rtw_write16(Adapter, REG_RXFLTMAP2, 0x00); + + + if(Adapter->iface_type == IFACE_PORT1) + { + //reset TSF1 + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(1)); + + //disable update TSF1 + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)|BIT(4)); + } + else + { + //reset TSF + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(0)); + + //disable update TSF + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(4)); + } +#endif +} + +static void hw_var_set_mlme_sitesurvey(PADAPTER Adapter, u8 variable, u8* val) +{ +#ifdef CONFIG_CONCURRENT_MODE + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + if(*((u8 *)val))//under sitesurvey + { + //config RCR to receive different BSSID & not to receive data frame + u32 v = rtw_read32(Adapter, REG_RCR); + v &= ~(RCR_CBSSID_BCN); + rtw_write32(Adapter, REG_RCR, v); + + //disable update TSF + if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) + { + if(Adapter->iface_type == IFACE_PORT1) + { + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)|BIT(4)); + } + else + { + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(4)); + } + } + + if(check_buddy_mlmeinfo_state(Adapter, WIFI_FW_AP_STATE) && + check_buddy_fwstate(Adapter, _FW_LINKED)) + { + StopTxBeacon(Adapter); + } + + } + else//sitesurvey done + { + //enable to rx data frame + //write32(Adapter, REG_RCR, read32(padapter, REG_RCR)|RCR_ADF); + rtw_write16(Adapter, REG_RXFLTMAP2,0xFFFF); + + //enable update TSF + if(Adapter->iface_type == IFACE_PORT1) + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)&(~BIT(4))); + else + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); + + if(check_buddy_mlmeinfo_state(Adapter, WIFI_FW_AP_STATE) && + check_buddy_fwstate(Adapter, _FW_LINKED)) + { + ResumeTxBeacon(Adapter); + } + + } +#endif +} + +static void hw_var_set_mlme_join(PADAPTER Adapter, u8 variable, u8* val) +{ +#ifdef CONFIG_CONCURRENT_MODE + u8 RetryLimit = 0x30; + u8 type = *((u8 *)val); + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + + if(type == 0) // prepare to join + { + if(check_buddy_mlmeinfo_state(Adapter, WIFI_FW_AP_STATE) && + check_buddy_fwstate(Adapter, _FW_LINKED)) + { + StopTxBeacon(Adapter); + } + + //enable to rx data frame.Accept all data frame + //rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); + rtw_write16(Adapter, REG_RXFLTMAP2,0xFFFF); + + if(check_buddy_mlmeinfo_state(Adapter, WIFI_FW_AP_STATE)) + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); + else + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + + if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) + { + RetryLimit = (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48; + } + else // Ad-hoc Mode + { + RetryLimit = 0x7; + } + } + else if(type == 1) //joinbss_event call back when join res < 0 + { + if(check_buddy_mlmeinfo_state(Adapter, _HW_STATE_NOLINK_)) + rtw_write16(Adapter, REG_RXFLTMAP2,0x00); + + if(check_buddy_mlmeinfo_state(Adapter, WIFI_FW_AP_STATE) && + check_buddy_fwstate(Adapter, _FW_LINKED)) + { + ResumeTxBeacon(Adapter); + + //reset TSF 1/2 after ResumeTxBeacon + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(1)|BIT(0)); + + } + } + else if(type == 2) //sta add event call back + { + + //enable update TSF + if(Adapter->iface_type == IFACE_PORT1) + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)&(~BIT(4))); + else + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + + + if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) + { + //fixed beacon issue for 8191su........... + rtw_write8(Adapter,0x542 ,0x02); + RetryLimit = 0x7; + } + + + if(check_buddy_mlmeinfo_state(Adapter, WIFI_FW_AP_STATE) && + check_buddy_fwstate(Adapter, _FW_LINKED)) + { + ResumeTxBeacon(Adapter); + + //reset TSF 1/2 after ResumeTxBeacon + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(1)|BIT(0)); + } + + } + + rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); + +#endif +} +static void SetHwReg8188ES(PADAPTER Adapter, u8 variable, u8* val) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct dm_priv *pdmpriv = &pHalData->dmpriv; + DM_ODM_T *podmpriv = &pHalData->odmpriv; +_func_enter_; + + switch(variable) + { + case HW_VAR_MEDIA_STATUS: + { + u8 val8; + + val8 = rtw_read8(Adapter, MSR)&0x0c; + val8 |= *((u8 *)val); + rtw_write8(Adapter, MSR, val8); + } + break; + case HW_VAR_MEDIA_STATUS1: + { + u8 val8; + + val8 = rtw_read8(Adapter, MSR)&0x03; + val8 |= *((u8 *)val) <<2; + rtw_write8(Adapter, MSR, val8); + } + break; + case HW_VAR_SET_OPMODE: + hw_var_set_opmode(Adapter, variable, val); + break; + case HW_VAR_MAC_ADDR: + hw_var_set_macaddr(Adapter, variable, val); + break; + case HW_VAR_BSSID: + hw_var_set_bssid(Adapter, variable, val); + break; + case HW_VAR_BASIC_RATE: + { + u16 BrateCfg = 0; + u8 RateIndex = 0; + + // 2007.01.16, by Emily + // Select RRSR (in Legacy-OFDM and CCK) + // For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, and 1M from the Basic rate. + // We do not use other rates. + HalSetBrateCfg( Adapter, val, &BrateCfg ); + DBG_8192C("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", BrateCfg); + + //2011.03.30 add by Luke Lee + //CCK 2M ACK should be disabled for some BCM and Atheros AP IOT + //because CCK 2M has poor TXEVM + //CCK 5.5M & 11M ACK should be enabled for better performance + + pHalData->BasicRateSet = BrateCfg = (BrateCfg |0xd) & 0x15d; + + BrateCfg |= 0x01; // default enable 1M ACK rate + // Set RRSR rate table. + rtw_write8(Adapter, REG_RRSR, BrateCfg&0xff); + rtw_write8(Adapter, REG_RRSR+1, (BrateCfg>>8)&0xff); + rtw_write8(Adapter, REG_RRSR+2, rtw_read8(Adapter, REG_RRSR+2)&0xf0); + + // Set RTS initial rate + while(BrateCfg > 0x1) + { + BrateCfg = (BrateCfg>> 1); + RateIndex++; + } + // Ziv - Check + rtw_write8(Adapter, REG_INIRTS_RATE_SEL, RateIndex); + } + break; + case HW_VAR_TXPAUSE: + rtw_write8(Adapter, REG_TXPAUSE, *((u8 *)val)); + break; + case HW_VAR_BCN_FUNC: + hw_var_set_bcn_func(Adapter, variable, val); + break; + case HW_VAR_CORRECT_TSF: +#ifdef CONFIG_CONCURRENT_MODE + hw_var_set_correct_tsf(Adapter, variable, val); +#else + { + u64 tsf; + struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + //f = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue % (pmlmeinfo->bcn_interval*1024)) -1024; //us + tsf = pmlmeext->TSFValue - rtw_modular64(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; //us + + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || + ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) + { + //pHalData->RegTxPause |= STOP_BCNQ;BIT(6) + //rtw_write8(Adapter, REG_TXPAUSE, (rtw_read8(Adapter, REG_TXPAUSE)|BIT(6))); + StopTxBeacon(Adapter); + } + + // disable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(3))); + + rtw_write32(Adapter, REG_TSFTR, tsf); + rtw_write32(Adapter, REG_TSFTR+4, tsf>>32); + + // enable related TSF function + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(3)); + + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || + ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) + { + //pHalData->RegTxPause &= (~STOP_BCNQ); + //rtw_write8(Adapter, REG_TXPAUSE, (rtw_read8(Adapter, REG_TXPAUSE)&(~BIT(6)))); + ResumeTxBeacon(Adapter); + } + } +#endif + break; + case HW_VAR_CHECK_BSSID: + if(*((u8 *)val)) + { + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + } + else + { + u32 val32; + + val32 = rtw_read32(Adapter, REG_RCR); + + val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); + + rtw_write32(Adapter, REG_RCR, val32); + } + break; + case HW_VAR_MLME_DISCONNECT: +#ifdef CONFIG_CONCURRENT_MODE + hw_var_set_mlme_disconnect(Adapter, variable, val); +#else + { + //Set RCR to not to receive data frame when NO LINK state + //rtw_write32(Adapter, REG_RCR, rtw_read32(padapter, REG_RCR) & ~RCR_ADF); + //reject all data frames + rtw_write16(Adapter, REG_RXFLTMAP2,0x00); + + //reset TSF + rtw_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0)|BIT(1))); + + //disable update TSF + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(4)); + } +#endif + break; + case HW_VAR_MLME_SITESURVEY: +#ifdef CONFIG_CONCURRENT_MODE + hw_var_set_mlme_sitesurvey(Adapter, variable, val); +#else + if(*((u8 *)val))//under sitesurvey + { + //config RCR to receive different BSSID & not to receive data frame + u32 v = rtw_read32(Adapter, REG_RCR); + v &= ~(RCR_CBSSID_BCN); + rtw_write32(Adapter, REG_RCR, v); + //reject all data frame + rtw_write16(Adapter, REG_RXFLTMAP2,0x00); + + //disable update TSF + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)|BIT(4)); + } + else//sitesurvey done + { + struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + if ((is_client_associated_to_ap(Adapter) == _TRUE) || + ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ) + { + //enable to rx data frame + //rtw_write32(Adapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); + rtw_write16(Adapter, REG_RXFLTMAP2,0xFFFF); + + //enable update TSF + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + } + else if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) + { + //rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_ADF); + rtw_write16(Adapter, REG_RXFLTMAP2,0xFFFF); + + //enable update TSF + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + } + + if(Adapter->in_cta_test) + { + if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) + { + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); + } + else + { + u32 v = rtw_read32(Adapter, REG_RCR); + v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN );//| RCR_ADF + rtw_write32(Adapter, REG_RCR, v); + } + } + else + { + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); + } + } +#endif + break; + case HW_VAR_MLME_JOIN: +#ifdef CONFIG_CONCURRENT_MODE + hw_var_set_mlme_join(Adapter, variable, val); +#else + { + u8 RetryLimit = 0x30; + u8 type = *((u8 *)val); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + + if(type == 0) // prepare to join + { + //enable to rx data frame.Accept all data frame + //rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); + rtw_write16(Adapter, REG_RXFLTMAP2,0xFFFF); + if(Adapter->in_cta_test) + { + u32 v = rtw_read32(Adapter, REG_RCR); + v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN );//| RCR_ADF + rtw_write32(Adapter, REG_RCR, v); + } + else + { + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + } + if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) + { + RetryLimit = (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48; + } + else // Ad-hoc Mode + { + RetryLimit = 0x7; + } + } + else if(type == 1) //joinbss_event call back when join res < 0 + { + rtw_write16(Adapter, REG_RXFLTMAP2,0x00); + } + else if(type == 2) //sta add event call back + { + // enable update TSF + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + + if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) + { + RetryLimit = 0x7; + } + } + + rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); + } +#endif + break; + case HW_VAR_ON_RCR_AM: + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_AM); + DBG_871X("%s, %d, RCR= %x \n", __FUNCTION__,__LINE__, rtw_read32(Adapter, REG_RCR)); + break; + case HW_VAR_OFF_RCR_AM: + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)& (~RCR_AM)); + DBG_871X("%s, %d, RCR= %x \n", __FUNCTION__,__LINE__, rtw_read32(Adapter, REG_RCR)); + break; + case HW_VAR_BEACON_INTERVAL: + rtw_write16(Adapter, REG_BCN_INTERVAL, *((u16 *)val)); + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + { + struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u16 bcn_interval = *((u16 *)val); + if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE){ + DBG_8192C("%s==> bcn_interval:%d, eraly_int:%d \n",__FUNCTION__,bcn_interval,bcn_interval>>1); + rtw_write8(Adapter, REG_DRVERLYINT, bcn_interval>>1);// 50ms for sdio + } + else{ + + } + } +#endif//CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + + break; + case HW_VAR_SLOT_TIME: + { + u8 u1bAIFS, aSifsTime; + struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + rtw_write8(Adapter, REG_SLOT, val[0]); + + if(pmlmeinfo->WMM_enable == 0) + { + if( pmlmeext->cur_wireless_mode == WIRELESS_11B) + aSifsTime = 10; + else + aSifsTime = 16; + + u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime); + + // <Roger_EXP> Temporary removed, 2008.06.20. + rtw_write8(Adapter, REG_EDCA_VO_PARAM, u1bAIFS); + rtw_write8(Adapter, REG_EDCA_VI_PARAM, u1bAIFS); + rtw_write8(Adapter, REG_EDCA_BE_PARAM, u1bAIFS); + rtw_write8(Adapter, REG_EDCA_BK_PARAM, u1bAIFS); + } + } + break; + case HW_VAR_RESP_SIFS: + { +#if 0 + // SIFS for OFDM Data ACK + rtw_write8(Adapter, REG_SIFS_CTX+1, val[0]); + // SIFS for OFDM consecutive tx like CTS data! + rtw_write8(Adapter, REG_SIFS_TRX+1, val[1]); + + rtw_write8(Adapter,REG_SPEC_SIFS+1, val[0]); + rtw_write8(Adapter,REG_MAC_SPEC_SIFS+1, val[0]); + + // 20100719 Joseph: Revise SIFS setting due to Hardware register definition change. + rtw_write8(Adapter, REG_R2T_SIFS+1, val[0]); + rtw_write8(Adapter, REG_T2T_SIFS+1, val[0]); +#else + //SIFS_Timer = 0x0a0a0808; + //RESP_SIFS for CCK + rtw_write8(Adapter, REG_R2T_SIFS, val[0]); // SIFS_T2T_CCK (0x08) + rtw_write8(Adapter, REG_R2T_SIFS+1, val[1]); //SIFS_R2T_CCK(0x08) + //RESP_SIFS for OFDM + rtw_write8(Adapter, REG_T2T_SIFS, val[2]); //SIFS_T2T_OFDM (0x0a) + rtw_write8(Adapter, REG_T2T_SIFS+1, val[3]); //SIFS_R2T_OFDM(0x0a) +#endif + } + break; + case HW_VAR_ACK_PREAMBLE: + { + u8 regTmp; + u8 bShortPreamble = *( (PBOOLEAN)val ); + // Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) + regTmp = (pHalData->nCur40MhzPrimeSC)<<5; + //regTmp = 0; + if(bShortPreamble) + regTmp |= 0x80; + + rtw_write8(Adapter, REG_RRSR+2, regTmp); + } + break; + case HW_VAR_SEC_CFG: +#ifdef CONFIG_CONCURRENT_MODE + rtw_write8(Adapter, REG_SECCFG, 0x0c|BIT(5));// enable tx enc and rx dec engine, and no key search for MC/BC +#else + rtw_write8(Adapter, REG_SECCFG, *((u8 *)val)); +#endif + break; + case HW_VAR_DM_FLAG: + podmpriv->SupportAbility = *((u8 *)val); + break; + case HW_VAR_DM_FUNC_OP: + if(val[0]) + {// save dm flag + podmpriv->BK_SupportAbility = podmpriv->SupportAbility; + } + else + {// restore dm flag + podmpriv->SupportAbility = podmpriv->BK_SupportAbility; + } + break; + case HW_VAR_DM_FUNC_SET: + if(*((u32 *)val) == DYNAMIC_ALL_FUNC_ENABLE){ + pdmpriv->DMFlag = pdmpriv->InitDMFlag; + podmpriv->SupportAbility = pdmpriv->InitODMFlag; + } + else{ + podmpriv->SupportAbility |= *((u32 *)val); + } + break; + case HW_VAR_DM_FUNC_CLR: + podmpriv->SupportAbility &= *((u32 *)val); + break; + case HW_VAR_CAM_EMPTY_ENTRY: + { + u8 ucIndex = *((u8 *)val); + u8 i; + u32 ulCommand=0; + u32 ulContent=0; + u32 ulEncAlgo=CAM_AES; + + for(i=0;i<CAM_CONTENT_COUNT;i++) + { + // filled id in CAM config 2 byte + if( i == 0) + { + ulContent |=(ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2); + //ulContent |= CAM_VALID; + } + else + { + ulContent = 0; + } + // polling bit, and No Write enable, and address + ulCommand= CAM_CONTENT_COUNT*ucIndex+i; + ulCommand= ulCommand | CAM_POLLINIG|CAM_WRITE; + // write content 0 is equall to mark invalid + rtw_write32(Adapter, WCAMI, ulContent); //delay_ms(40); + //RT_TRACE(COMP_SEC, DBG_LOUD, ("CAM_empty_entry(): WRITE A4: %lx \n",ulContent)); + rtw_write32(Adapter, RWCAM, ulCommand); //delay_ms(40); + //RT_TRACE(COMP_SEC, DBG_LOUD, ("CAM_empty_entry(): WRITE A0: %lx \n",ulCommand)); + } + } + break; + case HW_VAR_CAM_INVALID_ALL: + rtw_write32(Adapter, RWCAM, BIT(31)|BIT(30)); + break; + case HW_VAR_CAM_WRITE: + { + u32 cmd; + u32 *cam_val = (u32 *)val; + rtw_write32(Adapter, WCAMI, cam_val[0]); + + cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1]; + rtw_write32(Adapter, RWCAM, cmd); + } + break; + case HW_VAR_AC_PARAM_VO: + rtw_write32(Adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]); + break; + case HW_VAR_AC_PARAM_VI: + rtw_write32(Adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]); + break; + case HW_VAR_AC_PARAM_BE: + pHalData->AcParam_BE = ((u32 *)(val))[0]; + rtw_write32(Adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]); + break; + case HW_VAR_AC_PARAM_BK: + rtw_write32(Adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]); + break; + case HW_VAR_AMPDU_MIN_SPACE: + { + u8 MinSpacingToSet; + u8 SecMinSpace; + + MinSpacingToSet = *((u8 *)val); + if(MinSpacingToSet <= 7) + { + switch(Adapter->securitypriv.dot11PrivacyAlgrthm) + { + case _NO_PRIVACY_: + case _AES_: + SecMinSpace = 0; + break; + + case _WEP40_: + case _WEP104_: + case _TKIP_: + case _TKIP_WTMIC_: + SecMinSpace = 6; + break; + default: + SecMinSpace = 7; + break; + } + + if(MinSpacingToSet < SecMinSpace){ + MinSpacingToSet = SecMinSpace; + } + + //RT_TRACE(COMP_MLME, DBG_LOUD, ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", Adapter->MgntInfo.MinSpaceCfg)); + rtw_write8(Adapter, REG_AMPDU_MIN_SPACE, (rtw_read8(Adapter, REG_AMPDU_MIN_SPACE) & 0xf8) | MinSpacingToSet); + } + } + break; + case HW_VAR_AMPDU_FACTOR: + { + u8 RegToSet_Normal[4]={0x41,0xa8,0x72, 0xb9}; + u8 RegToSet_BT[4]={0x31,0x74,0x42, 0x97}; + u8 FactorToSet; + u8 *pRegToSet; + u8 index = 0; + +#ifdef CONFIG_BT_COEXIST + if( (pHalData->bt_coexist.BT_Coexist) && + (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4) ) + pRegToSet = RegToSet_BT; // 0x97427431; + else +#endif + pRegToSet = RegToSet_Normal; // 0xb972a841; + + FactorToSet = *((u8 *)val); + if(FactorToSet <= 3) + { + FactorToSet = (1<<(FactorToSet + 2)); + if(FactorToSet>0xf) + FactorToSet = 0xf; + + for(index=0; index<4; index++) + { + if((pRegToSet[index] & 0xf0) > (FactorToSet<<4)) + pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet<<4); + + if((pRegToSet[index] & 0x0f) > FactorToSet) + pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet); + + rtw_write8(Adapter, (REG_AGGLEN_LMT+index), pRegToSet[index]); + } + + //RT_TRACE(COMP_MLME, DBG_LOUD, ("Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet)); + } + } + break; + case HW_VAR_RXDMA_AGG_PG_TH: + rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, *((u8 *)val)); + break; + case HW_VAR_SET_RPWM: +#ifdef CONFIG_LPS_LCLK + { + u8 ps_state = *((u8 *)val); + //rpwm value only use BIT0(clock bit) ,BIT6(Ack bit), and BIT7(Toggle bit) for 88e. + //BIT0 value - 1: 32k, 0:40MHz. + //BIT6 value - 1: report cpwm value after success set, 0:do not report. + //BIT7 value - Toggle bit change. + //modify by Thomas. 2012/4/2. + ps_state = ps_state & 0xC1; + +#ifdef CONFIG_EXT_CLK //for sprd + if(ps_state&BIT(6)) // want to leave 32k + { + //enable ext clock req before leave LPS-32K + //DBG_871X("enable ext clock req before leaving LPS-32K\n"); + EnableGpio5ClockReq(Adapter, _FALSE, 1); + } +#endif //CONFIG_EXT_CLK + + //DBG_871X("##### Change RPWM value to = %x for switch clk #####\n",ps_state); + rtw_write8(Adapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1, ps_state); + } +#endif + break; + case HW_VAR_H2C_FW_PWRMODE: + { + u8 psmode = (*(u8 *)val); + + // Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power + // saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. + if( (psmode != PS_MODE_ACTIVE) && (!IS_92C_SERIAL(pHalData->VersionID))) + { + ODM_RF_Saving(podmpriv, _TRUE); + } + rtl8188e_set_FwPwrMode_cmd(Adapter, psmode); + } + break; + case HW_VAR_H2C_FW_JOINBSSRPT: + { + u8 mstatus = (*(u8 *)val); + rtl8188e_set_FwJoinBssReport_cmd(Adapter, mstatus); + } + break; +#ifdef CONFIG_P2P_PS + case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: + { + u8 p2p_ps_state = (*(u8 *)val); + rtl8188e_set_p2p_ps_offload_cmd(Adapter, p2p_ps_state); + } + break; +#endif // CONFIG_P2P_PS + case HW_VAR_INITIAL_GAIN: + { + DIG_T *pDigTable = &podmpriv->DM_DigTable; + u32 rx_gain = ((u32 *)(val))[0]; + + if(rx_gain == 0xff){//restore rx gain + ODM_Write_DIG(podmpriv,pDigTable->BackupIGValue); + } + else{ + pDigTable->BackupIGValue = pDigTable->CurIGValue; + ODM_Write_DIG(podmpriv,rx_gain); + } + } + break; + case HW_VAR_TRIGGER_GPIO_0: +// rtl8192cu_trigger_gpio_0(Adapter); + break; +#ifdef CONFIG_BT_COEXIST + case HW_VAR_BT_SET_COEXIST: + { + u8 bStart = (*(u8 *)val); + rtl8192c_set_dm_bt_coexist(Adapter, bStart); + } + break; + case HW_VAR_BT_ISSUE_DELBA: + { + u8 dir = (*(u8 *)val); + rtl8192c_issue_delete_ba(Adapter, dir); + } + break; +#endif +#if (RATE_ADAPTIVE_SUPPORT==1) + case HW_VAR_RPT_TIMER_SETTING: + { + u16 min_rpt_time = (*(u16 *)val); + + //DBG_8192C("==> HW_VAR_ANTENNA_DIVERSITY_SELECT , Ant_(%s)\n",(Optimum_antenna==2)?"A":"B"); + + //PHY_SetBBReg(Adapter, rFPGA0_XA_RFInterfaceOE, 0x300, Optimum_antenna); + ODM_RA_Set_TxRPT_Time(podmpriv,min_rpt_time); + } + break; +#endif + +#ifdef CONFIG_SW_ANTENNA_DIVERSITY + case HW_VAR_ANTENNA_DIVERSITY_LINK: + //SwAntDivRestAfterLink8192C(Adapter); + ODM_SwAntDivRestAfterLink(podmpriv); + break; +#endif +#ifdef CONFIG_ANTENNA_DIVERSITY + case HW_VAR_ANTENNA_DIVERSITY_SELECT: + { + u8 Optimum_antenna = (*(u8 *)val); + u8 Ant ; + //switch antenna to Optimum_antenna + //DBG_8192C("==> HW_VAR_ANTENNA_DIVERSITY_SELECT , Ant_(%s)\n",(Optimum_antenna==2)?"A":"B"); + if(pHalData->CurAntenna != Optimum_antenna) + { + Ant = (Optimum_antenna==2)?MAIN_ANT:AUX_ANT; + ODM_UpdateRxIdleAnt_88E(&pHalData->odmpriv, Ant); + + pHalData->CurAntenna = Optimum_antenna ; + //DBG_8192C("==> HW_VAR_ANTENNA_DIVERSITY_SELECT , Ant_(%s)\n",(Optimum_antenna==2)?"A":"B"); + } + } + break; +#endif + case HW_VAR_EFUSE_BYTES: // To set EFUE total used bytes, added by Roger, 2008.12.22. + pHalData->EfuseUsedBytes = *((u16 *)val); + break; + case HW_VAR_FIFO_CLEARN_UP: + { + struct pwrctrl_priv *pwrpriv = &Adapter->pwrctrlpriv; + u8 trycnt = 100; + + //pause tx + rtw_write8(Adapter,REG_TXPAUSE,0xff); + + //keep sn + Adapter->xmitpriv.nqos_ssn = rtw_read16(Adapter,REG_NQOS_SEQ); + + //RX DMA stop + rtw_write32(Adapter,REG_RXPKT_NUM,(rtw_read32(Adapter,REG_RXPKT_NUM)|RW_RELEASE_EN)); + do{ + if(!(rtw_read32(Adapter,REG_RXPKT_NUM)&RXDMA_IDLE)) + break; + }while(trycnt--); + if(trycnt ==0) + DBG_8192C("Stop RX DMA failed...... \n"); + + //RQPN Load 0 + rtw_write16(Adapter,REG_RQPN_NPQ,0x0); + rtw_write32(Adapter,REG_RQPN,0x80000000); + rtw_mdelay_os(10); + + } + break; + case HW_VAR_CHECK_TXBUF: +#ifdef CONFIG_CONCURRENT_MODE + { + int i; + u8 RetryLimit = 0x01; + + rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); + for(i=0;i<1000;i++) + { + if(rtw_read32(Adapter, 0x200) != rtw_read32(Adapter, 0x204)) + { + //DBG_871X("packet in tx packet buffer - 0x204=%x, 0x200=%x (%d)\n", rtw_read32(Adapter, 0x204), rtw_read32(Adapter, 0x200), i); + rtw_msleep_os(10); + } + else + { + DBG_871X("no packet in tx packet buffer (%d)\n", i); + break; + } + } + + RetryLimit = 0x30; + rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); + + } +#endif + break; +#ifdef CONFIG_WOWLAN + case HW_VAR_WOWLAN: + { + struct wowlan_ioctl_param *poidparam; + struct recv_buf *precvbuf; + int res, i; + u32 tmp; + u16 len = 0; + u8 mstatus = (*(u8 *)val); + u8 trycnt = 100; + u8 data[4]; + + poidparam = (struct wowlan_ioctl_param *)val; + switch (poidparam->subcode){ + case WOWLAN_ENABLE: + DBG_871X_LEVEL(_drv_always_, "WOWLAN_ENABLE\n"); + + SetFwRelatedForWoWLAN8188ES(Adapter, _TRUE); + + //Set Pattern + //if(Adapter->pwrctrlpriv.wowlan_pattern==_TRUE) + // rtw_wowlan_reload_pattern(Adapter); + + //RX DMA stop + DBG_871X_LEVEL(_drv_always_, "Pause DMA\n"); + rtw_write32(Adapter,REG_RXPKT_NUM,(rtw_read32(Adapter,REG_RXPKT_NUM)|RW_RELEASE_EN)); + do{ + if((rtw_read32(Adapter, REG_RXPKT_NUM)&RXDMA_IDLE)) { + DBG_871X_LEVEL(_drv_always_, "RX_DMA_IDLE is true\n"); + break; + } else { + // If RX_DMA is not idle, receive one pkt from DMA + res = sdio_local_read(Adapter, SDIO_REG_RX0_REQ_LEN, 4, (u8*)&tmp); + //len = le16_to_cpu(*(u16*)data); + if (tmp == 0){ + res = sdio_local_read(Adapter, SDIO_REG_HISR, 4, (u8*)&tmp); + DBG_871X_LEVEL(_drv_info_, "read SDIO_REG_HISR: 0x%08x\n", tmp); + } + res = RecvOnePkt(Adapter, tmp); + DBG_871X_LEVEL(_drv_always_, "RecvOnePkt Result: %d\n", res); + } + }while(trycnt--); + if(trycnt ==0) + DBG_871X_LEVEL(_drv_always_, "Stop RX DMA failed...... \n"); + + //Enable CPWM2 only. + DBG_871X_LEVEL(_drv_always_, "Enable only CPWM2\n"); + res = sdio_local_read(Adapter, SDIO_REG_HIMR, 4, (u8*)&tmp); + if (!res) + DBG_871X_LEVEL(_drv_info_, "read SDIO_REG_HIMR: 0x%08x\n", tmp); + else + DBG_871X_LEVEL(_drv_info_, "sdio_local_read fail\n"); + + tmp = SDIO_HIMR_CPWM2_MSK; + + res = sdio_local_write(Adapter, SDIO_REG_HIMR, 4, (u8*)&tmp); + + if (!res){ + res = sdio_local_read(Adapter, SDIO_REG_HIMR, 4, (u8*)&tmp); + DBG_871X_LEVEL(_drv_info_, "read again SDIO_REG_HIMR: 0x%08x\n", tmp); + }else + DBG_871X_LEVEL(_drv_info_, "sdio_local_write fail\n"); + + //Set WOWLAN H2C command. + DBG_871X_LEVEL(_drv_always_, "Set WOWLan cmd\n"); + rtl8188es_set_wowlan_cmd(Adapter, 1); + + mstatus = rtw_read8(Adapter, REG_WOW_CTRL); + trycnt = 10; + + while(!(mstatus&BIT1) && trycnt>1) { + mstatus = rtw_read8(Adapter, REG_WOW_CTRL); + DBG_871X_LEVEL(_drv_always_, "Loop index: %d :0x%02x\n", trycnt, mstatus); + trycnt --; + rtw_msleep_os(2); + } + + Adapter->pwrctrlpriv.wowlan_wake_reason = rtw_read8(Adapter, REG_WOWLAN_WAKE_REASON); + DBG_871X_LEVEL(_drv_always_, "wowlan_wake_reason: 0x%02x\n", + Adapter->pwrctrlpriv.wowlan_wake_reason); + + //rtw_msleep_os(10); + break; + case WOWLAN_DISABLE: + DBG_871X_LEVEL(_drv_always_, "WOWLAN_DISABLE\n"); + trycnt = 10; + Adapter->pwrctrlpriv.wowlan_wake_reason = + rtw_read8(Adapter, REG_WOWLAN_WAKE_REASON); + DBG_871X_LEVEL(_drv_always_, "wakeup_reason: 0x%02x\n", + Adapter->pwrctrlpriv.wowlan_wake_reason); + rtl8188es_set_wowlan_cmd(Adapter, 0); + mstatus = rtw_read8(Adapter, REG_WOW_CTRL); + DBG_871X_LEVEL(_drv_info_, "%s mstatus:0x%02x\n", __func__, mstatus); + + while(mstatus&BIT1 && trycnt>1) { + mstatus = rtw_read8(Adapter, REG_WOW_CTRL); + DBG_871X_LEVEL(_drv_always_, "Loop index: %d :0x%02x\n", trycnt, mstatus); + trycnt --; + rtw_msleep_os(2); + } + + if (mstatus & BIT1) + printk("System did not release RX_DMA\n"); + else + SetFwRelatedForWoWLAN8188ES(Adapter, _FALSE); + + EnableInterrupt8188ESdio(Adapter); + rtw_msleep_os(2); + if(!(Adapter->pwrctrlpriv.wowlan_wake_reason & FWDecisionDisconnect) || + !(Adapter->pwrctrlpriv.wowlan_wake_reason & Rx_GTK)) + rtl8188e_set_FwJoinBssReport_cmd(Adapter, 1); + //rtw_msleep_os(10); + break; + default: + break; + } + } + break; +#endif //CONFIG_WOWLAN + case HW_VAR_APFM_ON_MAC: + pHalData->bMacPwrCtrlOn = *val; + DBG_871X("%s: bMacPwrCtrlOn=%d\n", __func__, pHalData->bMacPwrCtrlOn); + break; +#if (RATE_ADAPTIVE_SUPPORT == 1) + case HW_VAR_TX_RPT_MAX_MACID: + { + u8 maxMacid = *val; + DBG_8192C("### MacID(%d),Set Max Tx RPT MID(%d)\n",maxMacid,maxMacid+1); + rtw_write8(Adapter, REG_TX_RPT_CTRL+1, maxMacid+1); + } + break; +#endif // (RATE_ADAPTIVE_SUPPORT == 1) + case HW_VAR_H2C_MEDIA_STATUS_RPT: + { + rtl8188e_set_FwMediaStatus_cmd(Adapter , (*(u16 *)val)); + } + break; + case HW_VAR_BCN_VALID: + //BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw + rtw_write8(Adapter, REG_TDECTRL+2, rtw_read8(Adapter, REG_TDECTRL+2) | BIT0); + break; + default: + + break; + } + +_func_exit_; +} + +static void GetHwReg8188ES(PADAPTER padapter, u8 variable, u8 *val) +{ + PHAL_DATA_TYPE pHalData= GET_HAL_DATA(padapter); + DM_ODM_T *podmpriv = &pHalData->odmpriv; +_func_enter_; + + switch (variable) + { + case HW_VAR_BASIC_RATE: + *((u16*)val) = pHalData->BasicRateSet; + break; + + case HW_VAR_TXPAUSE: + val[0] = rtw_read8(padapter, REG_TXPAUSE); + break; + + case HW_VAR_BCN_VALID: + //BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 + val[0] = (BIT0 & rtw_read8(padapter, REG_TDECTRL+2))?_TRUE:_FALSE; + break; + + case HW_VAR_DM_FLAG: + val[0] = podmpriv->SupportAbility; + break; + + case HW_VAR_RF_TYPE: + val[0] = pHalData->rf_type; + break; + + case HW_VAR_FWLPS_RF_ON: + { + //When we halt NIC, we should check if FW LPS is leave. + if ((padapter->bSurpriseRemoved == _TRUE) || + (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) + { + // If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, + // because Fw is unload. + val[0] = _TRUE; + } + else + { + u32 valRCR; + valRCR = rtw_read32(padapter, REG_RCR); + valRCR &= 0x00070000; + if(valRCR) + val[0] = _FALSE; + else + val[0] = _TRUE; + } + } + break; +#ifdef CONFIG_ANTENNA_DIVERSITY + case HW_VAR_CURRENT_ANTENNA: + val[0] = pHalData->CurAntenna; + break; +#endif + case HW_VAR_EFUSE_BYTES: // To get EFUE total used bytes, added by Roger, 2008.12.22. + *((u16*)val) = pHalData->EfuseUsedBytes; + break; + + case HW_VAR_APFM_ON_MAC: + *val = pHalData->bMacPwrCtrlOn; + break; + case HW_VAR_CHK_HI_QUEUE_EMPTY: + *val = ((rtw_read32(padapter, REG_HGQ_INFORMATION)&0x0000ff00)==0) ? _TRUE:_FALSE; + break; + default: + break; + } + +_func_exit_; +} + +// +// Description: +// Query setting of specified variable. +// +u8 +GetHalDefVar8188ESDIO( + IN PADAPTER Adapter, + IN HAL_DEF_VARIABLE eVariable, + IN PVOID pValue + ) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 bResult = _SUCCESS; + + switch(eVariable) + { + case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB: + { + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + struct sta_priv * pstapriv = &Adapter->stapriv; + struct sta_info * psta; + psta = rtw_get_stainfo(pstapriv, pmlmepriv->cur_network.network.MacAddress); + if(psta) + { + *((int *)pValue) = psta->rssi_stat.UndecoratedSmoothedPWDB; + } + } + + break; + case HAL_DEF_IS_SUPPORT_ANT_DIV: + #ifdef CONFIG_ANTENNA_DIVERSITY + *((u8 *)pValue) = (pHalData->AntDivCfg==0)?_FALSE:_TRUE; + #endif + break; + case HAL_DEF_CURRENT_ANTENNA: +#ifdef CONFIG_ANTENNA_DIVERSITY + *(( u8*)pValue) = pHalData->CurAntenna; +#endif + break; + case HAL_DEF_DBG_DM_FUNC: + *(( u32*)pValue) =pHalData->odmpriv.SupportAbility; + break; +#if (RATE_ADAPTIVE_SUPPORT == 1) + case HAL_DEF_RA_DECISION_RATE: + { + u8 MacID = *((u8*)pValue); + *((u8*)pValue) = ODM_RA_GetDecisionRate_8188E(&(pHalData->odmpriv), MacID); + } + break; + + case HAL_DEF_RA_SGI: + { + u8 MacID = *((u8*)pValue); + *((u8*)pValue) = ODM_RA_GetShortGI_8188E(&(pHalData->odmpriv), MacID); + } + break; +#endif + + + case HAL_DEF_PT_PWR_STATUS: +#if(POWER_TRAINING_ACTIVE==1) + { + u8 MacID = *((u8*)pValue); + *((u8*)pValue) = ODM_RA_GetHwPwrStatus_8188E(&(pHalData->odmpriv), MacID); + } +#endif //(POWER_TRAINING_ACTIVE==1) + break; + + case HW_VAR_MAX_RX_AMPDU_FACTOR: + *(( u32*)pValue) = MAX_AMPDU_FACTOR_16K; + break; + + case HW_DEF_RA_INFO_DUMP: +#if (RATE_ADAPTIVE_SUPPORT == 1) + { + u8 entry_id = *((u8*)pValue); + if(check_fwstate(&Adapter->mlmepriv, _FW_LINKED)== _TRUE) + { + DBG_871X("============ RA status check ===================\n"); + DBG_8192C("Mac_id:%d ,RateID = %d,RAUseRate = 0x%08x,RateSGI = %d, DecisionRate = 0x%02x ,PTStage = %d\n", + entry_id, + pHalData->odmpriv.RAInfo[entry_id].RateID, + pHalData->odmpriv.RAInfo[entry_id].RAUseRate, + pHalData->odmpriv.RAInfo[entry_id].RateSGI, + pHalData->odmpriv.RAInfo[entry_id].DecisionRate, + pHalData->odmpriv.RAInfo[entry_id].PTStage); + } + } +#endif // (RATE_ADAPTIVE_SUPPORT == 1) + break; + + case HAL_DEF_DBG_DUMP_RXPKT: + *(( u8*)pValue) = pHalData->bDumpRxPkt; + break; + case HAL_DEF_DBG_DUMP_TXPKT: + *(( u8*)pValue) = pHalData->bDumpTxPkt; + break; + case HW_DEF_ODM_DBG_FLAG: + { + u8Byte DebugComponents = *((u32*)pValue); + PDM_ODM_T pDM_Odm = &(pHalData->odmpriv); + printk("pDM_Odm->DebugComponents = 0x%llx \n",pDM_Odm->DebugComponents ); + } + break; + default: + //RT_TRACE(COMP_INIT, DBG_WARNING, ("GetHalDefVar8188ESDIO(): Unkown variable: %d!\n", eVariable)); + bResult = _FAIL; + break; + } + + return bResult; +} + + + + +// +// Description: +// Change default setting of specified variable. +// +u8 +SetHalDefVar8188ESDIO( + IN PADAPTER Adapter, + IN HAL_DEF_VARIABLE eVariable, + IN PVOID pValue + ) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 bResult = _TRUE; + + switch(eVariable) + { + case HAL_DEF_DBG_DM_FUNC: + { + u8 dm_func = *(( u8*)pValue); + struct dm_priv *pdmpriv = &pHalData->dmpriv; + DM_ODM_T *podmpriv = &pHalData->odmpriv; + + if(dm_func == 0){ //disable all dynamic func + podmpriv->SupportAbility = DYNAMIC_FUNC_DISABLE; + DBG_8192C("==> Disable all dynamic function...\n"); + } + else if(dm_func == 1){//disable DIG + podmpriv->SupportAbility &= (~DYNAMIC_BB_DIG); + DBG_8192C("==> Disable DIG...\n"); + } + else if(dm_func == 2){//disable High power + podmpriv->SupportAbility &= (~DYNAMIC_BB_DYNAMIC_TXPWR); + } + else if(dm_func == 3){//disable tx power tracking + podmpriv->SupportAbility &= (~DYNAMIC_RF_CALIBRATION); + DBG_8192C("==> Disable tx power tracking...\n"); + } + //else if(dm_func == 4){//disable BT coexistence + // pdmpriv->DMFlag &= (~DYNAMIC_FUNC_BT); + //} + else if(dm_func == 5){//disable antenna diversity + podmpriv->SupportAbility &= (~DYNAMIC_BB_ANT_DIV); + } + else if(dm_func == 6){//turn on all dynamic func + if(!(podmpriv->SupportAbility & DYNAMIC_BB_DIG)) + { + DIG_T *pDigTable = &podmpriv->DM_DigTable; + pDigTable->CurIGValue= rtw_read8(Adapter,0xc50); + } + //pdmpriv->DMFlag |= DYNAMIC_FUNC_BT; + podmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE; + DBG_8192C("==> Turn on all dynamic function...\n"); + } + } + break; + case HAL_DEF_DBG_DUMP_RXPKT: + pHalData->bDumpRxPkt = *(( u8*)pValue); + break; + case HAL_DEF_DBG_DUMP_TXPKT: + pHalData->bDumpTxPkt = *(( u8*)pValue); + break; + case HW_DEF_FA_CNT_DUMP: + { + u8 bRSSIDump = *((u8*)pValue); + PDM_ODM_T pDM_Odm = &(pHalData->odmpriv); + if(bRSSIDump) + pDM_Odm->DebugComponents = ODM_COMP_DIG|ODM_COMP_FA_CNT ; + else + pDM_Odm->DebugComponents = 0; + + } + break; + case HW_DEF_ODM_DBG_FLAG: + { + u8Byte DebugComponents = *((u8Byte*)pValue); + PDM_ODM_T pDM_Odm = &(pHalData->odmpriv); + pDM_Odm->DebugComponents = DebugComponents; + } + break; + default: + //RT_TRACE(COMP_INIT, DBG_TRACE, ("SetHalDefVar819xUsb(): Unkown variable: %d!\n", eVariable)); + bResult = _FALSE; + break; + } + + return bResult; +} + +void UpdateHalRAMask8188ESdio(PADAPTER padapter, u32 mac_id, u8 rssi_level) +{ + //volatile unsigned int result; + u8 init_rate=0; + u8 networkType, raid; + u32 mask,rate_bitmap; + u8 shortGIrate = _FALSE; + int supportRateNum = 0; + struct sta_info *psta; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + //struct dm_priv *pdmpriv = &pHalData->dmpriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); +#ifdef CONFIG_CONCURRENT_MODE + if(rtw_buddy_adapter_up(padapter) && padapter->adapter_type > PRIMARY_ADAPTER) + pHalData = GET_HAL_DATA(padapter->pbuddy_adapter); +#endif //CONFIG_CONCURRENT_MODE + + if (mac_id >= NUM_STA) //CAM_SIZE + { + return; + } + + psta = pmlmeinfo->FW_sta_info[mac_id].psta; + if(psta == NULL) + { + return; + } + + switch (mac_id) + { + case 0:// for infra mode +#ifdef CONFIG_CONCURRENT_MODE + case 2:// first station uses macid=0, second station uses macid=2 +#endif + supportRateNum = rtw_get_rateset_len(cur_network->SupportedRates); + networkType = judge_network_type(padapter, cur_network->SupportedRates, supportRateNum) & 0xf; + //pmlmeext->cur_wireless_mode = networkType; + raid = networktype_to_raid(networkType); + + mask = update_supported_rate(cur_network->SupportedRates, supportRateNum); + mask |= (pmlmeinfo->HT_enable)? update_MSC_rate(&(pmlmeinfo->HT_caps)): 0; + + + if (support_short_GI(padapter, &(pmlmeinfo->HT_caps))) + { + shortGIrate = _TRUE; + } + + break; + + case 1://for broadcast/multicast + supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates); + if(pmlmeext->cur_wireless_mode & WIRELESS_11B) + networkType = WIRELESS_11B; + else + networkType = WIRELESS_11G; + raid = networktype_to_raid(networkType); + mask = update_basic_rate(cur_network->SupportedRates, supportRateNum); + + + break; + + default: //for each sta in IBSS + supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates); + networkType = judge_network_type(padapter, pmlmeinfo->FW_sta_info[mac_id].SupportedRates, supportRateNum) & 0xf; + //pmlmeext->cur_wireless_mode = networkType; + raid = networktype_to_raid(networkType); + mask = update_supported_rate(cur_network->SupportedRates, supportRateNum); + + //todo: support HT in IBSS + + break; + } + + //mask &=0xffffffff; + rate_bitmap = 0x0fffffff; +#ifdef CONFIG_ODM_REFRESH_RAMASK + { + rate_bitmap = ODM_Get_Rate_Bitmap(&pHalData->odmpriv,mac_id,mask,rssi_level); + DBG_8192C("%s => mac_id:%d, networkType:0x%02x, mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n", + __FUNCTION__,mac_id,networkType,mask,rssi_level,rate_bitmap); + } +#endif + mask &= rate_bitmap; + + + init_rate = get_highest_rate_idx(mask)&0x3f; + + if(pHalData->fw_ractrl == _TRUE) + { + u8 arg = 0; + + //arg = (cam_idx-4)&0x1f;//MACID + arg = mac_id&0x1f;//MACID + + arg |= BIT(7); + + if (shortGIrate==_TRUE) + arg |= BIT(5); + mask |= ((raid<<28)&0xf0000000); + + DBG_871X("update raid entry, mask=0x%x, arg=0x%x\n", mask, arg); + psta->ra_mask=mask; +#ifdef CONFIG_INTEL_PROXIM + if(padapter->proximity.proxim_on ==_TRUE){ + arg &= ~BIT(6); + } + else { + arg |= BIT(6); + } +#endif //CONFIG_INTEL_PROXIM + rtl8188e_set_raid_cmd(padapter, mask); + + } + else + { + +#if(RATE_ADAPTIVE_SUPPORT == 1) + + ODM_RA_UpdateRateInfo_8188E( + &(pHalData->odmpriv), + mac_id, + raid, + mask, + shortGIrate + ); + +#endif + } + + + //set ra_id + psta->raid = raid; + psta->init_rate = init_rate; + + +} + + +static VOID +_BeaconFunctionEnable( + IN PADAPTER padapter, + IN BOOLEAN Enable, + IN BOOLEAN Linked + ) +{ + rtw_write8(padapter, REG_BCN_CTRL, (BIT4 | BIT3 | BIT1)); +// RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("_BeaconFunctionEnable 0x550 0x%x\n", rtw_read8(padapter, 0x550))); + + rtw_write8(padapter, REG_RD_CTRL+1, 0x6F); +} + +void SetBeaconRelatedRegisters8188ESdio(PADAPTER padapter) +{ + u32 value32; + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u32 bcn_ctrl_reg = REG_BCN_CTRL; + //reset TSF, enable update TSF, correcting TSF On Beacon + + //REG_BCN_INTERVAL + //REG_BCNDMATIM + //REG_ATIMWND + //REG_TBTT_PROHIBIT + //REG_DRVERLYINT + //REG_BCN_MAX_ERR + //REG_BCNTCFG //(0x510) + //REG_DUAL_TSF_RST + //REG_BCN_CTRL //(0x550) + + +#ifdef CONFIG_CONCURRENT_MODE + if (padapter->iface_type == IFACE_PORT1){ + bcn_ctrl_reg = REG_BCN_CTRL_1; + } +#endif + // + // ATIM window + // + rtw_write16(padapter, REG_ATIMWND, 2); + + // + // Beacon interval (in unit of TU). + // + rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval); + + _InitBeaconParameters(padapter); + + rtw_write8(padapter, REG_SLOT, 0x09); + + // + // Force beacon frame transmission even after receiving beacon frame from other ad hoc STA + // + //PlatformEFIOWrite1Byte(Adapter, BCN_ERR_THRESH, 0x0a); // We force beacon sent to prevent unexpect disconnect status in Ad hoc mode + + // + // Reset TSF Timer to zero, added by Roger. 2008.06.24 + // + value32 = rtw_read32(padapter, REG_TCR); + value32 &= ~TSFRST; + rtw_write32(padapter, REG_TCR, value32); + + value32 |= TSFRST; + rtw_write32(padapter, REG_TCR, value32); + + // TODO: Modify later (Find the right parameters) + // NOTE: Fix test chip's bug (about contention windows's randomness) +// if (OpMode == RT_OP_MODE_IBSS || OpMode == RT_OP_MODE_AP) + if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_AP_STATE) == _TRUE) + { + rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50); + rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50); + } + + _BeaconFunctionEnable(padapter, _TRUE, _TRUE); + + ResumeTxBeacon(padapter); + rtw_write8(padapter, bcn_ctrl_reg, rtw_read8(padapter, bcn_ctrl_reg)|BIT(1)); +} + +void rtl8188es_set_hal_ops(PADAPTER padapter) +{ + struct hal_ops *pHalFunc = &padapter->HalFunc; + +_func_enter_; + + + //set hardware operation functions + padapter->HalData = rtw_zmalloc(sizeof(HAL_DATA_TYPE)); + + if (padapter->HalData == NULL) { + RT_TRACE(_module_hci_hal_init_c_, _drv_err_, + ("can't alloc memory for HAL DATA\n")); + } + + + padapter->hal_data_sz = sizeof(HAL_DATA_TYPE); + + pHalFunc->hal_power_on = rtl8188es_InitPowerOn; + pHalFunc->hal_init = &rtl8188es_hal_init; + pHalFunc->hal_deinit = &rtl8188es_hal_deinit; + + pHalFunc->inirp_init = &rtl8188es_inirp_init; + pHalFunc->inirp_deinit = &rtl8188es_inirp_deinit; + + pHalFunc->init_xmit_priv = &rtl8188es_init_xmit_priv; + pHalFunc->free_xmit_priv = &rtl8188es_free_xmit_priv; + + pHalFunc->init_recv_priv = &rtl8188es_init_recv_priv; + pHalFunc->free_recv_priv = &rtl8188es_free_recv_priv; + + pHalFunc->InitSwLeds = &rtl8188es_InitSwLeds; + pHalFunc->DeInitSwLeds = &rtl8188es_DeInitSwLeds; + + pHalFunc->init_default_value = &rtl8188es_init_default_value; + pHalFunc->intf_chip_configure = &rtl8188es_interface_configure; + pHalFunc->read_adapter_info = &ReadAdapterInfo8188ES; + + pHalFunc->enable_interrupt = &EnableInterrupt8188ESdio; + pHalFunc->disable_interrupt = &DisableInterrupt8188ESdio; + +#ifdef COWFIG_WOWLAN + pHalFunc->disable_interrupt = &ClearInterrupt8189ESdio; +#endif + + pHalFunc->SetHwRegHandler = &SetHwReg8188ES; + pHalFunc->GetHwRegHandler = &GetHwReg8188ES; + + pHalFunc->GetHalDefVarHandler = &GetHalDefVar8188ESDIO; + pHalFunc->SetHalDefVarHandler = &SetHalDefVar8188ESDIO; + + pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8188ESdio; + pHalFunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188ESdio; + + pHalFunc->hal_xmit = &rtl8188es_hal_xmit; + pHalFunc->mgnt_xmit = &rtl8188es_mgnt_xmit; + pHalFunc->hal_xmitframe_enqueue = &rtl8188es_hal_xmitframe_enqueue; + +#ifdef CONFIG_HOSTAPD_MLME + pHalFunc->hostap_mgnt_xmit_entry = NULL; +// pHalFunc->hostap_mgnt_xmit_entry = &rtl8192cu_hostap_mgnt_xmit_entry; +#endif + rtl8188e_set_hal_ops(pHalFunc); +_func_exit_; + +} + diff --git a/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/sdio_ops.c b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/sdio_ops.c new file mode 100755 index 00000000..35c94a00 --- /dev/null +++ b/drivers/net/wireless/rtl8188E_8192E/hal/rtl8188e/sdio/sdio_ops.c @@ -0,0 +1,1940 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + *******************************************************************************/ +#define _SDIO_OPS_C_ + +#include <drv_types.h> +#include <rtl8188e_hal.h> +#include <rtl8188e_spec.h> + +//#define SDIO_DEBUG_IO 1 + +#define SDIO_ERR_VAL8 0xEA +#define SDIO_ERR_VAL16 0xEAEA +#define SDIO_ERR_VAL32 0xEAEAEAEA + +extern u8 sd_f0_read8(PSDIO_DATA psdio, u32 addr, s32 *err); +extern void sd_f0_write8(PSDIO_DATA psdio, u32 addr, s32 *err); + +extern s32 _sd_cmd52_read(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata); +extern s32 _sd_cmd52_write(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata); +extern s32 sd_cmd52_read(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata); +extern s32 sd_cmd52_write(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata); + +extern u8 _sd_read8(PSDIO_DATA psdio, u32 addr, s32 *err); +extern u8 sd_read8(PSDIO_DATA psdio, u32 addr, s32 *err); +extern u16 sd_read16(PSDIO_DATA psdio, u32 addr, s32 *err); +extern u32 _sd_read32(PSDIO_DATA psdio, u32 addr, s32 *err); +extern u32 sd_read32(PSDIO_DATA psdio, u32 addr, s32 *err); +extern s32 _sd_read(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata); +extern s32 sd_read(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata); +extern void sd_write8(PSDIO_DATA psdio, u32 addr, u8 v, s32 *err); +extern void sd_write16(PSDIO_DATA psdio, u32 addr, u16 v, s32 *err); +extern void _sd_write32(PSDIO_DATA psdio, u32 addr, u32 v, s32 *err); +extern void sd_write32(PSDIO_DATA psdio, u32 addr, u32 v, s32 *err); +extern s32 _sd_write(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata); +extern s32 sd_write(PSDIO_DATA psdio, u32 addr, u32 cnt, void *pdata); + +#ifdef CONFIG_EXT_CLK +void EnableGpio5ClockReq(PADAPTER Adapter, u8 in_interrupt, u32 Enable); +#endif //CONFIG_EXT_CLK + +// +// Description: +// The following mapping is for SDIO host local register space. +// +// Creadted by Roger, 2011.01.31. +// +static void HalSdioGetCmdAddr8723ASdio( + IN PADAPTER padapter, + IN u8 DeviceID, + IN u32 Addr, + OUT u32* pCmdAddr + ) +{ + switch (DeviceID) + { + case SDIO_LOCAL_DEVICE_ID: + *pCmdAddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (Addr & SDIO_LOCAL_MSK)); + break; + + case WLAN_IOREG_DEVICE_ID: + *pCmdAddr = ((WLAN_IOREG_DEVICE_ID << 13) | (Addr & WLAN_IOREG_MSK)); + break; + + case WLAN_TX_HIQ_DEVICE_ID: + *pCmdAddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK)); + break; + + case WLAN_TX_MIQ_DEVICE_ID: + *pCmdAddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK)); + break; + + case WLAN_TX_LOQ_DEVICE_ID: + *pCmdAddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK)); + break; + + case WLAN_RX0FF_DEVICE_ID: + *pCmdAddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (Addr & WLAN_RX0FF_MSK)); + break; + + default: + break; + } +} + +static u8 get_deviceid(u32 addr) +{ + u8 devideId; + u16 pseudoId; + + + pseudoId = (u16)(addr >> 16); + switch (pseudoId) + { + case 0x1025: + devideId = SDIO_LOCAL_DEVICE_ID; + break; + + case 0x1026: + devideId = WLAN_IOREG_DEVICE_ID; + break; + +// case 0x1027: +// devideId = SDIO_FIRMWARE_FIFO; +// break; + + case 0x1031: + devideId = WLAN_TX_HIQ_DEVICE_ID; + break; + + case 0x1032: + devideId = WLAN_TX_MIQ_DEVICE_ID; + break; + + case 0x1033: + devideId = WLAN_TX_LOQ_DEVICE_ID; + break; + + case 0x1034: + devideId = WLAN_RX0FF_DEVICE_ID; + break; + + default: +// devideId = (u8)((addr >> 13) & 0xF); + devideId = WLAN_IOREG_DEVICE_ID; + break; + } + + return devideId; +} + +/* + * Ref: + * HalSdioGetCmdAddr8723ASdio() + */ +static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset) +{ + u8 deviceId; + u16 offset; + u32 ftaddr; + + + deviceId = get_deviceid(addr); + offset = 0; + + switch (deviceId) + { + case SDIO_LOCAL_DEVICE_ID: + offset = addr & SDIO_LOCAL_MSK; + break; + + case WLAN_TX_HIQ_DEVICE_ID: + case WLAN_TX_MIQ_DEVICE_ID: + case WLAN_TX_LOQ_DEVICE_ID: + offset = addr & WLAN_FIFO_MSK; + break; + + case WLAN_RX0FF_DEVICE_ID: + offset = addr & WLAN_RX0FF_MSK; + break; + + case WLAN_IOREG_DEVICE_ID: + default: + deviceId = WLAN_IOREG_DEVICE_ID; + offset = addr & WLAN_IOREG_MSK; + break; + } + ftaddr = (deviceId << 13) | offset; + + if (pdeviceId) *pdeviceId = deviceId; + if (poffset) *poffset = offset; + + return ftaddr; +} + +u8 _sdio_read8(PADAPTER padapter, u32 addr) +{ + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u32 ftaddr; + u8 val; + +_func_enter_; + + //psdiodev = pintfhdl->pintf_dev; + //psdio = &psdiodev->intf_data; + psdiodev = adapter_to_dvobj(padapter); + psdio = &psdiodev->intf_data; + + ftaddr = _cvrt2ftaddr(addr, NULL, NULL); + val = _sd_read8(psdio, ftaddr, NULL); + +_func_exit_; + + return val; +} + +u8 sdio_read8(struct intf_hdl *pintfhdl, u32 addr) +{ + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u32 ftaddr; + u8 val; + +_func_enter_; + + psdiodev = pintfhdl->pintf_dev; + psdio = &psdiodev->intf_data; + + ftaddr = _cvrt2ftaddr(addr, NULL, NULL); + val = sd_read8(psdio, ftaddr, NULL); + +_func_exit_; + + return val; +} + +u16 sdio_read16(struct intf_hdl *pintfhdl, u32 addr) +{ + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u32 ftaddr; + u16 val; + +_func_enter_; + + psdiodev = pintfhdl->pintf_dev; + psdio = &psdiodev->intf_data; + + ftaddr = _cvrt2ftaddr(addr, NULL, NULL); + sd_cmd52_read(psdio, ftaddr, 2, (u8*)&val); + val = le16_to_cpu(val); + +_func_exit_; + + return val; +} + +u32 _sdio_read32(PADAPTER padapter, u32 addr) +{ + //PADAPTER padapter; + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + u8 deviceId; + u16 offset; + u32 ftaddr; + u8 shift; + u32 val; + s32 err; + +_func_enter_; + + //padapter = pintfhdl->padapter; + //psdiodev = pintfhdl->pintf_dev; + psdiodev = adapter_to_dvobj(padapter); + psdio = &psdiodev->intf_data; + + ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) + || (_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + err = _sd_cmd52_read(psdio, ftaddr, 4, (u8*)&val); +#ifdef SDIO_DEBUG_IO + if (!err) { +#endif + val = le32_to_cpu(val); + return val; +#ifdef SDIO_DEBUG_IO + } + + DBG_871X(KERN_ERR "%s: Mac Power off, Read FAIL(%d)! addr=0x%x\n", __func__, err, addr); + return SDIO_ERR_VAL32; +#endif + } + + // 4 bytes alignment + shift = ftaddr & 0x3; + if (shift == 0) { + val = _sd_read32(psdio, ftaddr, NULL); + } else { + u8 *ptmpbuf; + + ptmpbuf = (u8*)rtw_malloc(8); + if (NULL == ptmpbuf) { + DBG_871X(KERN_ERR "%s: Allocate memory FAIL!(size=8) addr=0x%x\n", __func__, addr); + return SDIO_ERR_VAL32; + } + + ftaddr &= ~(u16)0x3; + _sd_read(psdio, ftaddr, 8, ptmpbuf); + _rtw_memcpy(&val, ptmpbuf+shift, 4); + val = le32_to_cpu(val); + + rtw_mfree(ptmpbuf, 8); + } + +_func_exit_; + + return val; +} + +u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr) +{ + PADAPTER padapter; + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + u8 deviceId; + u16 offset; + u32 ftaddr; + u8 shift; + u32 val; + s32 err; + +_func_enter_; + + padapter = pintfhdl->padapter; + psdiodev = pintfhdl->pintf_dev; + psdio = &psdiodev->intf_data; + + ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) + || (_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + err = sd_cmd52_read(psdio, ftaddr, 4, (u8*)&val); +#ifdef SDIO_DEBUG_IO + if (!err) { +#endif + val = le32_to_cpu(val); + return val; +#ifdef SDIO_DEBUG_IO + } + + DBG_871X(KERN_ERR "%s: Mac Power off, Read FAIL(%d)! addr=0x%x\n", __func__, err, addr); + return SDIO_ERR_VAL32; +#endif + } + + // 4 bytes alignment + shift = ftaddr & 0x3; + if (shift == 0) { + val = sd_read32(psdio, ftaddr, NULL); + } else { + u8 *ptmpbuf; + + ptmpbuf = (u8*)rtw_malloc(8); + if (NULL == ptmpbuf) { + DBG_871X(KERN_ERR "%s: Allocate memory FAIL!(size=8) addr=0x%x\n", __func__, addr); + return SDIO_ERR_VAL32; + } + + ftaddr &= ~(u16)0x3; + sd_read(psdio, ftaddr, 8, ptmpbuf); + _rtw_memcpy(&val, ptmpbuf+shift, 4); + val = le32_to_cpu(val); + + rtw_mfree(ptmpbuf, 8); + } + +_func_exit_; + + return val; +} + +s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8* pbuf) +{ + PADAPTER padapter; + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + u8 deviceId; + u16 offset; + u32 ftaddr; + u8 shift; + s32 err; + +_func_enter_; + + padapter = pintfhdl->padapter; + psdiodev = pintfhdl->pintf_dev; + psdio = &psdiodev->intf_data; + err = 0; + + ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) + || (_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + err = sd_cmd52_read(psdio, ftaddr, cnt, pbuf); + return err; + } + + // 4 bytes alignment + shift = ftaddr & 0x3; + if (shift == 0) { + err = sd_read(psdio, ftaddr, cnt, pbuf); + } else { + u8 *ptmpbuf; + u32 n; + + ftaddr &= ~(u16)0x3; + n = cnt + shift; + ptmpbuf = rtw_malloc(n); + if (NULL == ptmpbuf) return -1; + err = sd_read(psdio, ftaddr, n, ptmpbuf); + if (!err) + _rtw_memcpy(pbuf, ptmpbuf+shift, cnt); + rtw_mfree(ptmpbuf, n); + } + +_func_exit_; + + return err; +} + +s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val) +{ + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u32 ftaddr; + s32 err; + +_func_enter_; + + psdiodev = pintfhdl->pintf_dev; + psdio = &psdiodev->intf_data; + + ftaddr = _cvrt2ftaddr(addr, NULL, NULL); + sd_write8(psdio, ftaddr, val, &err); + +_func_exit_; + + return err; +} + +s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val) +{ + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u32 ftaddr; + u8 shift; + s32 err; + +_func_enter_; + + psdiodev = pintfhdl->pintf_dev; + psdio = &psdiodev->intf_data; + + ftaddr = _cvrt2ftaddr(addr, NULL, NULL); + val = cpu_to_le16(val); + err = sd_cmd52_write(psdio, ftaddr, 2, (u8*)&val); + +_func_exit_; + + return err; +} + +s32 _sdio_write32(PADAPTER padapter, u32 addr, u32 val) +{ + //PADAPTER padapter; + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + u8 deviceId; + u16 offset; + u32 ftaddr; + u8 shift; + s32 err; + +_func_enter_; + + //padapter = pintfhdl->padapter; + //psdiodev = pintfhdl->pintf_dev; + psdiodev = adapter_to_dvobj(padapter); + psdio = &psdiodev->intf_data; + err = 0; + + ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) + || (_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + val = cpu_to_le32(val); + err = _sd_cmd52_write(psdio, ftaddr, 4, (u8*)&val); + return err; + } + + // 4 bytes alignment + shift = ftaddr & 0x3; +#if 1 + if (shift == 0) + { + _sd_write32(psdio, ftaddr, val, &err); + } + else + { + val = cpu_to_le32(val); + err = _sd_cmd52_write(psdio, ftaddr, 4, (u8*)&val); + } +#else + if (shift == 0) { + sd_write32(psdio, ftaddr, val, &err); + } else { + u8 *ptmpbuf; + + ptmpbuf = (u8*)rtw_malloc(8); + if (NULL == ptmpbuf) return (-1); + + ftaddr &= ~(u16)0x3; + err = sd_read(psdio, ftaddr, 8, ptmpbuf); + if (err) { + _rtw_mfree(ptmpbuf, 8); + return err; + } + val = cpu_to_le32(val); + _rtw_memcpy(ptmpbuf+shift, &val, 4); + err = sd_write(psdio, ftaddr, 8, ptmpbuf); + + rtw_mfree(ptmpbuf, 8); + } +#endif + +_func_exit_; + + return err; +} + + +s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val) +{ + PADAPTER padapter; + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + u8 deviceId; + u16 offset; + u32 ftaddr; + u8 shift; + s32 err; + +_func_enter_; + + padapter = pintfhdl->padapter; + psdiodev = pintfhdl->pintf_dev; + psdio = &psdiodev->intf_data; + err = 0; + + ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) + || (_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + val = cpu_to_le32(val); + err = sd_cmd52_write(psdio, ftaddr, 4, (u8*)&val); + return err; + } + + // 4 bytes alignment + shift = ftaddr & 0x3; +#if 1 + if (shift == 0) + { + sd_write32(psdio, ftaddr, val, &err); + } + else + { + val = cpu_to_le32(val); + err = sd_cmd52_write(psdio, ftaddr, 4, (u8*)&val); + } +#else + if (shift == 0) { + sd_write32(psdio, ftaddr, val, &err); + } else { + u8 *ptmpbuf; + + ptmpbuf = (u8*)rtw_malloc(8); + if (NULL == ptmpbuf) return (-1); + + ftaddr &= ~(u16)0x3; + err = sd_read(psdio, ftaddr, 8, ptmpbuf); + if (err) { + _rtw_mfree(ptmpbuf, 8); + return err; + } + val = cpu_to_le32(val); + _rtw_memcpy(ptmpbuf+shift, &val, 4); + err = sd_write(psdio, ftaddr, 8, ptmpbuf); + + rtw_mfree(ptmpbuf, 8); + } +#endif + +_func_exit_; + + return err; +} + +s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8* pbuf) +{ + PADAPTER padapter; + struct dvobj_priv *psdiodev; + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + u8 deviceId; + u16 offset; + u32 ftaddr; + u8 shift; + s32 err; + +_func_enter_; + + padapter = pintfhdl->padapter; + psdiodev = pintfhdl->pintf_dev; + psdio = &psdiodev->intf_data; + err = 0; + + ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) + || (_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + err = sd_cmd52_write(psdio, ftaddr, cnt, pbuf); + return err; + } + + shift = ftaddr & 0x3; + if (shift == 0) { + err = sd_write(psdio, ftaddr, cnt, pbuf); + } else { + u8 *ptmpbuf; + u32 n; + + ftaddr &= ~(u16)0x3; + n = cnt + shift; + ptmpbuf = rtw_malloc(n); + if (NULL == ptmpbuf) return -1; + err = sd_read(psdio, ftaddr, 4, ptmpbuf); + if (err) { + rtw_mfree(ptmpbuf, n); + return err; + } + _rtw_memcpy(ptmpbuf+shift, pbuf, cnt); + err = sd_write(psdio, ftaddr, n, ptmpbuf); + rtw_mfree(ptmpbuf, n); + } + +_func_exit_; + + return err; +} + +void sdio_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) +{ + s32 err; + +_func_enter_; + + err = sdio_readN(pintfhdl, addr, cnt, rmem); + +_func_exit_; +} + +void sdio_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) +{ +_func_enter_; + + sdio_writeN(pintfhdl, addr, cnt, wmem); + +_func_exit_; +} + +/* + * Description: + * Read from RX FIFO + * Round read size to block size, + * and make sure data transfer will be done in one command. + * + * Parameters: + * pintfhdl a pointer of intf_hdl + * addr port ID + * cnt size to read + * rmem address to put data + * + * Return: + * _SUCCESS(1) Success + * _FAIL(0) Fail + */ +static u32 sdio_read_port( + struct intf_hdl *pintfhdl, + u32 addr, + u32 cnt, + u8 *mem) +{ + PADAPTER padapter = pintfhdl->padapter; + PSDIO_DATA psdio= &adapter_to_dvobj(padapter)->intf_data; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + s32 err; + + HalSdioGetCmdAddr8723ASdio(padapter, addr, pHalData->SdioRxFIFOCnt++, &addr); + + + cnt = _RND4(cnt); + if (cnt > psdio->block_transfer_len) + cnt = _RND(cnt, psdio->block_transfer_len); + +// cnt = sdio_align_size(cnt); + + err = _sd_read(psdio, addr, cnt, mem); + //err = sd_read(psdio, addr, cnt, mem); + + + + if (err) return _FAIL; + return _SUCCESS; +} + +/* + * Description: + * Write to TX FIFO + * Align write size block size, + * and make sure data could be written in one command. + * + * Parameters: + * pintfhdl a pointer of intf_hdl + * addr port ID + * cnt size to write + * wmem data pointer to write + * + * Return: + * _SUCCESS(1) Success + * _FAIL(0) Fail + */ +static u32 sdio_write_port( + struct intf_hdl *pintfhdl, + u32 addr, + u32 cnt, + u8 *mem) +{ + PADAPTER padapter; + PSDIO_DATA psdio; + s32 err; + struct xmit_buf *xmitbuf = (struct xmit_buf *)mem; + + padapter = pintfhdl->padapter; + psdio = &adapter_to_dvobj(padapter)->intf_data; + + cnt = _RND4(cnt); + HalSdioGetCmdAddr8723ASdio(padapter, addr, cnt >> 2, &addr); + + if (cnt > psdio->block_transfer_len) + cnt = _RND(cnt, psdio->block_transfer_len); +// cnt = sdio_align_size(cnt); + + err = sd_write(psdio, addr, cnt, xmitbuf->pdata); + + rtw_sctx_done_err(&xmitbuf->sctx, + err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS); + + if (err) + { + DBG_871X("%s, error=%d\n", __func__, err); + + return _FAIL; + } + return _SUCCESS; +} + +void sdio_set_intf_ops(struct _io_ops *pops) +{ +_func_enter_; + + pops->_read8 = &sdio_read8; + pops->_read16 = &sdio_read16; + pops->_read32 = &sdio_read32; + pops->_read_mem = &sdio_read_mem; + pops->_read_port = &sdio_read_port; + + pops->_write8 = &sdio_write8; + pops->_write16 = &sdio_write16; + pops->_write32 = &sdio_write32; + pops->_writeN = &sdio_writeN; + pops->_write_mem = &sdio_write_mem; + pops->_write_port = &sdio_write_port; + +_func_exit_; +} + +/* + * Todo: align address to 4 bytes. + */ +s32 _sdio_local_read( + PADAPTER padapter, + u32 addr, + u32 cnt, + u8 *pbuf) +{ + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + s32 err; + u8 *ptmpbuf; + u32 n; + + + psdio = &adapter_to_dvobj(padapter)->intf_data; + + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if ((_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK +// || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + err = _sd_cmd52_read(psdio, addr, cnt, pbuf); + return err; + } + + n = RND4(cnt); + ptmpbuf = (u8*)rtw_malloc(n); + if(!ptmpbuf) + return (-1); + + err = _sd_read(psdio, addr, n, ptmpbuf); + if (!err) + _rtw_memcpy(pbuf, ptmpbuf, cnt); + + if(ptmpbuf) + rtw_mfree(ptmpbuf, n); + + return err; +} + +/* + * Todo: align address to 4 bytes. + */ +s32 sdio_local_read( + PADAPTER padapter, + u32 addr, + u32 cnt, + u8 *pbuf) +{ + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + s32 err; + u8 *ptmpbuf; + u32 n; + + + psdio = &adapter_to_dvobj(padapter)->intf_data; + + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if ((_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + err = sd_cmd52_read(psdio, addr, cnt, pbuf); + return err; + } + + n = RND4(cnt); + ptmpbuf = (u8*)rtw_malloc(n); + if(!ptmpbuf) + return (-1); + + err = sd_read(psdio, addr, n, ptmpbuf); + if (!err) + _rtw_memcpy(pbuf, ptmpbuf, cnt); + + if(ptmpbuf) + rtw_mfree(ptmpbuf, n); + + return err; +} + +/* + * Todo: align address to 4 bytes. + */ +s32 _sdio_local_write( + PADAPTER padapter, + u32 addr, + u32 cnt, + u8 *pbuf) +{ + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + s32 err; + u8 *ptmpbuf; + + if(addr & 0x3) + DBG_8192C("%s, address must be 4 bytes alignment\n", __FUNCTION__); + + if(cnt & 0x3) + DBG_8192C("%s, size must be the multiple of 4 \n", __FUNCTION__); + + psdio = &adapter_to_dvobj(padapter)->intf_data; + + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if ((_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK +// || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + err = _sd_cmd52_write(psdio, addr, cnt, pbuf); + return err; + } + + ptmpbuf = (u8*)rtw_malloc(cnt); + if(!ptmpbuf) + return (-1); + + _rtw_memcpy(ptmpbuf, pbuf, cnt); + + err = _sd_write(psdio, addr, cnt, ptmpbuf); + + if (ptmpbuf) + rtw_mfree(ptmpbuf, cnt); + + return err; +} + +/* + * Todo: align address to 4 bytes. + */ +s32 sdio_local_write( + PADAPTER padapter, + u32 addr, + u32 cnt, + u8 *pbuf) +{ + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + s32 err; + u8 *ptmpbuf; + + if(addr & 0x3) + DBG_8192C("%s, address must be 4 bytes alignment\n", __FUNCTION__); + + if(cnt & 0x3) + DBG_8192C("%s, size must be the multiple of 4 \n", __FUNCTION__); + + psdio = &adapter_to_dvobj(padapter)->intf_data; + + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if ((_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + err = sd_cmd52_write(psdio, addr, cnt, pbuf); + return err; + } + + ptmpbuf = (u8*)rtw_malloc(cnt); + if(!ptmpbuf) + return (-1); + + _rtw_memcpy(ptmpbuf, pbuf, cnt); + + err = sd_write(psdio, addr, cnt, ptmpbuf); + + if (ptmpbuf) + rtw_mfree(ptmpbuf, cnt); + + return err; +} + +u8 SdioLocalCmd52Read1Byte(PADAPTER padapter, u32 addr) +{ + PSDIO_DATA psdio; + u8 val = 0; + + + psdio = &adapter_to_dvobj(padapter)->intf_data; + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + sd_cmd52_read(psdio, addr, 1, &val); + + return val; +} + +u16 SdioLocalCmd52Read2Byte(PADAPTER padapter, u32 addr) +{ + PSDIO_DATA psdio; + u16 val = 0; + + + psdio = &adapter_to_dvobj(padapter)->intf_data; + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + sd_cmd52_read(psdio, addr, 2, (u8*)&val); + + val = le16_to_cpu(val); + + return val; +} + +u32 SdioLocalCmd52Read4Byte(PADAPTER padapter, u32 addr) +{ + PSDIO_DATA psdio; + u32 val = 0; + + + psdio = &adapter_to_dvobj(padapter)->intf_data; + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + sd_cmd52_read(psdio, addr, 4, (u8*)&val); + + val = le32_to_cpu(val); + + return val; +} + +u32 SdioLocalCmd53Read4Byte(PADAPTER padapter, u32 addr) +{ + PSDIO_DATA psdio; + u8 bMacPwrCtrlOn; + u32 val; + + + val = 0; + psdio = &adapter_to_dvobj(padapter)->intf_data; + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if ((_FALSE == bMacPwrCtrlOn) +#ifdef CONFIG_LPS_LCLK + || (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode) +#endif + ) + { + sd_cmd52_read(psdio, addr, 4, (u8*)&val); + val = le32_to_cpu(val); + } + else + val = sd_read32(psdio, addr, NULL); + + return val; +} + +void SdioLocalCmd52Write1Byte(PADAPTER padapter, u32 addr, u8 v) +{ + PSDIO_DATA psdio; + + + psdio = &adapter_to_dvobj(padapter)->intf_data; + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + sd_cmd52_write(psdio, addr, 1, &v); +} + +void SdioLocalCmd52Write2Byte(PADAPTER padapter, u32 addr, u16 v) +{ + PSDIO_DATA psdio; + + + psdio = &adapter_to_dvobj(padapter)->intf_data; + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + v = cpu_to_le16(v); + sd_cmd52_write(psdio, addr, 2, (u8*)&v); +} + +void SdioLocalCmd52Write4Byte(PADAPTER padapter, u32 addr, u32 v) +{ + PSDIO_DATA psdio; + + + psdio = &adapter_to_dvobj(padapter)->intf_data; + HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); + v = cpu_to_le32(v); + sd_cmd52_write(psdio, addr, 4, (u8*)&v); +} + +#if 0 +void +DumpLoggedInterruptHistory8723Sdio( + PADAPTER padapter +) +{ + HAL_DATA_TYPE *pHalData=GET_HAL_DATA(padapter); + u4Byte DebugLevel = DBG_LOUD; + + if (DBG_Var.DbgPrintIsr == 0) + return; + + DBG_ChkDrvResource(padapter); + + + if(pHalData->InterruptLog.nISR_RX_REQUEST) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# RX_REQUEST[%ld]\t\n", pHalData->InterruptLog.nISR_RX_REQUEST)); + + if(pHalData->InterruptLog.nISR_AVAL) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# AVAL[%ld]\t\n", pHalData->InterruptLog.nISR_AVAL)); + + if(pHalData->InterruptLog.nISR_TXERR) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# TXERR[%ld]\t\n", pHalData->InterruptLog.nISR_TXERR)); + + if(pHalData->InterruptLog.nISR_RXERR) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# RXERR[%ld]\t\n", pHalData->InterruptLog.nISR_RXERR)); + + if(pHalData->InterruptLog.nISR_TXFOVW) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# TXFOVW[%ld]\t\n", pHalData->InterruptLog.nISR_TXFOVW)); + + if(pHalData->InterruptLog.nISR_RXFOVW) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# RXFOVW[%ld]\t\n", pHalData->InterruptLog.nISR_RXFOVW)); + + if(pHalData->InterruptLog.nISR_TXBCNOK) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# TXBCNOK[%ld]\t\n", pHalData->InterruptLog.nISR_TXBCNOK)); + + if(pHalData->InterruptLog.nISR_TXBCNERR) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# TXBCNERR[%ld]\t\n", pHalData->InterruptLog.nISR_TXBCNERR)); + + if(pHalData->InterruptLog.nISR_BCNERLY_INT) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# BCNERLY_INT[%ld]\t\n", pHalData->InterruptLog.nISR_BCNERLY_INT)); + + if(pHalData->InterruptLog.nISR_C2HCMD) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# C2HCMD[%ld]\t\n", pHalData->InterruptLog.nISR_C2HCMD)); + + if(pHalData->InterruptLog.nISR_CPWM1) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# CPWM1L[%ld]\t\n", pHalData->InterruptLog.nISR_CPWM1)); + + if(pHalData->InterruptLog.nISR_CPWM2) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# CPWM2[%ld]\t\n", pHalData->InterruptLog.nISR_CPWM2)); + + if(pHalData->InterruptLog.nISR_HSISR_IND) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# HSISR_IND[%ld]\t\n", pHalData->InterruptLog.nISR_HSISR_IND)); + + if(pHalData->InterruptLog.nISR_GTINT3_IND) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# GTINT3_IND[%ld]\t\n", pHalData->InterruptLog.nISR_GTINT3_IND)); + + if(pHalData->InterruptLog.nISR_GTINT4_IND) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# GTINT4_IND[%ld]\t\n", pHalData->InterruptLog.nISR_GTINT4_IND)); + + if(pHalData->InterruptLog.nISR_PSTIMEOUT) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# PSTIMEOUT[%ld]\t\n", pHalData->InterruptLog.nISR_PSTIMEOUT)); + + if(pHalData->InterruptLog.nISR_OCPINT) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# OCPINT[%ld]\t\n", pHalData->InterruptLog.nISR_OCPINT)); + + if(pHalData->InterruptLog.nISR_ATIMEND) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# ATIMEND[%ld]\t\n", pHalData->InterruptLog.nISR_ATIMEND)); + + if(pHalData->InterruptLog.nISR_ATIMEND_E) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# ATIMEND_E[%ld]\t\n", pHalData->InterruptLog.nISR_ATIMEND_E)); + + if(pHalData->InterruptLog.nISR_CTWEND) + RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# CTWEND[%ld]\t\n", pHalData->InterruptLog.nISR_CTWEND)); +} + +void +LogInterruptHistory8723Sdio( + PADAPTER padapter, + PRT_ISR_CONTENT pIsrContent +) +{ + HAL_DATA_TYPE *pHalData=GET_HAL_DATA(padapter); + + if((pHalData->IntrMask[0] & SDIO_HIMR_RX_REQUEST_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_RX_REQUEST)) + pHalData->InterruptLog.nISR_RX_REQUEST ++; + if((pHalData->IntrMask[0] & SDIO_HIMR_AVAL_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_AVAL)) + pHalData->InterruptLog.nISR_AVAL++; + if((pHalData->IntrMask[0] & SDIO_HIMR_TXERR_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_TXERR)) + pHalData->InterruptLog.nISR_TXERR++; + if((pHalData->IntrMask[0] & SDIO_HIMR_RXERR_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_RXERR)) + pHalData->InterruptLog.nISR_RXERR++; + if((pHalData->IntrMask[0] & SDIO_HIMR_TXFOVW_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_TXFOVW)) + pHalData->InterruptLog.nISR_TXFOVW++; + if((pHalData->IntrMask[0] & SDIO_HIMR_RXFOVW_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_RXFOVW)) + pHalData->InterruptLog.nISR_RXFOVW++; + if((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNOK_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNOK)) + pHalData->InterruptLog.nISR_TXBCNOK++; + if((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNERR_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNERR)) + pHalData->InterruptLog.nISR_TXBCNERR++; + if((pHalData->IntrMask[0] & SDIO_HIMR_BCNERLY_INT_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_BCNERLY_INT)) + pHalData->InterruptLog.nISR_BCNERLY_INT ++; + if((pHalData->IntrMask[0] & SDIO_HIMR_C2HCMD_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_C2HCMD)) + pHalData->InterruptLog.nISR_C2HCMD++; + if((pHalData->IntrMask[0] & SDIO_HIMR_CPWM1_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_CPWM1)) + pHalData->InterruptLog.nISR_CPWM1++; + if((pHalData->IntrMask[0] & SDIO_HIMR_CPWM2_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_CPWM2)) + pHalData->InterruptLog.nISR_CPWM2++; + if((pHalData->IntrMask[0] & SDIO_HIMR_HSISR_IND_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_HSISR_IND)) + pHalData->InterruptLog.nISR_HSISR_IND++; + if((pHalData->IntrMask[0] & SDIO_HIMR_GTINT3_IND_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_GTINT3_IND)) + pHalData->InterruptLog.nISR_GTINT3_IND++; + if((pHalData->IntrMask[0] & SDIO_HIMR_GTINT4_IND_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_GTINT4_IND)) + pHalData->InterruptLog.nISR_GTINT4_IND++; + if((pHalData->IntrMask[0] & SDIO_HIMR_PSTIMEOUT_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_PSTIMEOUT)) + pHalData->InterruptLog.nISR_PSTIMEOUT++; + if((pHalData->IntrMask[0] & SDIO_HIMR_OCPINT_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_OCPINT)) + pHalData->InterruptLog.nISR_OCPINT++; + if((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND)) + pHalData->InterruptLog.nISR_ATIMEND++; + if((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_E_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND_E)) + pHalData->InterruptLog.nISR_ATIMEND_E++; + if((pHalData->IntrMask[0] & SDIO_HIMR_CTWEND_MSK) && + (pIsrContent->IntArray[0] & SDIO_HISR_CTWEND)) + pHalData->InterruptLog.nISR_CTWEND++; + +} + +void +DumpHardwareProfile8723Sdio( + IN PADAPTER padapter +) +{ + DumpLoggedInterruptHistory8723Sdio(padapter); +} +#endif + +// +// Description: +// Initialize SDIO Host Interrupt Mask configuration variables for future use. +// +// Assumption: +// Using SDIO Local register ONLY for configuration. +// +// Created by Roger, 2011.02.11. +// +void InitInterrupt8188ESdio(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData; + + + pHalData = GET_HAL_DATA(padapter); + pHalData->sdio_himr = (u32)( \ + SDIO_HIMR_RX_REQUEST_MSK | +// SDIO_HIMR_AVAL_MSK | +// SDIO_HIMR_TXERR_MSK | +// SDIO_HIMR_RXERR_MSK | +// SDIO_HIMR_TXFOVW_MSK | +// SDIO_HIMR_RXFOVW_MSK | +// SDIO_HIMR_TXBCNOK_MSK | +// SDIO_HIMR_TXBCNERR_MSK | +#ifdef CONFIG_EXT_CLK //for sprd + SDIO_HIMR_BCNERLY_INT_MSK | +#endif //CONFIG_EXT_CLK +// SDIO_HIMR_C2HCMD_MSK | +#ifdef CONFIG_LPS_LCLK + SDIO_HIMR_CPWM1_MSK | + SDIO_HIMR_CPWM2_MSK | +#endif +// SDIO_HIMR_HSISR_IND_MSK | +// SDIO_HIMR_GTINT3_IND_MSK | +// SDIO_HIMR_GTINT4_IND_MSK | +// SDIO_HIMR_PSTIMEOUT_MSK | +// SDIO_HIMR_OCPINT_MSK | +// SDIO_HIMR_ATIMEND_MSK | +// SDIO_HIMR_ATIMEND_E_MSK | +// SDIO_HIMR_CTWEND_MSK | + 0); +} + +// +// Description: +// Clear corresponding SDIO Host ISR interrupt service. +// +// Assumption: +// Using SDIO Local register ONLY for configuration. +// +// Created by Roger, 2011.02.11. +// +void ClearInterrupt8723ASdio(PADAPTER padapter) +{ + u32 tmp = 0; + tmp = SdioLocalCmd52Read4Byte(padapter, SDIO_REG_HISR); + SdioLocalCmd52Write4Byte(padapter, SDIO_REG_HISR, tmp); +// padapter->IsrContent.IntArray[0] = 0; + padapter->IsrContent = 0; +} + +// +// Description: +// Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. +// +// Assumption: +// 1. Using SDIO Local register ONLY for configuration. +// 2. PASSIVE LEVEL +// +// Created by Roger, 2011.02.11. +// +void EnableInterrupt8188ESdio(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData; + u32 himr; + +#ifdef CONFIG_CONCURRENT_MODE + if ((padapter->isprimary == _FALSE) && padapter->pbuddy_adapter){ + padapter = padapter->pbuddy_adapter; + } +#endif + pHalData = GET_HAL_DATA(padapter); + himr = cpu_to_le32(pHalData->sdio_himr); + sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8*)&himr); + + + // + // <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. + // So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. + // 2011.10.19. + // + rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); + +} + +// +// Description: +// Disable SDIO Host IMR configuration to mask unnecessary interrupt service. +// +// Assumption: +// Using SDIO Local register ONLY for configuration. +// +// Created by Roger, 2011.02.11. +// +void DisableInterrupt8188ESdio(PADAPTER padapter) +{ + u32 himr; + +#ifdef CONFIG_CONCURRENT_MODE + if ((padapter->isprimary == _FALSE) && padapter->pbuddy_adapter){ + padapter = padapter->pbuddy_adapter; + } +#endif + himr = cpu_to_le32(SDIO_HIMR_DISABLED); + sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8*)&himr); + +} + +// +// Description: +// Update SDIO Host Interrupt Mask configuration on SDIO local domain. +// +// Assumption: +// 1. Using SDIO Local register ONLY for configuration. +// 2. PASSIVE LEVEL +// +// Created by Roger, 2011.02.11. +// +void UpdateInterruptMask8188ESdio(PADAPTER padapter, u32 AddMSR, u32 RemoveMSR) +{ + HAL_DATA_TYPE *pHalData; + +#ifdef CONFIG_CONCURRENT_MODE + if ((padapter->isprimary == _FALSE) && padapter->pbuddy_adapter){ + padapter = padapter->pbuddy_adapter; + } +#endif + pHalData = GET_HAL_DATA(padapter); + + if (AddMSR) + pHalData->sdio_himr |= AddMSR; + + if (RemoveMSR) + pHalData->sdio_himr &= (~RemoveMSR); + + DisableInterrupt8188ESdio(padapter); + EnableInterrupt8188ESdio(padapter); +} + +#ifdef CONFIG_WOWLAN +void ClearInterrupt8189ESdio(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u32 v32; + + pHalData->sdio_hisr &= pHalData->sdio_himr; + + // clear HISR + v32 = pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR; + if (v32) { + v32 = cpu_to_le32(v32); + _sdio_local_write(padapter, SDIO_REG_HISR, 4, (u8*)&v32); + } +} +#endif + +#ifdef CONFIG_MAC_LOOPBACK_DRIVER +static void sd_recv_loopback(PADAPTER padapter, u32 size) +{ + PLOOPBACKDATA ploopback; + u32 readsize, allocsize; + u8 *preadbuf; + + + readsize = size; + DBG_8192C("%s: read size=%d\n", __func__, readsize); + allocsize = _RND(readsize, adapter_to_dvobj(padapter)->intf_data.block_transfer_len); + + ploopback = padapter->ploopback; + if (ploopback) { + ploopback->rxsize = readsize; + preadbuf = ploopback->rxbuf; + } + else { + preadbuf = rtw_malloc(allocsize); + if (preadbuf == NULL) { + DBG_8192C("%s: malloc fail size=%d\n", __func__, allocsize); + return; + } + } + +// rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); + sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); + + if (ploopback) + _rtw_up_sema(&ploopback->sema); + else { + u32 i; + + DBG_8192C("%s: drop pkt\n", __func__); + for (i = 0; i < readsize; i+=4) { + DBG_8192C("%08X", *(u32*)(preadbuf + i)); + if ((i+4) & 0x1F) printk(" "); + else printk("\n"); + } + printk("\n"); + rtw_mfree(preadbuf, allocsize); + } +} +#endif // CONFIG_MAC_LOOPBACK_DRIVER + +#ifdef CONFIG_SDIO_RX_COPY +static struct recv_buf* sd_recv_rxfifo(PADAPTER padapter, u32 size) +{ + u32 readsize, ret; + u8 *preadbuf; + struct recv_priv *precvpriv; + struct recv_buf *precvbuf; + + + readsize = size; + + //3 1. alloc recvbuf + precvpriv = &padapter->recvpriv; + precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue); + if (precvbuf == NULL) { + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc recvbuf FAIL!\n", __FUNCTION__)); + return NULL; + } + + //3 2. alloc skb + if (precvbuf->pskb == NULL) { + SIZE_PTR tmpaddr=0; + SIZE_PTR alignment=0; + + DBG_871X("%s: alloc_skb for rx buffer\n", __FUNCTION__); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html + precvbuf->pskb = __dev_alloc_skb(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL); +#else + precvbuf->pskb = __netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL); +#endif + + if(precvbuf->pskb) + { + precvbuf->pskb->dev = padapter->pnetdev; + + tmpaddr = (SIZE_PTR)precvbuf->pskb->data; + alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); + skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); + + precvbuf->phead = precvbuf->pskb->head; + precvbuf->pdata = precvbuf->pskb->data; + precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); + precvbuf->pend = skb_end_pointer(precvbuf->pskb); + precvbuf->len = 0; + } + + if (precvbuf->pskb == NULL) { + DBG_871X("%s: alloc_skb fail! read=%d\n", __FUNCTION__, readsize); + return NULL; + } + } + + //3 3. read data from rxfifo + preadbuf = precvbuf->pdata; +// rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); + ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); + if (ret == _FAIL) { + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __FUNCTION__)); + return NULL; + } + + + //3 4. init recvbuf + precvbuf->len = readsize; + + return precvbuf; +} +#else +static struct recv_buf* sd_recv_rxfifo(PADAPTER padapter, u32 size) +{ + u32 readsize, allocsize, ret; + u8 *preadbuf; + _pkt *ppkt; + struct recv_priv *precvpriv; + struct recv_buf *precvbuf; + + + readsize = size; + + //3 1. alloc skb + // align to block size + allocsize = _RND(readsize, adapter_to_dvobj(padapter)->intf_data.block_transfer_len); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html + ppkt = __dev_alloc_skb(allocsize, GFP_KERNEL); +#else + ppkt = __netdev_alloc_skb(padapter->pnetdev, allocsize, GFP_KERNEL); +#endif + if (ppkt == NULL) { + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc_skb fail! alloc=%d read=%d\n", __FUNCTION__, allocsize, readsize)); + return NULL; + } + + //3 2. read data from rxfifo + preadbuf = skb_put(ppkt, readsize); +// rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); + ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); + if (ret == _FAIL) { + dev_kfree_skb_any(ppkt); + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __FUNCTION__)); + return NULL; + } + + //3 3. alloc recvbuf + precvpriv = &padapter->recvpriv; + precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue); + if (precvbuf == NULL) { + dev_kfree_skb_any(ppkt); + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc recvbuf FAIL!\n", __FUNCTION__)); + return NULL; + } + + //3 4. init recvbuf + precvbuf->pskb = ppkt; + + precvbuf->len = ppkt->len; + + precvbuf->phead = ppkt->head; + precvbuf->pdata = ppkt->data; + precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); + precvbuf->pend = skb_end_pointer(precvbuf->pskb); + + return precvbuf; +} +#endif + +static void sd_rxhandler(PADAPTER padapter, struct recv_buf *precvbuf) +{ + struct recv_priv *precvpriv; + _queue *ppending_queue; + + + precvpriv = &padapter->recvpriv; + ppending_queue = &precvpriv->recv_buf_pending_queue; + + //3 1. enqueue recvbuf + rtw_enqueue_recvbuf(precvbuf, ppending_queue); + + //3 2. schedule tasklet +#ifdef PLATFORM_LINUX + tasklet_schedule(&precvpriv->recv_tasklet); +#endif +} + +void sd_int_dpc(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (pHalData->sdio_hisr & SDIO_HISR_CPWM1) + { + struct reportpwrstate_parm report; + + _sdio_local_read(padapter, SDIO_REG_HCPWM1, 1, &report.state); +#ifdef CONFIG_LPS_LCLK + //88e's cpwm value only change BIT0, so driver need to add PS_STATE_S2 for LPS flow. + //modify by Thomas. 2012/4/2. + +#ifdef CONFIG_EXT_CLK //for sprd + if(report.state & BIT(4)) //indicate FW entering 32k + { + u8 chk_cnt = 0; + + do{ + if(_sdio_read8(padapter, 0x90)&BIT(0))//FW in 32k already + { + struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + + if(pwrpriv->rpwm < PS_STATE_S2) + { + //DBG_871X("disable ext clk when FW in LPS-32K already!\n"); + EnableGpio5ClockReq(padapter, _TRUE, 0); + } + + break; + } + + chk_cnt++; + + }while(chk_cnt<10); + + if(chk_cnt==10) + { + DBG_871X("polling fw in 32k already, fail!\n"); + } + + } + else //indicate fw leaving 32K +#endif //CONFIG_EXT_CLK + { + report.state |= PS_STATE_S2; + //cpwm_int_hdl(padapter, &report); + _set_workitem(&padapter->pwrctrlpriv.cpwm_event); + } +#endif + } + +#ifdef CONFIG_WOWLAN + if (pHalData->sdio_hisr & SDIO_HISR_CPWM2) { + u32 value; + value = rtw_read32(padapter, SDIO_LOCAL_BASE+SDIO_REG_HISR); + DBG_871X_LEVEL(_drv_always_, "Reset SDIO HISR(0x%08x) original:0x%08x\n", + SDIO_LOCAL_BASE+SDIO_REG_HISR, value); + value |= BIT19; + rtw_write32(padapter, SDIO_LOCAL_BASE+SDIO_REG_HISR, value); + + value = rtw_read8(padapter, SDIO_LOCAL_BASE+SDIO_REG_HIMR+2); + DBG_871X_LEVEL(_drv_always_, "Reset SDIO HIMR CPWM2(0x%08x) original:0x%02x\n", + SDIO_LOCAL_BASE+SDIO_REG_HIMR + 2, value); + } +#endif + if (pHalData->sdio_hisr & SDIO_HISR_TXERR) + { + u8 *status; + u32 addr; + + status = _rtw_malloc(4); + if (status) + { + addr = REG_TXDMA_STATUS; + HalSdioGetCmdAddr8723ASdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr); + _sd_read(&adapter_to_dvobj(padapter)->intf_data, addr, 4, status); + _sd_write(&adapter_to_dvobj(padapter)->intf_data, addr, 4, status); + DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32*)status)); + _rtw_mfree(status, 4); + } else { + DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__); + } + } + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN + + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + if (pHalData->sdio_hisr & SDIO_HISR_BCNERLY_INT) + #endif + #ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + if (pHalData->sdio_hisr & (SDIO_HISR_TXBCNOK|SDIO_HISR_TXBCNERR)) + #endif + { + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + + #if 0 //for debug + if (pHalData->sdio_hisr & SDIO_HISR_BCNERLY_INT) + DBG_8192C("%s: SDIO_HISR_BCNERLY_INT\n", __func__); + + if (pHalData->sdio_hisr & SDIO_HISR_TXBCNOK) + DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__); + + if (pHalData->sdio_hisr & SDIO_HISR_TXBCNERR) + DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__); + #endif + + + if(check_fwstate(pmlmepriv, WIFI_AP_STATE)) + { + //send_beacon(padapter); + if(pmlmepriv->update_bcn == _TRUE) + { + //tx_beacon_hdl(padapter, NULL); + set_tx_beacon_cmd(padapter); + } + } +#ifdef CONFIG_CONCURRENT_MODE + if(check_buddy_fwstate(padapter, WIFI_AP_STATE)) + { + //send_beacon(padapter); + if(padapter->pbuddy_adapter->mlmepriv.update_bcn == _TRUE) + { + //tx_beacon_hdl(padapter, NULL); + set_tx_beacon_cmd(padapter->pbuddy_adapter); + } + } +#endif + } +#endif //CONFIG_INTERRUPT_BASED_TXBCN + +#ifdef CONFIG_EXT_CLK + if (pHalData->sdio_hisr & SDIO_HISR_BCNERLY_INT) + { + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + + if(check_fwstate(pmlmepriv, _FW_LINKED) && check_fwstate(pmlmepriv, WIFI_STATION_STATE)) + { + //DBG_8192C("BCNERLY_INT for enabling ext clk\n"); + EnableGpio5ClockReq(padapter, _TRUE, 1); + } + } +#endif //CONFIG_EXT_CLK + + if (pHalData->sdio_hisr & SDIO_HISR_C2HCMD) + { + DBG_8192C("%s: C2H Command\n", __func__); + } + + if (pHalData->sdio_hisr & SDIO_HISR_RX_REQUEST) + { + struct recv_buf *precvbuf; + + //DBG_8192C("%s: RX Request, size=%d\n", __func__, phal->SdioRxFIFOSize); + pHalData->sdio_hisr ^= SDIO_HISR_RX_REQUEST; +#ifdef CONFIG_MAC_LOOPBACK_DRIVER + sd_recv_loopback(padapter, pHalData->SdioRxFIFOSize); +#else + do { + //Sometimes rx length will be zero. driver need to use cmd53 read again. + if(pHalData->SdioRxFIFOSize == 0) + { + u8 data[4]; + + _sdio_local_read(padapter, SDIO_REG_RX0_REQ_LEN, 4, data); + + pHalData->SdioRxFIFOSize = le16_to_cpu(*(u16*)data); + } + + if(pHalData->SdioRxFIFOSize) + { + precvbuf = sd_recv_rxfifo(padapter, pHalData->SdioRxFIFOSize); + + pHalData->SdioRxFIFOSize = 0; + + if (precvbuf) + sd_rxhandler(padapter, precvbuf); + else + break; + } + else + break; +#ifdef CONFIG_SDIO_DISABLE_RXFIFO_POLLING_LOOP + } while (0); +#else + } while (1); +#endif +#endif + + } + +} + +void sd_int_hdl(PADAPTER padapter) +{ + u8 data[6]; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + if ((padapter->bDriverStopped == _TRUE) || + (padapter->bSurpriseRemoved == _TRUE)) + return; + + _sdio_local_read(padapter, SDIO_REG_HISR, 6, data); + pHalData->sdio_hisr = le32_to_cpu(*(u32*)data); + pHalData->SdioRxFIFOSize = le16_to_cpu(*(u16*)&data[4]); + + if (pHalData->sdio_hisr & pHalData->sdio_himr) + { + u32 v32; + + pHalData->sdio_hisr &= pHalData->sdio_himr; + + // clear HISR + v32 = pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR; + if (v32) { + v32 = cpu_to_le32(v32); + _sdio_local_write(padapter, SDIO_REG_HISR, 4, (u8*)&v32); + } + + sd_int_dpc(padapter); + + } + else + { + RT_TRACE(_module_hci_ops_c_, _drv_err_, + ("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n", + __FUNCTION__, pHalData->sdio_hisr, pHalData->sdio_himr)); + } + +} + +// +// Description: +// Query SDIO Local register to query current the number of Free TxPacketBuffer page. +// +// Assumption: +// 1. Running at PASSIVE_LEVEL +// 2. RT_TX_SPINLOCK is NOT acquired. +// +// Created by Roger, 2011.01.28. +// +u8 HalQueryTxBufferStatus8189ESdio(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u32 NumOfFreePage; +// _irqL irql; + + + pHalData = GET_HAL_DATA(padapter); + + NumOfFreePage = SdioLocalCmd53Read4Byte(padapter, SDIO_REG_FREE_TXPG); + +// _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); + _rtw_memcpy(pHalData->SdioTxFIFOFreePage, &NumOfFreePage, 4); + RT_TRACE(_module_hci_ops_c_, _drv_notice_, + ("%s: Free page for HIQ(%#x),MIDQ(%#x),LOWQ(%#x),PUBQ(%#x)\n", + __FUNCTION__, + pHalData->SdioTxFIFOFreePage[HI_QUEUE_IDX], + pHalData->SdioTxFIFOFreePage[MID_QUEUE_IDX], + pHalData->SdioTxFIFOFreePage[LOW_QUEUE_IDX], + pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX])); +// _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); + + return _TRUE; +} + +#ifdef CONFIG_WOWLAN +u8 RecvOnePkt(PADAPTER padapter, u32 size) +{ + struct recv_buf *precvbuf; + struct dvobj_priv *psddev; + PSDIO_DATA psdio_data; + struct sdio_func *func; + + u8 res = _FALSE; + + DBG_8192C("+%s: size: %d+\n", __func__, size); + + if (padapter == NULL) { + DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__); + return _FALSE; + } + + psddev = padapter->dvobj; + psdio_data = &psddev->intf_data; + func = psdio_data->func; + + if(size) { + sdio_claim_host(func); + precvbuf = sd_recv_rxfifo(padapter, size); + + if (precvbuf) { + //printk("Completed Recv One Pkt.\n"); + sd_rxhandler(padapter, precvbuf); + res = _TRUE; + }else{ + res = _FALSE; + } + sdio_release_host(func); + } + DBG_8192C("-%s-\n", __func__); + return res; +} +#endif //CONFIG_WOWLAN |