Change SDK dir name. Use OpenOCD only.

Signed-off-by: Drasko DRASKOVIC <drasko.draskovic@gmail.com>
This commit is contained in:
Drasko DRASKOVIC 2017-05-14 18:47:13 +02:00
parent 05b731b5f3
commit eeb7f808ae
1446 changed files with 1 additions and 65 deletions

View file

@ -0,0 +1,493 @@
/******************************************************************************
*
* 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 _GSPI_INTF_C_
#include <drv_types.h>
#ifdef CONFIG_GSPI_HCI
struct dvobj_priv *gspi_dvobj_init(void)
{
// int status = _FAIL;
struct dvobj_priv *dvobj = NULL;
PGSPI_DATA pgspi_data;
_func_enter_;
dvobj = (struct dvobj_priv*)rtw_zmalloc(sizeof(*dvobj));
if (NULL == dvobj) {
goto exit;
}
pgspi_data = &dvobj->intf_data;
rtw_mutex_init(&pgspi_data->spi_mutex);
//pgspi_data->block_transfer_len = 512; //512 blocks r/w is not required for GSPI interface
//pgspi_data->tx_block_mode = 0;
//pgspi_data->rx_block_mode = 0;
// status = _SUCCESS;
#if 0
free_dvobj:
if (status != _SUCCESS && dvobj) {
rtw_mfree((u8*)dvobj, sizeof(*dvobj));
dvobj = NULL;
}
#endif
exit:
_func_exit_;
return dvobj;
}
void gspi_dvobj_deinit(struct dvobj_priv *dvobj)
{
//TODO
// struct dvobj_priv *dvobj = spi_get_drvdata(spi);
_func_enter_;
//TODO
// spi_set_drvdata(spi, NULL);
if (dvobj) {
//TODO
// gspi_deinit(dvobj);
rtw_mutex_free(&dvobj->intf_data.spi_mutex);
rtw_mfree((u8*)dvobj, sizeof(*dvobj));
}
_func_exit_;
}
s32 gspi_dvobj_xmit_mgnt(_adapter * padapter, struct xmit_frame *pmgntframe)
{
s32 ret = _SUCCESS;
struct pkt_attrib *pattrib;
struct xmit_buf *pxmitbuf;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
u8 *pframe = NULL;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("+rtw_xmit_mgnt()\n"));
pattrib = &pmgntframe->attrib;
pxmitbuf = pmgntframe->pxmitbuf;
pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
rtw_hal_update_txdesc(padapter, pmgntframe, pmgntframe->buf_addr);
pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
//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);
//RT_TRACE(_module_rtl871x_xmit_c_, _drv_always_, ("+rtw_xmit_mgnt(): type=%d\n", GetFrameSubType(pframe)));
if(GetFrameSubType(pframe)==WIFI_BEACON) //dump beacon directly
{
//When using dedicated xmit frame for issue bcn on ap mode
//free xmit frame for bcn reserved page on station mode - Alex Fang
#if USE_DEDICATED_BCN_TX
if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE) {
rtw_free_xmitframe(pxmitpriv, pmgntframe);
pxmitbuf->priv_data = NULL;
}
rtw_write_port(padapter, ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr), pxmitbuf->len, pxmitbuf->pbuf);
if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
#else
rtw_free_xmitframe(pxmitpriv, pmgntframe);
pxmitbuf->priv_data = NULL;
rtw_xmit_xmitbuf(padapter, pxmitbuf);
#endif
}
else
{
rtw_free_xmitframe(pxmitpriv, pmgntframe);
pxmitbuf->priv_data = NULL;
rtw_xmit_xmitbuf(padapter, pxmitbuf);
}
if (ret != _SUCCESS)
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("-rtw_xmit_mgnt\n"));
return ret;
}
//#include <skbuff.h>
s32 gspi_dvobj_xmit_data(_adapter *padapter, struct xmit_frame *pxmitframe)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
_irqL irql;
s32 err;
#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
#if USE_SKB_AS_XMITBUF
rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
#endif
rtw_enter_critical_bh(&pxmitpriv->lock, &irql);
#if 1 //FIX_XMITFRAME_FAULT, move from rtw_xmit().
#ifdef CONFIG_AP_MODE
if(xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe) == _TRUE)
{
rtw_exit_critical_bh(&pxmitpriv->lock, &irql);
return 1;
}
#endif
#endif
err = rtw_xmitframe_enqueue(padapter, pxmitframe);
rtw_exit_critical_bh(&pxmitpriv->lock, &irql);
if (err != _SUCCESS) {
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("rtw_xmit_data(): enqueue xmitframe fail\n"));
rtw_free_xmitframe(pxmitpriv, pxmitframe);
// Trick, make the statistics correct
pxmitpriv->tx_pkts--;
pxmitpriv->tx_drop++;
return _TRUE;
}
rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
#ifdef CONFIG_CONCURRENT_MODE
if (padapter->adapter_type > PRIMARY_ADAPTER){
padapter = padapter->pbuddy_adapter;
}
#endif
rtw_wakeup_task(&padapter->xmitThread);
return _FALSE;
}
const struct host_ctrl_intf_ops hci_ops = {
gspi_dvobj_init,
gspi_dvobj_deinit,
NULL,
NULL
};
//TODO
#if 0
unsigned int oob_irq;
static irqreturn_t spi_interrupt_thread(int irq, void *data)
{
struct dvobj_priv *dvobj;
PGSPI_DATA pgspi_data;
dvobj = (struct dvobj_priv*)data;
pgspi_data = &dvobj->intf_data;
//spi_int_hdl(padapter);
if (pgspi_data->priv_wq)
queue_delayed_work(pgspi_data->priv_wq, &pgspi_data->irq_work, 0);
return IRQ_HANDLED;
}
static u8 gspi_alloc_irq(struct dvobj_priv *dvobj)
{
PGSPI_DATA pgspi_data;
struct spi_device *spi;
int err;
pgspi_data = &dvobj->intf_data;
spi = pgspi_data->func;
err = request_irq(oob_irq, spi_interrupt_thread,
IRQF_TRIGGER_FALLING,//IRQF_TRIGGER_HIGH;//|IRQF_ONESHOT,
DRV_NAME, dvobj);
//err = request_threaded_irq(oob_irq, NULL, spi_interrupt_thread,
// IRQF_TRIGGER_FALLING,
// DRV_NAME, dvobj);
if (err < 0) {
DBG_871X("Oops: can't allocate irq %d err:%d\n", oob_irq, err);
goto exit;
}
enable_irq_wake(oob_irq);
disable_irq(oob_irq);
exit:
return err?_FAIL:_SUCCESS;
}
#endif //#if 0
//TODO
#if 0
static void spi_irq_work(void *data)
{
struct delayed_work *dwork;
PGSPI_DATA pgspi;
struct dvobj_priv *dvobj;
dwork = container_of(data, struct delayed_work, work);
pgspi = container_of(dwork, GSPI_DATA, irq_work);
dvobj = spi_get_drvdata(pgspi->func);
if (!dvobj->if1) {
DBG_871X("%s if1 == NULL !!\n", __FUNCTION__);
return;
}
spi_int_hdl(dvobj->if1);
}
#endif //#if 0
//TODO
#if 0
static int rtw_gspi_suspend(struct spi_device *spi, pm_message_t mesg)
{
struct dvobj_priv *dvobj = spi_get_drvdata(spi);
PADAPTER padapter = (_adapter *)dvobj->if1;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct net_device *pnetdev = padapter->pnetdev;
int ret = 0;
u32 start_time = rtw_get_current_time();
_func_enter_;
DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
pwrpriv->bInSuspend = _TRUE;
while (pwrpriv->bips_processing == _TRUE)
rtw_msleep_os(1);
if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved))
{
DBG_871X("%s bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", __FUNCTION__
,padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved);
goto exit;
}
rtw_cancel_all_timer(padapter);
LeaveAllPowerSaveMode(padapter);
//padapter->net_closed = _TRUE;
//s1.
if(pnetdev)
{
netif_carrier_off(pnetdev);
rtw_netif_stop_queue(pnetdev);
}
#ifdef CONFIG_WOWLAN
padapter->pwrctrlpriv.bSupportWakeOnWlan=_TRUE;
#else
//s2.
//s2-1. issue rtw_disassoc_cmd to fw
disconnect_hdl(padapter, NULL);
//rtw_disassoc_cmd(padapter);
#endif
#ifdef CONFIG_LAYER2_ROAMING_RESUME
if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) )
{
DBG_871X("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n",__FUNCTION__,
pmlmepriv->cur_network.network.Ssid.Ssid,
MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
pmlmepriv->cur_network.network.Ssid.SsidLength,
pmlmepriv->assoc_ssid.SsidLength);
pmlmepriv->to_roaming = 1;
}
#endif
//s2-2. indicate disconnect to os
rtw_indicate_disconnect(padapter);
//s2-3.
rtw_free_assoc_resources(padapter, 1);
//s2-4.
rtw_free_network_queue(padapter, _TRUE);
rtw_led_control(padapter, LED_CTL_POWER_OFF);
rtw_dev_unload(padapter);
if(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
rtw_indicate_scan_done(padapter, 1);
if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
rtw_indicate_disconnect(padapter);
// interface deinit
gspi_deinit(dvobj);
RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("%s: deinit GSPI complete!\n", __FUNCTION__));
rtw_wifi_gpio_wlan_ctrl(WLAN_PWDN_OFF);
rtw_mdelay_os(1);
exit:
DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__
, ret, rtw_get_passing_time_ms(start_time));
_func_exit_;
return ret;
}
extern int pm_netdev_open(struct net_device *pnetdev,u8 bnormal);
int rtw_resume_process(_adapter *padapter)
{
struct net_device *pnetdev;
struct pwrctrl_priv *pwrpriv;
u8 is_pwrlock_hold_by_caller;
u8 is_directly_called_by_auto_resume;
int ret = 0;
u32 start_time = rtw_get_current_time();
_func_enter_;
DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
rtw_wifi_gpio_wlan_ctrl(WLAN_PWDN_ON);
rtw_mdelay_os(1);
rtw_set_chip_endian(adapter);
if (padapter) {
pnetdev = padapter->pnetdev;
pwrpriv = &padapter->pwrctrlpriv;
} else {
ret = -1;
goto exit;
}
// interface init
if (gspi_init(adapter_to_dvobj(padapter)) != _SUCCESS)
{
ret = -1;
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("%s: initialize SDIO Failed!!\n", __FUNCTION__));
goto exit;
}
rtw_hal_disable_interrupt(padapter);
if (gspi_alloc_irq(adapter_to_dvobj(padapter)) != _SUCCESS)
{
ret = -1;
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("%s: gspi_alloc_irq Failed!!\n", __FUNCTION__));
goto exit;
}
rtw_reset_drv_sw(padapter);
pwrpriv->bkeepfwalive = _FALSE;
DBG_871X("bkeepfwalive(%x)\n",pwrpriv->bkeepfwalive);
if(pm_netdev_open(pnetdev,_TRUE) != 0) {
ret = -1;
goto exit;
}
netif_device_attach(pnetdev);
netif_carrier_on(pnetdev);
if( padapter->pid[1]!=0) {
DBG_871X("pid[1]:%d\n",padapter->pid[1]);
rtw_signal_process(padapter->pid[1], SIGUSR2);
}
#ifdef CONFIG_LAYER2_ROAMING_RESUME
rtw_roaming(padapter, NULL);
#endif
#ifdef CONFIG_RESUME_IN_WORKQUEUE
rtw_unlock_suspend();
#endif //CONFIG_RESUME_IN_WORKQUEUE
pwrpriv->bInSuspend = _FALSE;
exit:
DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__
, ret, rtw_get_passing_time_ms(start_time));
_func_exit_;
return ret;
}
static int rtw_gspi_resume(struct spi_device *spi)
{
struct dvobj_priv *dvobj = spi_get_drvdata(spi);
PADAPTER padapter = (_adapter *)dvobj->if1;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
int ret = 0;
DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
if(pwrpriv->bInternalAutoSuspend ){
ret = rtw_resume_process(padapter);
} else {
#ifdef CONFIG_RESUME_IN_WORKQUEUE
rtw_resume_in_workqueue(pwrpriv);
#elif defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
if(rtw_is_earlysuspend_registered(pwrpriv)) {
//jeff: bypass resume here, do in late_resume
pwrpriv->do_late_resume = _TRUE;
} else {
ret = rtw_resume_process(padapter);
}
#else // Normal resume process
ret = rtw_resume_process(padapter);
#endif //CONFIG_RESUME_IN_WORKQUEUE
}
DBG_871X("<======== %s return %d\n", __FUNCTION__, ret);
return ret;
}
static struct spi_driver rtw_spi_drv = {
.probe = rtw_drv_probe,
.remove = rtw_dev_remove,
.suspend = rtw_gspi_suspend,
.resume = rtw_gspi_resume,
.driver = {
.name = "wlan_spi",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
}
};
#endif //#if 0
#endif

View file

@ -0,0 +1,566 @@
/******************************************************************************
*
* 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 _GSPI_IO_C_
#include <drv_types.h>
#ifdef CONFIG_GSPI_HCI
u8 spi_read8(struct dvobj_priv *pdvobj, u32 addr, s32 *err);
u16 spi_read16(struct dvobj_priv *pdvobj, u32 addr, s32 *err);
u32 spi_read32(struct dvobj_priv *pdvobj, u32 addr, s32 *err);
s32 spi_write8(struct dvobj_priv *pdvobj, u32 addr, u8 buf, s32 *err);
s32 spi_write16(struct dvobj_priv *pdvobj, u32 addr, u16 buf, s32 *err);
s32 spi_write32(struct dvobj_priv *pdvobj, u32 addr, u32 buf, s32 *err);
static u32 rtw_spi_transfer(
struct dvobj_priv *pdvobj,
bool pool,
u8* buf,
u32 buf_len)
{
_mutex *spi_mutex;
u32 ret_value = _SUCCESS;
spi_mutex = &(pdvobj->intf_data.spi_mutex);
rtw_enter_critical_mutex(spi_mutex, NULL);
if(!WLAN_BSP_Transfer(buf, buf_len))
ret_value = _FAIL;
rtw_exit_critical_mutex(spi_mutex, NULL);
return ret_value;
}
static int addr_convert(u32 addr)
{
u32 domain_id = 0 ;
u32 temp_addr = addr&0xffff0000;
if (temp_addr == 0 ) {
domain_id = WLAN_IOREG_DOMAIN;
return domain_id;
}
switch (temp_addr) {
case WLAN_LOCAL_OFFSET:
domain_id = SPI_LOCAL_DOMAIN;
break;
case WLAN_IOREG_OFFSET:
domain_id = WLAN_IOREG_DOMAIN;
break;
case FW_FIFO_OFFSET:
domain_id = FW_FIFO_DOMAIN;
break;
case TX_HIQ_OFFSET:
domain_id = TX_HIQ_DOMAIN;
break;
case TX_MIQ_OFFSET:
domain_id = TX_MIQ_DOMAIN;
break;
case TX_LOQ_OFFSET:
domain_id = TX_LOQ_DOMAIN;
break;
case RX_RXOFF_OFFSET:
domain_id = RX_RXFIFO_DOMAIN;
break;
default:
break;
}
return domain_id;
}
/*
* Description:
* Translate sdio fifo address to Domain ID in each WLAN FIFO
*/
static u32 hwaddr2txfifo(u32 addr)
{
u32 fifo_domain_id;
switch (addr)
{
case WLAN_TX_HIQ_DEVICE_ID:
fifo_domain_id = TX_HIQ_DOMAIN;
break;
case WLAN_TX_MIQ_DEVICE_ID:
fifo_domain_id = TX_MIQ_DOMAIN;
break;
case WLAN_TX_LOQ_DEVICE_ID:
fifo_domain_id = TX_LOQ_DOMAIN;
break;
default:
fifo_domain_id = TX_LOQ_DOMAIN;
break;
}
return fifo_domain_id;
}
static u32 buf_endian_reverse(u32 src)
{
return (((src&0x000000ff)<<24)|((src&0x0000ff00)<<8)|
((src&0x00ff0000)>>8)|((src&0xff000000)>>24));
}
//
// 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.
//
#ifdef CONFIG_RTL8188F
u8 spi_query_status_info(struct dvobj_priv *pdvobj)
{
pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX] = spi_read8(pdvobj, LOCAL_REG_FREE_TXPG, NULL);
pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX] =spi_read8(pdvobj, LOCAL_REG_FREE_TXPG+2, NULL);
pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX] = spi_read8(pdvobj, LOCAL_REG_FREE_TXPG+4, NULL);
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] = spi_read8(pdvobj, LOCAL_REG_FREE_TXPG+6, NULL);
RT_TRACE(_module_hci_ops_c_, _drv_notice_,
("%s: Free page for HIQ(%x),MIDQ(%x),LOWQ(%x),PUBQ(%x)\n",
__FUNCTION__,
pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
//_exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql);
return _TRUE;
}
#else
u8 spi_query_status_info(struct dvobj_priv *pdvobj)
{
u32 NumOfFreePage;
NumOfFreePage = spi_read32(pdvobj, LOCAL_REG_FREE_TXPG, NULL);
// _enter_critical_bh(&pdvobj->SdioTxFIFOFreePageLock, &irql);
rtw_memcpy(pdvobj->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__,
pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
// _exit_critical_bh(&pdvobj->SdioTxFIFOFreePageLock, &irql);
return _TRUE;
}
#endif
static void spi_get_status_info(struct dvobj_priv *pdvobj, unsigned char *status)
{
#ifdef CONFIG_MEMORY_ACCESS_ALIGNED
u32 local_status[2];
u8 *pstatus = (u8*)(&local_status[0]);
memcpy(pstatus, status, GSPI_STATUS_LEN);
#else
u8 *pstatus = status;
#endif
#ifdef CONFIG_RTL8188F
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] = GET_STATUS_PUB_PAGE_NUM(pstatus)*2;
#else
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] = GET_STATUS_PUB_PAGE_NUM(pstatus);
#endif
pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX] = GET_STATUS_HI_PAGE_NUM(pstatus);
pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX] = GET_STATUS_MID_PAGE_NUM(pstatus);
pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX] = GET_STATUS_LOW_PAGE_NUM(pstatus);
RT_TRACE(_module_hci_ops_c_, _drv_dump_,
("%s: Free page for HIQ(%x),MIDQ(%x),LOWQ(%x),PUBQ(%x)\n",
__FUNCTION__,
pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
}
static int spi_read_write_reg(struct dvobj_priv *pdvobj, int write_flag, u32 addr, char * buf, int len, u32 eddien)
{
int fun = 1, domain_id = 0x0; //LOCAL
unsigned int cmd = 0 ;
int byte_en = 0 ;//,i = 0 ;
int ret = 1;
unsigned char status[8] = {0};
unsigned int data_tmp = 0;
u32 force_bigendian = eddien;
u32 spi_buf[4] = {0};
bool polled = TRUE;
if (len!=1 && len!=2 && len != 4) {
return -1;
}
domain_id = addr_convert(addr);
addr &= 0x7fff;
len &= 0xff;
if (write_flag) //write register
{
int remainder = addr % 4;
u32 val32 = *(u32 *)buf;
switch(len) {
case 1:
byte_en = (0x1 << remainder);
data_tmp = (val32& 0xff)<< (remainder*8);
break;
case 2:
byte_en = (0x3 << remainder);
data_tmp = (val32 & 0xffff)<< (remainder*8);
break;
case 4:
byte_en = 0xf;
data_tmp = val32 & 0xffffffff;
break;
default:
byte_en = 0xf;
data_tmp = val32 & 0xffffffff;
break;
}
}
else //read register
{
switch(len) {
case 1:
byte_en = 0x1;
break;
case 2:
byte_en = 0x3;
break;
case 4:
byte_en = 0xf;
break;
default:
byte_en = 0xf;
break;
}
if(domain_id == SPI_LOCAL_DOMAIN)
byte_en = 0;
}
//addr = 0xF0 4byte: 0x2800f00f
REG_LEN_FORMAT(&cmd, byte_en);
REG_ADDR_FORMAT(&cmd, (addr&0xfffffffc));
REG_DOMAIN_ID_FORMAT(&cmd, domain_id);
REG_FUN_FORMAT(&cmd, fun);
REG_RW_FORMAT(&cmd, write_flag);
if (force_bigendian) {
cmd = buf_endian_reverse(cmd);
}
if (!write_flag && (domain_id!= RX_RXFIFO_DOMAIN)) {
u32 read_data = 0;
rtw_memset(spi_buf, 0x00, sizeof(spi_buf));
spi_buf[0] = cmd;
spi_buf[1] = 0;
spi_buf[2] = 0;
spi_buf[3] = 0;
rtw_spi_transfer(pdvobj, polled, (u8*)spi_buf, sizeof(spi_buf));
rtw_memcpy(status, (u8 *) &spi_buf[1], sizeof(status));
read_data = EF4Byte(spi_buf[3]);
//add for 8810
#ifdef CONFIG_BIG_ENDIAN
if (!force_bigendian)
read_data = buf_endian_reverse(read_data);
#else
if (force_bigendian)
read_data = buf_endian_reverse(read_data);
#endif
*(u32*)buf = read_data;
} else if (write_flag ) {
#ifdef CONFIG_BIG_ENDIAN
if (!force_bigendian)
data_tmp = buf_endian_reverse(data_tmp);
#else
if (force_bigendian)
data_tmp = buf_endian_reverse(data_tmp);
#endif
spi_buf[0] = cmd;
spi_buf[1] = data_tmp;
spi_buf[2] = 0;
spi_buf[3] = 0;
rtw_spi_transfer(pdvobj, polled, (u8*)spi_buf, sizeof(spi_buf));
rtw_memcpy(status, (u8 *) &spi_buf[2], sizeof(status));
}
spi_get_status_info(pdvobj, (unsigned char*)status);
return ret;
}
static int spi_io_priv(struct dvobj_priv *pdvobj)
{
//struct dvobj_priv *pdvobj = &Adapter->dvobjpriv;
return _SUCCESS;
}
static int spi_write8_endian(struct dvobj_priv *pdvobj, u32 addr, u32 buf, u32 big)
{
return spi_read_write_reg(pdvobj,1,addr,(char *)&buf,1, big);
}
u8 spi_read8(struct dvobj_priv *pdvobj, u32 addr, s32 *err)
{
u32 ret = 0;
int val32 = 0 , remainder = 0 ;
s32 _err = 0;
_err = spi_read_write_reg(pdvobj,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
remainder = addr % 4;
val32 = ret;
val32 = (val32& (0xff<< (remainder<<3)))>>(remainder<<3);
if (err)
*err = _err;
return (u8)val32;
}
u16 spi_read16(struct dvobj_priv *pdvobj, u32 addr, s32 *err)
{
u32 ret = 0;
int val32 = 0 , remainder = 0 ;
s32 _err = 0;
_err = spi_read_write_reg(pdvobj,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
remainder = addr % 4;
val32 = ret;
val32 = (val32& (0xffff<< (remainder<<3)))>>(remainder<<3);
if (err)
*err = _err;
return (u16)val32;
}
u32 spi_read32(struct dvobj_priv *pdvobj, u32 addr, s32 *err)
{
u32 ret = 0;
s32 _err = 0;
_err = spi_read_write_reg(pdvobj,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
if (err)
*err = _err;
return ret;
}
s32 spi_write8(struct dvobj_priv *pdvobj, u32 addr, u8 buf, s32 *err)
{
int ret = 0;
ret = spi_read_write_reg(pdvobj,1,addr,(char *)&buf,1,0);
if (err)
*err = ret;
return ret;
}
s32 spi_write16(struct dvobj_priv *pdvobj, u32 addr, u16 buf, s32 *err)
{
int ret = 0;
ret = spi_read_write_reg(pdvobj,1,addr,(char *)&buf,2,0);
if (err)
*err = ret;
return ret;
}
s32 spi_write32(struct dvobj_priv *pdvobj, u32 addr, u32 buf, s32 *err)
{
int ret = 0;
ret = spi_read_write_reg(pdvobj, 1,addr,(char *)&buf,4,0);
if (err)
*err = ret;
return ret;
}
static int spi_read_rx_fifo(struct dvobj_priv *pdvobj, u32 addr, u8 *buf, u32 len, struct fifo_more_data *pmore_data)
{
int fun = 1, domain_id = RX_RXFIFO_DOMAIN;
unsigned int cmd = 0;
unsigned char *status = buf + len;
u8 *spi_buf = (u8 *) (buf - GSPI_CMD_LEN);
int spi_buf_len = 0;
bool polled = TRUE;
bool use_alloc = FALSE;
u32 max_skb_len = 0;
#ifndef CONFIG_DONT_CARE_TP
max_skb_len = MAX_SKB_BUF_SIZE;
#else
max_skb_len = MAX_RX_SKB_BUF_SIZE;
#endif
if(((GSPI_CMD_LEN + len + GSPI_STATUS_LEN) > max_skb_len) || (!buf)) {
#if !defined(CONFIG_MP_INCLUDED) || !defined(CONFIG_MP_IWPRIV_SUPPORT) // Cloud 2013/09/06
DBG_871X("data len=%d, MAX_SKB_BUF_SIZE(%d) is not enough, change to dynamic alloc\n", len, max_skb_len);
#endif
use_alloc = TRUE;
spi_buf_len = GSPI_CMD_LEN + len + GSPI_STATUS_LEN;
spi_buf = rtw_malloc(spi_buf_len);
if(spi_buf == NULL) {
DBG_871X("Failed to alloc %d bytes\n", len);
return _FAIL;
}
else {
buf = spi_buf + GSPI_CMD_LEN;
status = spi_buf + GSPI_CMD_LEN + len;
}
}
FIFO_LEN_FORMAT(&cmd, len); //TX Agg len
FIFO_DOMAIN_ID_FORMAT(&cmd, domain_id);
FIFO_FUN_FORMAT(&cmd, fun);
FIFO_RW_FORMAT(&cmd, 0); //read
rtw_memset(status, 0x00, GSPI_STATUS_LEN);
rtw_memset(buf, 0x0, len);
#ifdef CONFIG_MEMORY_ACCESS_ALIGNED
memcpy(spi_buf, (u8 *)&cmd, sizeof(int));
#else
*((u32 *) spi_buf) = cmd;
#endif
rtw_spi_transfer(pdvobj, polled, (u8 *) spi_buf, GSPI_CMD_LEN + len + GSPI_STATUS_LEN);
spi_get_status_info(pdvobj, status);
pmore_data->more_data = GET_STATUS_HISR_LOW8BIT(status) & BIT(0);
pmore_data->len = GET_STATUS_RX_LENGTH(status);
if(use_alloc) {
//Drop the data
rtw_mfree(spi_buf, spi_buf_len);
return _FAIL;
}
return _SUCCESS;
}
static int spi_write_tx_fifo(struct dvobj_priv *pdvobj, u32 addr, u8 *buf, u32 len)
{
int fun = 1; //TX_HIQ_FIFO
unsigned int cmd = 0;
unsigned char *status = buf + len;
u8 *spi_buf = (u8 *) (buf - GSPI_CMD_LEN);
u32 page_num = 0;
u32 wait_num = 100;
bool polled = TRUE;
u32 fifo = 0;
_func_enter_;
fifo = hwaddr2txfifo(addr);
spi_query_status_info(pdvobj);
if (fifo == TX_HIQ_DOMAIN)
page_num = pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX];
else if (fifo == TX_LOQ_DOMAIN)
page_num = pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX];
else
page_num = pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX];
while (page_num + pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] < 15) {
DBG_871X("Oops: spi_write_tx_fifo(): page_num is %d, padapter->pub_page is %d, wait_num is %d",
page_num, pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX], wait_num);
rtw_msleep_os(1);
//rtw_udelay_os(20);
spi_read32(pdvobj, 0x608, NULL);
if (fifo == TX_HIQ_DOMAIN)
page_num = pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX];
else if (fifo == TX_LOQ_DOMAIN)
page_num = pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX];
else
page_num = pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX];
if (wait_num <= 2) {
DBG_871X("%s(): wait_num is <= 2 drop", __FUNCTION__);
return _FAIL;
}
wait_num --;
}
FIFO_LEN_FORMAT(&cmd, len); //TX Agg len
FIFO_DOMAIN_ID_FORMAT(&cmd, fifo);
FIFO_FUN_FORMAT(&cmd, fun);
FIFO_RW_FORMAT(&cmd, (unsigned int) 1); //write
//DBG_871X("%s(): len = %d\n", __FUNCTION__, len);
//RT_PRINT_DATA(_module_hal_xmit_c_, _drv_always_, "Tx:\n", buf, GSPI_CMD_LEN + len);
rtw_memset(status, 0x00, GSPI_STATUS_LEN);
#ifdef CONFIG_MEMORY_ACCESS_ALIGNED
memcpy(spi_buf, (u8 *)&cmd, sizeof(int));
#else
*((u32 *) spi_buf) = cmd;
#endif
rtw_spi_transfer(pdvobj, polled, (u8 *) spi_buf, GSPI_CMD_LEN + len + GSPI_STATUS_LEN);
spi_get_status_info(pdvobj, status);
_func_exit_;
return _SUCCESS;
}
void spi_set_intf_ops(struct _io_ops *pops)
{
pops->init_io_priv = &spi_io_priv;
pops->write8_endian = &spi_write8_endian;
pops->_read8 = &spi_read8;
pops->_read16 = &spi_read16;
pops->_read32 = &spi_read32;
pops->_write8 = &spi_write8;
pops->_write16 = &spi_write16;
pops->_write32 = &spi_write32;
pops->read_rx_fifo = &spi_read_rx_fifo;
pops->write_tx_fifo = &spi_write_tx_fifo;
}
#endif

View file

@ -0,0 +1,236 @@
/******************************************************************************
*
* 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 _GSPI_ISR_C_
#include <drv_types.h>
#ifdef CONFIG_GSPI_HCI
extern struct recv_buf* rtw_recv_rxfifo(_adapter * padapter, u32 size, struct fifo_more_data* more_data);
u8 spi_read8(struct dvobj_priv *pdvobj, u32 addr, s32 *err);
u16 spi_read16(struct dvobj_priv *pdvobj, u32 addr, s32 *err);
u32 spi_read32(struct dvobj_priv *pdvobj, u32 addr, s32 *err);
s32 spi_write8(struct dvobj_priv *pdvobj, u32 addr, u8 buf, s32 *err);
s32 spi_write16(struct dvobj_priv *pdvobj, u32 addr, u16 buf, s32 *err);
s32 spi_write32(struct dvobj_priv *pdvobj, u32 addr, u32 buf, s32 *err);
void spi_int_dpc(PADAPTER padapter, u32 sdio_hisr)
{
struct dvobj_priv *pdvobj = padapter->dvobj;
#ifdef CONFIG_LPS_LCLK
if (sdio_hisr & HCI_HISR_CPWM1)
{
struct reportpwrstate_parm report;
report.state = spi_read8(pdvobj, LOCAL_REG_HCPWM1, NULL);
if(report.state == 0xEA)
report.state = PS_STATE_S0;
else
report.state = PS_STATE_S2;
cpwm_int_hdl(padapter, &report);
}
#endif
if (sdio_hisr & HCI_HISR_TXERR)
{
u32 status;
status = rtw_read32(padapter, REG_TXDMA_STATUS);
rtw_write32(padapter, REG_TXDMA_STATUS, status);
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, status));
}
#ifdef CONFIG_INTERRUPT_BASED_TXBCN
#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT
if (sdio_hisr & HCI_HISR_BCNERLY_INT)
#endif
#ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR
if (sdio_hisr & (HCI_HISR_TXBCNOK|HCI_HISR_TXBCNERR))
#endif
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
#if 0 //for debug
if (sdio_hisr & SDIO_HISR_BCNERLY_INT)
DBG_8192C("%s: SDIO_HISR_BCNERLY_INT\n", __func__);
if (sdio_hisr & SDIO_HISR_TXBCNOK)
DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
if (sdio_hisr & SDIO_HISR_TXBCNERR) {
u1Byte v422, v550, v419;
v422 = rtw_read8(padapter, 0x422);
v419 = rtw_read8(padapter, 0x419);
v550 = rtw_read8(padapter, 0x550);
DBG_8192C("%s: SDIO_HISR_TXBCNERR 422=%02x, 419=%02x, 550=%02x\n", __func__, v422, v419, v550);
}
#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);
}
}
#if 0//def 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
if (sdio_hisr & HCI_HISR_C2HCMD)
{
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s: C2H Command\n", __func__));
//TODO
// rtw_c2h_wk_cmd(padapter);
}
if (sdio_hisr & HCI_HISR_RX_REQUEST)// || sdio_hisr & SPI_HISR_RXFOVW)
{
struct recv_buf *precvbuf;
struct fifo_more_data more_data = {0};
//RT_TRACE(_module_hci_ops_c_,_drv_info_, ("%s: RX Request, size=%d\n", __func__, pdvobj->SdioRxFIFOSize));
sdio_hisr ^= HCI_HISR_RX_REQUEST;
do {
more_data.more_data = 0;
more_data.len = 0;
if (pdvobj->SdioRxFIFOSize == 0)
{
u16 val = 0;
s32 ret;
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s, %d, read RXFIFOsize again size=%d\n", __FUNCTION__, __LINE__, pdvobj->SdioRxFIFOSize));
val = spi_read16(pdvobj, LOCAL_REG_RX0_REQ_LEN_1_BYTE, &ret);
if (!ret) {
pdvobj->SdioRxFIFOSize = val;
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s: RX_REQUEST, read RXFIFOsize again size=%d\n", __func__, pdvobj->SdioRxFIFOSize));
} else {
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s: RX_REQUEST, read RXFIFOsize ERROR!!\n", __func__));
}
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s, %d, read RXFIFOsize again size=%d\n", __FUNCTION__, __LINE__, pdvobj->SdioRxFIFOSize));
}
if (pdvobj->SdioRxFIFOSize != 0)
{
#ifdef RTL8723A_SDIO_LOOPBACK
sd_recv_loopback(padapter, pdvobj->SdioRxFIFOSize);
#else
if (sdio_hisr & HCI_HISR_RXFOVW)
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s RXFOVW RX\n", __func__));
precvbuf = rtw_recv_rxfifo(padapter, pdvobj->SdioRxFIFOSize, &more_data);
if (precvbuf)
rtw_rxhandler(padapter, precvbuf);
if (more_data.more_data) {
pdvobj->SdioRxFIFOSize = more_data.len;
} else {
pdvobj->SdioRxFIFOSize = 0;
}
#endif
//If Rx_request ISR is set, execute receive tasklet (sdio_hisr & SPI_HISR_RX_REQUEST)
#if defined(CONFIG_ISR_THREAD_MODE_INTERRUPT) && defined(CONFIG_RECV_TASKLET_THREAD)
rtw_wakeup_task(&padapter->recvtasklet_thread);
#endif
}
#ifdef CONFIG_INTERRUPT_BASED_TXBCN
{
//Prevent BCN update not realtime in ap mode - Alex Fang
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
if((check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) && (pmlmepriv->update_bcn == _TRUE))
break;
}
#endif
} while (more_data.more_data);
#ifdef PLATFORM_LINUX
#ifdef CONFIG_GSPI_HCI
tasklet_schedule(&padapter->recvpriv.recv_tasklet);
#endif
#endif
}
}
void spi_int_hdl(PADAPTER padapter)
{
struct dvobj_priv *pdvobj = padapter->dvobj;
u32 sdio_hisr = 0;
s32 ret;
if ((padapter->bDriverStopped == _TRUE) ||
(padapter->bSurpriseRemoved == _TRUE))
return;
sdio_hisr = spi_read32(pdvobj, LOCAL_REG_HISR, &ret);
if (!ret) {
RT_TRACE(_module_hci_ops_c_, _drv_err_, ("%s: read SDIO_REG_HISR FAIL!!\n", __func__));
return;
}
pdvobj->SdioRxFIFOSize = spi_read16(pdvobj, LOCAL_REG_RX0_REQ_LEN_1_BYTE, &ret);
if (!ret) {
RT_TRACE(_module_hci_ops_c_, _drv_err_, ("%s: read SPI_REG_RX0_REQ_LEN FAIL!!\n", __func__));
return;
}
if (sdio_hisr & pdvobj->sdio_himr)
{
u32 v32;
sdio_hisr &= pdvobj->sdio_himr;
// clear HISR
v32 = sdio_hisr & MASK_SPI_HISR_CLEAR;
if (v32) {
spi_write32(pdvobj, LOCAL_REG_HISR, v32, &ret);
}
spi_int_dpc(padapter, sdio_hisr);
} else {
RT_TRACE(_module_hci_ops_c_, _drv_err_,
("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
__FUNCTION__, sdio_hisr, pdvobj->sdio_himr));
if(sdio_hisr)
spi_write32(pdvobj, LOCAL_REG_HISR, sdio_hisr, &ret);
}
}
#endif

View file

@ -0,0 +1,257 @@
/******************************************************************************
*
* 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
*
*******************************************************************************/
#ifndef __GSPI_SPEC_H__
#define __GSPI_SPEC_H__
#define SPI_LOCAL_DOMAIN 0x0
#define WLAN_IOREG_DOMAIN 0x8
#define FW_FIFO_DOMAIN 0x4
#define TX_HIQ_DOMAIN 0xc
#define TX_MIQ_DOMAIN 0xd
#define TX_LOQ_DOMAIN 0xe
#define RX_RXFIFO_DOMAIN 0x1f
//IO Bus domain address mapping
#define DEFUALT_OFFSET 0x0
#define LOCAL_OFFSET 0x10250000
#define SPI_LOCAL_OFFSET 0x10250000
#define WLAN_IOREG_OFFSET 0x10260000
#define FW_FIFO_OFFSET 0x10270000
#define TX_HIQ_OFFSET 0x10310000
#define TX_MIQ_OFFSET 0x1032000
#define TX_LOQ_OFFSET 0x10330000
#define RX_RXOFF_OFFSET 0x10340000
#define WLAN_TX_HIQ_DEVICE_ID 4 // 0b[16], 100b[15:13]
#define WLAN_TX_MIQ_DEVICE_ID 5 // 0b[16], 101b[15:13]
#define WLAN_TX_LOQ_DEVICE_ID 6 // 0b[16], 110b[15:13]
#define WLAN_TX_EXQ_DEVICE_ID 3 // 0b[16], 011b[15:13]
#define WLAN_RX0FF_DEVICE_ID 7 // 0b[16], 111b[15:13]
#define WLAN_IOREG_DEVICE_ID 8 // 1b[16]
//SPI Tx Free Page Index
#define HI_QUEUE_IDX 0
#define MID_QUEUE_IDX 1
#define LOW_QUEUE_IDX 2
#define PUBLIC_QUEUE_IDX 3
#define MAX_TX_QUEUE 3 // HIQ, MIQ and LOQ
#define MAX_RX_QUEUE 1
//SPI Local registers
#ifdef CONFIG_RTL8188F
#define SPI_REG_TX_CTRL 0x0000 // SPI Tx Control
#define SPI_REG_STATUS_RECOVERY 0x0004
#define SPI_REG_INT_TIMEOUT 0x0006
#define SPI_REG_HIMR 0x0014 // SPI Host Interrupt Mask
#define SPI_REG_HISR 0x0018 // SPI Host Interrupt Service Routine
#define SPI_REG_RX0_REQ_LEN 0x001C // RXDMA Request Length
#define SPI_REG_FREE_TXPG 0x0020 // Free Tx Buffer Page
#define SPI_REG_HTSFR_INFO 0x0030 // HTSF Informaion
#define SPI_REG_HCPWM1 0x0038 // HCI Current Power Mode 1
#define SPI_REG_HCPWM2 0x003A // HCI Current Power Mode 2
#define SPI_REG_HRPWM1 0x0080 // HCI Request Power Mode 1 need check for 8188f???
#define SPI_REG_HPS_CLKR 0x0084 // HCI Power Save Clock
#define SPI_REG_HSUS_CTRL 0x0086 // SPI HCI Suspend Control
#else
#define SPI_REG_TX_CTRL 0x0000 // SPI Tx Control
#define SPI_REG_STATUS_RECOVERY 0x0004
#define SPI_REG_INT_TIMEOUT 0x0006
#define SPI_REG_HIMR 0x0014 // SPI Host Interrupt Mask
#define SPI_REG_HISR 0x0018 // SPI Host Interrupt Service Routine
#define SPI_REG_RX0_REQ_LEN 0x001C // RXDMA Request Length
#define SPI_REG_FREE_TXPG 0x0020 // Free Tx Buffer Page
#define SPI_REG_HCPWM1 0x0024 // HCI Current Power Mode 1
#define SPI_REG_HCPWM2 0x0026 // HCI Current Power Mode 2
#define SPI_REG_HTSFR_INFO 0x0030 // HTSF Informaion
#define SPI_REG_HRPWM1 0x0080 // HCI Request Power Mode 1
#define SPI_REG_HRPWM2 0x0082 // HCI Request Power Mode 2
#define SPI_REG_HPS_CLKR 0x0084 // HCI Power Save Clock
#define SPI_REG_HSUS_CTRL 0x0086 // SPI HCI Suspend Control
#define SPI_REG_HIMR_ON 0x0090 //SPI Host Extension Interrupt Mask Always
#define SPI_REG_HISR_ON 0x0091 //SPI Host Extension Interrupt Status Always
#define SPI_REG_CFG 0x00F0 //SPI Configuration Register
#endif
#define LOCAL_REG_TX_CTRL (SPI_REG_TX_CTRL |SPI_LOCAL_OFFSET)
#define LOCAL_REG_STATUS_RECOVERY (SPI_REG_STATUS_RECOVERY |SPI_LOCAL_OFFSET)
#define LOCAL_REG_INT_TIMEOUT (SPI_REG_INT_TIMEOUT |SPI_LOCAL_OFFSET)
#define LOCAL_REG_HIMR (SPI_REG_HIMR |SPI_LOCAL_OFFSET)
#define LOCAL_REG_HISR (SPI_REG_HISR |SPI_LOCAL_OFFSET)
#define LOCAL_REG_RX0_REQ_LEN_1_BYTE (SPI_REG_RX0_REQ_LEN |SPI_LOCAL_OFFSET)
#define LOCAL_REG_FREE_TXPG (SPI_REG_FREE_TXPG |SPI_LOCAL_OFFSET)
#define LOCAL_REG_HRPWM1 (SPI_REG_HRPWM1 |SPI_LOCAL_OFFSET)
#define LOCAL_REG_HCPWM1 (SPI_REG_HCPWM1 |SPI_LOCAL_OFFSET)
#define LOCAL_REG_SUSPEND_NORMAL (SPI_REG_HSUS_CTRL|SPI_LOCAL_OFFSET)
#define HCI_HIMR_DISABLED 0
//SPI HIMR MASK diff with SDIO
#ifdef CONFIG_RTL8188F
#define HCI_HISR_RX_REQUEST BIT(0)
#define HCI_HISR_AVAL BIT(1)
#define HCI_HISR_TXERR BIT(2)
#define HCI_HISR_RXERR BIT(3)
#define HCI_HISR_TXFOVW BIT(4)
#define HCI_HISR_RXFOVW BIT(5)
#define HCI_HISR_TXBCNOK BIT(6)
#define HCI_HISR_TXBCNERR BIT(7)
#define HCI_HISR_BCNERLY_INT BIT(16)
#define HCI_HISR_C2HCMD BIT(17)
#define HCI_HISR_CPWM1 BIT(18)
#define HCI_HISR_CPWM2 BIT(19)
#define HCI_HISR_HSISR_IND BIT(20)
#define HCI_HISR_GTINT3_IND BIT(21)
#define HCI_HISR_GTINT4_IND BIT(22)
#define HCI_HISR_PSTIMEOUT BIT(23)
#define HCI_HISR_OCPINT BIT(24)
#define HCI_HISR_ATIMEND BIT(25)
#define HCI_HISR_ATIMEND_E BIT(26)
#define HCI_HISR_CTWEND BIT(27)
#define HCI_HISR_TSF_BIT32_TOGGLE BIT(29)
#define HCI_HISR_PSTIMEOUT_E BIT(30)
//SPI HIMR MASK diff with SDIO
#define HCI_HIMR_RX_REQUEST BIT(0)
#define HCI_HIMR_AVAL BIT(1)
#define HCI_HIMR_TXERR BIT(2)
#define HCI_HIMR_RXERR BIT(3)
#define HCI_HIMR_TXFOVW BIT(4)
#define HCI_HIMR_RXFOVW BIT(5)
#define HCI_HIMR_TXBCNOK BIT(6)
#define HCI_HIMR_TXBCNERR BIT(7)
#define HCI_HIMR_BCNERLY_INT BIT(16)
#define HCI_HIMR_C2HCMD BIT(17)
#define HCI_HIMR_CPWM1 BIT(18)
#define HCI_HIMR_CPWM2 BIT(19)
#define HCI_HIMR_HSISR_IND BIT(20)
#define HCI_HIMR_GTINT3_IND BIT(21)
#define HCI_HIMR_GTINT4_IND BIT(22)
#define HCI_HIMR_PSTIMEOUT BIT(23)
#define HCI_HIMR_OCPINT BIT(24)
#define HCI_HIMR_ATIMEND BIT(25)
#define HCI_HIMR_ATIMEND_E BIT(26)
#define HCI_HIMR_CTWEND BIT(27)
#define HCI_HIMR_TSF_BIT32_TOGGLE BIT(29)
#define HCI_HIMR_PSTIMEOUT_E BIT(30)
#else
#define HCI_HISR_RX_REQUEST BIT(0)
#define HCI_HISR_AVAL BIT(1)
#define HCI_HISR_TXERR BIT(2)
#define HCI_HISR_RXERR BIT(3)
#define HCI_HISR_TXFOVW BIT(4)
#define HCI_HISR_RXFOVW BIT(5)
#define HCI_HISR_TXBCNOK BIT(6)
#define HCI_HISR_TXBCNERR BIT(7)
#define HCI_HISR_BCNERLY_INT BIT(16)
#define HCI_HISR_ATIMEND BIT(17)
#define HCI_HISR_ATIMEND_E BIT(18)
#define HCI_HISR_CTWEND BIT(19)
#define HCI_HISR_C2HCMD BIT(20)
#define HCI_HISR_CPWM1 BIT(21)
#define HCI_HISR_CPWM2 BIT(22)
#define HCI_HISR_HSISR_IND BIT(23)
#define HCI_HISR_GTINT3_IND BIT(24)
#define HCI_HISR_GTINT4_IND BIT(25)
#define HCI_HISR_PSTIMEOUT BIT(26)
#define HCI_HISR_OCPINT BIT(27)
#define HCI_HISR_TSF_BIT32_TOGGLE BIT(29)
//SPI HIMR MASK diff with SDIO
#define HCI_HIMR_RX_REQUEST BIT(0)
#define HCI_HIMR_AVAL BIT(1)
#define HCI_HIMR_TXERR BIT(2)
#define HCI_HIMR_RXERR BIT(3)
#define HCI_HIMR_TXFOVW BIT(4)
#define HCI_HIMR_RXFOVW BIT(5)
#define HCI_HIMR_TXBCNOK BIT(6)
#define HCI_HIMR_TXBCNERR BIT(7)
#define HCI_HIMR_BCNERLY_INT BIT(16)
#define HCI_HIMR_ATIMEND BIT(17)
#define HCI_HIMR_ATIMEND_E BIT(18)
#define HCI_HIMR_CTWEND BIT(19)
#define HCI_HIMR_C2HCMD BIT(20)
#define HCI_HIMR_CPWM1 BIT(21)
#define HCI_HIMR_CPWM2 BIT(22)
#define HCI_HIMR_HSISR_IND BIT(23)
#define HCI_HIMR_GTINT3_IND BIT(24)
#define HCI_HIMR_GTINT4_IND BIT(25)
#define HCI_HIMR_PSTIMEOUT BIT(26)
#define HCI_HIMR_OCPINT BIT(27)
#define HCI_HIMR_TSF_BIT32_TOGGLE BIT(29)
#endif
#define MASK_SPI_HISR_CLEAR (HCI_HIMR_TXERR |\
HCI_HIMR_RXERR |\
HCI_HIMR_TXFOVW |\
HCI_HIMR_RXFOVW |\
HCI_HIMR_TXBCNOK |\
HCI_HIMR_TXBCNERR |\
HCI_HIMR_C2HCMD |\
HCI_HIMR_CPWM1 |\
HCI_HIMR_CPWM2 |\
HCI_HIMR_HSISR_IND |\
HCI_HIMR_GTINT3_IND |\
HCI_HIMR_GTINT4_IND |\
HCI_HIMR_PSTIMEOUT |\
HCI_HIMR_OCPINT)
#define REG_LEN_FORMAT(pcmd, x) SET_BITS_TO_LE_4BYTE(pcmd, 0, 8, x)//(x<<(unsigned int)24)
#define REG_ADDR_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 8, 16, x)//(x<<(unsigned int)16)
#define REG_DOMAIN_ID_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 24, 5, x)//(x<<(unsigned int)0)
#define REG_FUN_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 29, 2, x)//(x<<(unsigned int)5)
#define REG_RW_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 31, 1, x)//(x<<(unsigned int)7)
#define FIFO_LEN_FORMAT(pcmd, x) SET_BITS_TO_LE_4BYTE(pcmd, 0, 16, x)//(x<<(unsigned int)24)
//#define FIFO_ADDR_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 8, 16, x)//(x<<(unsigned int)16)
#define FIFO_DOMAIN_ID_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 24, 5, x)//(x<<(unsigned int)0)
#define FIFO_FUN_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 29, 2, x)//(x<<(unsigned int)5)
#define FIFO_RW_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 31, 1, x)//(x<<(unsigned int)7)
//get status dword0
#define GET_STATUS_PUB_PAGE_NUM(status) LE_BITS_TO_4BYTE(status, 24, 8)
#define GET_STATUS_HI_PAGE_NUM(status) LE_BITS_TO_4BYTE(status, 18, 6)
#define GET_STATUS_MID_PAGE_NUM(status) LE_BITS_TO_4BYTE(status, 12, 6)
#define GET_STATUS_LOW_PAGE_NUM(status) LE_BITS_TO_4BYTE(status, 6, 6)
#define GET_STATUS_HISR_HI6BIT(status) LE_BITS_TO_4BYTE(status, 0, 6)
//get status dword1
#define GET_STATUS_HISR_MID8BIT(status) LE_BITS_TO_4BYTE(status + 4, 24, 8)
#define GET_STATUS_HISR_LOW8BIT(status) LE_BITS_TO_4BYTE(status + 4, 16, 8)
#define GET_STATUS_ERROR(status) LE_BITS_TO_4BYTE(status + 4, 17, 1)
#define GET_STATUS_INT(status) LE_BITS_TO_4BYTE(status + 4, 16, 1)
#define GET_STATUS_RX_LENGTH(status) LE_BITS_TO_4BYTE(status + 4, 0, 16)
#define RXDESC_SIZE 24
#define TX_FREE_PG_QUEUE 4 // The number of Tx FIFO free page
#define TX_FIFO_PAGE_SZ 128
struct spi_more_data {
unsigned long more_data;
unsigned long len;
};
extern BUS_DRV_OPS_T bus_driver_ops;
extern u8 spi_query_status_info(struct dvobj_priv *pdvobj);
extern void spi_set_intf_ops(struct _io_ops *pops);
#endif //__GSPI_SPEC_H__

View file

@ -0,0 +1,68 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#ifndef _HCI_INTFS_H_
#define _HCI_INTFS_H_
#include <autoconf.h>
struct host_ctrl_intf_ops
{
struct dvobj_priv * (*dvobj_init)(void);
void (*dvobj_deinit)(struct dvobj_priv *dvobj);
void (*dvobj_request_irq)(struct dvobj_priv *dvobj);
void (*dvobj_free_irq)(struct dvobj_priv *dvobj);
};
extern struct dvobj_priv *hci_dvobj_init(void);
extern void hci_dvobj_deinit(struct dvobj_priv *dvobj);
extern void hci_dvobj_request_irq(struct dvobj_priv *dvobj);
extern void hci_dvobj_free_irq(struct dvobj_priv *dvobj);
#if defined(CONFIG_GSPI_HCI)
#define hci_bus_intf_type RTW_GSPI
#define hci_set_intf_ops spi_set_intf_ops
#define hci_intf_start rtw_hal_enable_interrupt
#define hci_intf_stop rtw_hal_disable_interrupt
extern s32 gspi_dvobj_xmit_mgnt(_adapter * padapter, struct xmit_frame *pmgntframe);
extern s32 gspi_dvobj_xmit_data(_adapter *padapter, struct xmit_frame *pxmitframe);
#endif
#if defined(CONFIG_SDIO_HCI)
#define hci_bus_intf_type RTW_SDIO
#define hci_set_intf_ops sdio_set_intf_ops
#define hci_intf_start rtw_hal_enable_interrupt
#define hci_intf_stop rtw_hal_disable_interrupt
extern s32 sdio_dvobj_xmit_mgnt(_adapter * padapter, struct xmit_frame *pmgntframe);
extern s32 sdio_dvobj_xmit_data(_adapter *padapter, struct xmit_frame *pxmitframe);
#endif
#if defined(CONFIG_LX_HCI)
#define hci_bus_intf_type RTW_LXBUS
#define hci_set_intf_ops lxbus_set_intf_ops
#define hci_intf_start rtw_hal_enable_interrupt
#define hci_intf_stop hci_lxbus_intf_stop
void hci_lxbus_intf_stop(_adapter *padapter);
u32 lextra_bus_dma_Interrupt (void* data);
#endif
#endif //_HCI_INTFS_H_

View file

@ -0,0 +1,433 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#ifndef __HCI_SPEC_H__
#define __HCI_SPEC_H__
#if defined(CONFIG_GSPI_HCI)
#include "gspi/gspi_spec.h"
// SPI Header Files
#ifdef PLATFORM_LINUX
#include <linux/spi/spi.h>
#endif
#define GSPI_CMD_LEN 4
#define HAL_INTERFACE_CMD_LEN GSPI_CMD_LEN
#define GSPI_STATUS_LEN 8
#define HAL_INTERFACE_CMD_STATUS_LEN GSPI_STATUS_LEN
#define HAL_INTERFACE_OVERHEAD (HAL_INTERFACE_CMD_LEN+HAL_INTERFACE_OVERHEAD)
//reserve tx headroom in case of softap forwarding unicase packet
#define RX_RESERV_HEADROOM (SKB_WLAN_TX_EXTRA_LEN>RX_DRIVER_INFO+RXDESC_SIZE)?(SKB_WLAN_TX_EXTRA_LEN-RX_DRIVER_INFO-RXDESC_SIZE):0
typedef struct gspi_data
{
//u8 func_number;
//u8 tx_block_mode;
//u8 rx_block_mode;
u16 block_transfer_len; //u32 block_transfer_len;
#ifdef PLATFORM_LINUX
struct spi_device *func;
struct workqueue_struct *priv_wq;
struct delayed_work irq_work;
#endif
#if defined(PLATFORM_FREERTOS) || defined (PLATFORM_CMSIS_RTOS)
_mutex spi_mutex;
#endif
} GSPI_DATA, *PGSPI_DATA;
#define INTF_DATA GSPI_DATA
//extern void spi_set_intf_ops(struct _io_ops *pops);
extern void spi_int_hdl(PADAPTER padapter);
#define rtw_hci_interrupt_handler(__adapter) spi_int_hdl(__adapter)
#elif defined(CONFIG_SDIO_HCI)
#include "sdio/sdio_spec.h"
#define GSPI_CMD_LEN 0
#define HAL_INTERFACE_CMD_LEN GSPI_CMD_LEN
#define GSPI_STATUS_LEN 8
#define HAL_INTERFACE_CMD_STATUS_LEN GSPI_STATUS_LEN
#define HAL_INTERFACE_OVERHEAD (HAL_INTERFACE_CMD_LEN+HAL_INTERFACE_OVERHEAD)
#define RX_RESERV_HEADROOM (SKB_WLAN_TX_EXTRA_LEN>RX_DRIVER_INFO+RXDESC_SIZE)?(SKB_WLAN_TX_EXTRA_LEN-RX_DRIVER_INFO-RXDESC_SIZE):0
typedef struct gspi_data
{
//u8 func_number;
//u8 tx_block_mode;
//u8 rx_block_mode;
u16 block_transfer_len; //u32 block_transfer_len;
#ifdef PLATFORM_LINUX
struct spi_device *func;
struct workqueue_struct *priv_wq;
struct delayed_work irq_work;
#endif
struct sdio_func *func;
#if defined(PLATFORM_FREERTOS) || defined (PLATFORM_CMSIS_RTOS)
_mutex spi_mutex;
#endif
} GSPI_DATA, *PGSPI_DATA;
#define INTF_DATA GSPI_DATA
//extern void spi_set_intf_ops(struct _io_ops *pops);
extern void spi_int_hdl(PADAPTER padapter);
#define rtw_hci_interrupt_handler(__adapter) spi_int_hdl(__adapter)
#elif defined(CONFIG_USB_HCI)
#include <usb_ops.h>
#include <usb_osintf.h>
#elif defined(CONFIG_PCI_HCI)
#include <pci_osintf.h>
#ifdef PLATFORM_LINUX
#include <linux/pci.h>
#endif
#define INTF_CMD_LEN 0
#define INTEL_VENDOR_ID 0x8086
#define SIS_VENDOR_ID 0x1039
#define ATI_VENDOR_ID 0x1002
#define ATI_DEVICE_ID 0x7914
#define AMD_VENDOR_ID 0x1022
#define PCI_MAX_BRIDGE_NUMBER 255
#define PCI_MAX_DEVICES 32
#define PCI_MAX_FUNCTION 8
#define PCI_CONF_ADDRESS 0x0CF8 // PCI Configuration Space Address
#define PCI_CONF_DATA 0x0CFC // PCI Configuration Space Data
#define PCI_CLASS_BRIDGE_DEV 0x06
#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04
#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10
#define U1DONTCARE 0xFF
#define U2DONTCARE 0xFFFF
#define U4DONTCARE 0xFFFFFFFF
#define PCI_VENDER_ID_REALTEK 0x10ec
#define HAL_HW_PCI_8180_DEVICE_ID 0x8180
#define HAL_HW_PCI_8185_DEVICE_ID 0x8185 //8185 or 8185b
#define HAL_HW_PCI_8188_DEVICE_ID 0x8188 //8185b
#define HAL_HW_PCI_8198_DEVICE_ID 0x8198 //8185b
#define HAL_HW_PCI_8190_DEVICE_ID 0x8190 //8190
#define HAL_HW_PCI_8723E_DEVICE_ID 0x8723 //8723E
#define HAL_HW_PCI_8192_DEVICE_ID 0x8192 //8192 PCI-E
#define HAL_HW_PCI_8192SE_DEVICE_ID 0x8192 //8192 SE
#define HAL_HW_PCI_8174_DEVICE_ID 0x8174 //8192 SE
#define HAL_HW_PCI_8173_DEVICE_ID 0x8173 //8191 SE Crab
#define HAL_HW_PCI_8172_DEVICE_ID 0x8172 //8191 SE RE
#define HAL_HW_PCI_8171_DEVICE_ID 0x8171 //8191 SE Unicron
#define HAL_HW_PCI_0045_DEVICE_ID 0x0045 //8190 PCI for Ceraga
#define HAL_HW_PCI_0046_DEVICE_ID 0x0046 //8190 Cardbus for Ceraga
#define HAL_HW_PCI_0044_DEVICE_ID 0x0044 //8192e PCIE for Ceraga
#define HAL_HW_PCI_0047_DEVICE_ID 0x0047 //8192e Express Card for Ceraga
#define HAL_HW_PCI_700F_DEVICE_ID 0x700F
#define HAL_HW_PCI_701F_DEVICE_ID 0x701F
#define HAL_HW_PCI_DLINK_DEVICE_ID 0x3304
#define HAL_HW_PCI_8192CET_DEVICE_ID 0x8191 //8192ce
#define HAL_HW_PCI_8192CE_DEVICE_ID 0x8178 //8192ce
#define HAL_HW_PCI_8191CE_DEVICE_ID 0x8177 //8192ce
#define HAL_HW_PCI_8188CE_DEVICE_ID 0x8176 //8192ce
#define HAL_HW_PCI_8192CU_DEVICE_ID 0x8191 //8192ce
#define HAL_HW_PCI_8192DE_DEVICE_ID 0x8193 //8192de
#define HAL_HW_PCI_002B_DEVICE_ID 0x002B //8192de, provided by HW SD
#define HAL_HW_PCI_8188EE_DEVICE_ID 0x8179
#define HAL_MEMORY_MAPPED_IO_RANGE_8190PCI 0x1000 //8190 support 16 pages of IO registers
#define HAL_HW_PCI_REVISION_ID_8190PCI 0x00
#define HAL_MEMORY_MAPPED_IO_RANGE_8192PCIE 0x4000 //8192 support 16 pages of IO registers
#define HAL_HW_PCI_REVISION_ID_8192PCIE 0x01
#define HAL_MEMORY_MAPPED_IO_RANGE_8192SE 0x4000 //8192 support 16 pages of IO registers
#define HAL_HW_PCI_REVISION_ID_8192SE 0x10
#define HAL_HW_PCI_REVISION_ID_8192CE 0x1
#define HAL_MEMORY_MAPPED_IO_RANGE_8192CE 0x4000 //8192 support 16 pages of IO registers
#define HAL_HW_PCI_REVISION_ID_8192DE 0x0
#define HAL_MEMORY_MAPPED_IO_RANGE_8192DE 0x4000 //8192 support 16 pages of IO registers
enum pci_bridge_vendor {
PCI_BRIDGE_VENDOR_INTEL = 0x0,//0b'0000,0001
PCI_BRIDGE_VENDOR_ATI, //= 0x02,//0b'0000,0010
PCI_BRIDGE_VENDOR_AMD, //= 0x04,//0b'0000,0100
PCI_BRIDGE_VENDOR_SIS ,//= 0x08,//0b'0000,1000
PCI_BRIDGE_VENDOR_UNKNOWN, //= 0x40,//0b'0100,0000
PCI_BRIDGE_VENDOR_MAX ,//= 0x80
} ;
// copy this data structor defination from MSDN SDK
typedef struct _PCI_COMMON_CONFIG {
u16 VendorID;
u16 DeviceID;
u16 Command;
u16 Status;
u8 RevisionID;
u8 ProgIf;
u8 SubClass;
u8 BaseClass;
u8 CacheLineSize;
u8 LatencyTimer;
u8 HeaderType;
u8 BIST;
union {
struct _PCI_HEADER_TYPE_0 {
u32 BaseAddresses[6];
u32 CIS;
u16 SubVendorID;
u16 SubSystemID;
u32 ROMBaseAddress;
u8 CapabilitiesPtr;
u8 Reserved1[3];
u32 Reserved2;
u8 InterruptLine;
u8 InterruptPin;
u8 MinimumGrant;
u8 MaximumLatency;
} type0;
#if 0
struct _PCI_HEADER_TYPE_1 {
u32 BaseAddresses[PCI_TYPE1_ADDRESSES];
u8 PrimaryBusNumber;
u8 SecondaryBusNumber;
u8 SubordinateBusNumber;
u8 SecondaryLatencyTimer;
u8 IOBase;
u8 IOLimit;
u16 SecondaryStatus;
u16 MemoryBase;
u16 MemoryLimit;
u16 PrefetchableMemoryBase;
u16 PrefetchableMemoryLimit;
u32 PrefetchableMemoryBaseUpper32;
u32 PrefetchableMemoryLimitUpper32;
u16 IOBaseUpper;
u16 IOLimitUpper;
u32 Reserved2;
u32 ExpansionROMBase;
u8 InterruptLine;
u8 InterruptPin;
u16 BridgeControl;
} type1;
struct _PCI_HEADER_TYPE_2 {
u32 BaseAddress;
u8 CapabilitiesPtr;
u8 Reserved2;
u16 SecondaryStatus;
u8 PrimaryBusNumber;
u8 CardbusBusNumber;
u8 SubordinateBusNumber;
u8 CardbusLatencyTimer;
u32 MemoryBase0;
u32 MemoryLimit0;
u32 MemoryBase1;
u32 MemoryLimit1;
u16 IOBase0_LO;
u16 IOBase0_HI;
u16 IOLimit0_LO;
u16 IOLimit0_HI;
u16 IOBase1_LO;
u16 IOBase1_HI;
u16 IOLimit1_LO;
u16 IOLimit1_HI;
u8 InterruptLine;
u8 InterruptPin;
u16 BridgeControl;
u16 SubVendorID;
u16 SubSystemID;
u32 LegacyBaseAddress;
u8 Reserved3[56];
u32 SystemControl;
u8 MultiMediaControl;
u8 GeneralStatus;
u8 Reserved4[2];
u8 GPIO0Control;
u8 GPIO1Control;
u8 GPIO2Control;
u8 GPIO3Control;
u32 IRQMuxRouting;
u8 RetryStatus;
u8 CardControl;
u8 DeviceControl;
u8 Diagnostic;
} type2;
#endif
} u;
u8 DeviceSpecific[108];
} PCI_COMMON_CONFIG , *PPCI_COMMON_CONFIG;
typedef struct _RT_PCI_CAPABILITIES_HEADER {
u8 CapabilityID;
u8 Next;
} RT_PCI_CAPABILITIES_HEADER, *PRT_PCI_CAPABILITIES_HEADER;
struct pci_priv{
BOOLEAN pci_clk_req;
u8 pciehdr_offset;
// PCIeCap is only differece between B-cut and C-cut.
// Configuration Space offset 72[7:4]
// 0: A/B cut
// 1: C cut and later.
u8 pcie_cap;
u8 linkctrl_reg;
u8 busnumber;
u8 devnumber;
u8 funcnumber;
u8 pcibridge_busnum;
u8 pcibridge_devnum;
u8 pcibridge_funcnum;
u8 pcibridge_vendor;
u16 pcibridge_vendorid;
u16 pcibridge_deviceid;
u8 pcibridge_pciehdr_offset;
u8 pcibridge_linkctrlreg;
u8 amd_l1_patch;
};
typedef struct _RT_ISR_CONTENT
{
union{
u32 IntArray[2];
u32 IntReg4Byte;
u16 IntReg2Byte;
};
}RT_ISR_CONTENT, *PRT_ISR_CONTENT;
//#define RegAddr(addr) (addr + 0xB2000000UL)
//some platform macros will def here
static inline void NdisRawWritePortUlong(u32 port, u32 val)
{
outl(val, port);
//writel(val, (u8 *)RegAddr(port));
}
static inline void NdisRawWritePortUchar(u32 port, u8 val)
{
outb(val, port);
//writeb(val, (u8 *)RegAddr(port));
}
static inline void NdisRawReadPortUchar(u32 port, u8 *pval)
{
*pval = inb(port);
//*pval = readb((u8 *)RegAddr(port));
}
static inline void NdisRawReadPortUshort(u32 port, u16 *pval)
{
*pval = inw(port);
//*pval = readw((u8 *)RegAddr(port));
}
static inline void NdisRawReadPortUlong(u32 port, u32 *pval)
{
*pval = inl(port);
//*pval = readl((u8 *)RegAddr(port));
}
#elif defined(CONFIG_LX_HCI)
#define GSPI_CMD_LEN 0
#define GSPI_STATUS_LEN 0
#include "lxbus/lxbus_spec.h"
#endif // interface define
#if 0 //TODO
struct intf_priv {
u8 *intf_dev;
u32 max_iosz; //USB2.0: 128, USB1.1: 64, SDIO:64
u32 max_xmitsz; //USB2.0: unlimited, SDIO:512
u32 max_recvsz; //USB2.0: unlimited, SDIO:512
volatile u8 *io_rwmem;
volatile u8 *allocated_io_rwmem;
u32 io_wsz; //unit: 4bytes
u32 io_rsz;//unit: 4bytes
u8 intf_status;
void (*_bus_io)(u8 *priv);
/*
Under Sync. IRP (SDIO/USB)
A protection mechanism is necessary for the io_rwmem(read/write protocol)
Under Async. IRP (SDIO/USB)
The protection mechanism is through the pending queue.
*/
_mutex ioctl_mutex;
#ifdef PLATFORM_LINUX
#ifdef CONFIG_USB_HCI
// when in USB, IO is through interrupt in/out endpoints
struct usb_device *udev;
PURB piorw_urb;
u8 io_irp_cnt;
u8 bio_irp_pending;
_sema io_retevt;
_timer io_timer;
u8 bio_irp_timeout;
u8 bio_timer_cancel;
#endif
#endif
#ifdef PLATFORM_OS_XP
#ifdef CONFIG_SDIO_HCI
// below is for io_rwmem...
PMDL pmdl;
PSDBUS_REQUEST_PACKET sdrp;
PSDBUS_REQUEST_PACKET recv_sdrp;
PSDBUS_REQUEST_PACKET xmit_sdrp;
PIRP piorw_irp;
#endif
#ifdef CONFIG_USB_HCI
PURB piorw_urb;
PIRP piorw_irp;
u8 io_irp_cnt;
u8 bio_irp_pending;
_sema io_retevt;
#endif
#endif
};
#endif
#endif //__HCI_SPEC_H__

View file

@ -0,0 +1,55 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#ifndef __LXBUS_SPEC_H__
#define __LXBUS_SPEC_H__
#include <lxbus_ops.h>
//#include <lxbus_hal.h>
#define HAL_INTERFACE_CMD_LEN 0
#define HAL_INTERFACE_CMD_STATUS_LEN 0
#define HAL_INTERFACE_OVERHEAD (HAL_INTERFACE_CMD_LEN+HAL_INTERFACE_CMD_STATUS_LEN)
/*
* The following data structure is used for 8195a debug, and should not
* declared this parameter in release version to save sram usage
* It is used for debugging tx/rx and r/w pointer
*/
struct hal_debug
{
unsigned int int_count;
unsigned int crc_err;
u16 last_write_be;
u16 last_write_mgt;
u16 last_closed_be;
u16 last_closed_mgt;
};
// The following section should be removed?
#define WLAN_TX_HIQ_DEVICE_ID 4 // 0b[16], 100b[15:13]
#define WLAN_TX_MIQ_DEVICE_ID 5 // 0b[16], 101b[15:13]
#define WLAN_TX_LOQ_DEVICE_ID 6 // 0b[16], 110b[15:13]
#define SDIO_MAX_TX_QUEUE 3 // HIQ, MIQ and LOQ
#endif //__LXBUS_SPEC_H__

View file

@ -0,0 +1,818 @@
/******************************************************************************
*
* 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 _GSPI_IO_C_
#include <drv_types.h>
#ifdef CONFIG_SDIO_HCI
#include "wifi_io.h" //from sdio_host driver
//#include <FreeRTOS.h>
//#include <task.h>
//#define SDIO_CMD52_IO
//SDIO host local register space mapping.
#define SDIO_LOCAL_MSK 0x0FFF
#define WLAN_IOREG_MSK 0x7FFF
#define WLAN_FIFO_MSK 0x1FFF // Aggregation Length[12:0]
#define WLAN_RX0FF_MSK 0x0003
#define SDIO_WITHOUT_REF_DEVICE_ID 0 // Without reference to the SDIO Device ID
#define SDIO_LOCAL_DEVICE_ID 0 // 0b[16], 000b[15:13]
#define WLAN_TX_HIQ_DEVICE_ID 4 // 0b[16], 100b[15:13]
#define WLAN_TX_MIQ_DEVICE_ID 5 // 0b[16], 101b[15:13]
#define WLAN_TX_LOQ_DEVICE_ID 6 // 0b[16], 110b[15:13]
#define WLAN_RX0FF_DEVICE_ID 7 // 0b[16], 111b[15:13]
#define WLAN_IOREG_DEVICE_ID 8 // 1b[16]
//
// 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.
//
#ifdef CONFIG_RTL8188F
u8 spi_query_status_info(struct dvobj_priv *pdvobj)
{
ADAPTER *padapter = pdvobj->if1;
pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX] = rtw_read8(padapter, LOCAL_REG_FREE_TXPG);
pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX] = rtw_read8(padapter, LOCAL_REG_FREE_TXPG+2);
pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX] = rtw_read8(padapter, LOCAL_REG_FREE_TXPG+4);
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] = rtw_read8(padapter, LOCAL_REG_FREE_TXPG+6);
RT_TRACE(_module_hci_ops_c_, _drv_notice_,
("%s: Free page for HIQ(%x),MIDQ(%x),LOWQ(%x),PUBQ(%x)\n",
__FUNCTION__,
pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
//_exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql);
return _TRUE;
}
#else
u8 spi_query_status_info(struct dvobj_priv *pdvobj)
{
u32 NumOfFreePage;
ADAPTER *padapter = pdvobj->if1;
NumOfFreePage = rtw_read32(padapter, LOCAL_REG_FREE_TXPG);
// _enter_critical_bh(&pdvobj->SdioTxFIFOFreePageLock, &irql);
rtw_memcpy(pdvobj->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__,
pdvobj->SdioTxFIFOFreePage[HI_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[MID_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
pdvobj->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
// _exit_critical_bh(&pdvobj->SdioTxFIFOFreePageLock, &irql);
return _TRUE;
}
#endif
static unsigned char get_deviceid(unsigned int addr)
{
unsigned char devideId;
unsigned short pseudoId;
pseudoId = (unsigned short)(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;
}
static unsigned int _cvrt2ftaddr(const unsigned int addr, unsigned char *pdeviceId, unsigned short *poffset)
{
unsigned char deviceId;
unsigned short offset;
unsigned int 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;
}
unsigned char sdio_read8(ADAPTER *Adapter, unsigned int addr, int *err)
{
struct dvobj_priv *psdiodev;
unsigned int ftaddr;
unsigned char val;
_func_enter_;
psdiodev = adapter_to_dvobj(Adapter);
ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
rtw_sdio_bus_ops.claim_host(psdiodev->intf_data.func);
val = rtw_sdio_bus_ops.readb(psdiodev->intf_data.func, ftaddr, err);
rtw_sdio_bus_ops.release_host(psdiodev->intf_data.func);
if(err && *err)
DBG_871X( "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
_func_exit_;
return val;
}
unsigned short sdio_read16(ADAPTER *Adapter, unsigned int addr, int *err)
{
struct dvobj_priv *psdiodev;
unsigned int ftaddr;
unsigned short val;
_func_enter_;
psdiodev = adapter_to_dvobj(Adapter);
if (addr & 1)
DBG_871X( "sdio_read16 addr is wrong addr:0x%08x\n", addr);
ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
rtw_sdio_bus_ops.claim_host(psdiodev->intf_data.func);
val = rtw_sdio_bus_ops.readw(psdiodev->intf_data.func, ftaddr, err);
rtw_sdio_bus_ops.release_host(psdiodev->intf_data.func);
if(err && *err)
DBG_871X( "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
_func_exit_;
return val;
}
unsigned int sdio_read32(ADAPTER *Adapter, unsigned int addr, int *err)
{
struct dvobj_priv *psdiodev;
unsigned int ftaddr;
unsigned int val;
_func_enter_;
psdiodev = adapter_to_dvobj(Adapter);
if (addr & 3)
DBG_871X( "sdio_read32 addr is wrong addr:0x%08x\n", addr);
ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
rtw_sdio_bus_ops.claim_host(psdiodev->intf_data.func);
val = rtw_sdio_bus_ops.readl(psdiodev->intf_data.func, ftaddr, err);
rtw_sdio_bus_ops.release_host(psdiodev->intf_data.func);
if(err && *err)
DBG_871X( "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
_func_exit_;
return val;
}
unsigned int sdio_write8(ADAPTER *Adapter, unsigned int addr, unsigned int buf, int*err)
{
struct dvobj_priv *psdiodev;
unsigned int ftaddr;
unsigned int val = 0;
_func_enter_;
psdiodev = adapter_to_dvobj(Adapter);
ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
rtw_sdio_bus_ops.claim_host(psdiodev->intf_data.func);
rtw_sdio_bus_ops.writeb(psdiodev->intf_data.func, buf&0xFF,ftaddr, err);
rtw_sdio_bus_ops.release_host(psdiodev->intf_data.func);
if(err && *err)
DBG_871X( "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
_func_exit_;
return val;
}
unsigned int sdio_write16(ADAPTER *Adapter, unsigned int addr,unsigned int buf, int *err)
{
struct dvobj_priv *psdiodev;
unsigned int ftaddr;
unsigned int val = 0;
_func_enter_;
psdiodev = adapter_to_dvobj(Adapter);
if (addr & 1)
DBG_871X( "sdio_write16 addr is wrong addr:0x%08x\n", addr);
ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
rtw_sdio_bus_ops.claim_host(psdiodev->intf_data.func);
rtw_sdio_bus_ops.writew(psdiodev->intf_data.func, buf&0xFFFF,ftaddr, err);
rtw_sdio_bus_ops.release_host(psdiodev->intf_data.func);
if(err && *err)
DBG_871X( "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
_func_exit_;
return val;
}
unsigned int sdio_write32(ADAPTER *Adapter, unsigned int addr, unsigned int buf, int *err)
{
struct dvobj_priv *psdiodev;
unsigned int ftaddr;
unsigned int val = 0;
_func_enter_;
psdiodev = adapter_to_dvobj(Adapter);
if (addr & 3)
DBG_871X( "sdio_write32 addr is wrong addr:0x%08x\n", addr);
ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
rtw_sdio_bus_ops.claim_host(psdiodev->intf_data.func);
rtw_sdio_bus_ops.writel(psdiodev->intf_data.func, buf&0xFFFFFFFF,ftaddr, err);
rtw_sdio_bus_ops.release_host(psdiodev->intf_data.func);
if(err && *err)
DBG_871X( "%s: FAIL!(%d) addr=0x%05x\n", __func__, *err, addr);
_func_exit_;
return val;
}
unsigned int _fifoqueue2ftaddr(unsigned int fifo, unsigned int addr)
{
unsigned int cmdaddr = TX_HIQ_DOMAIN;
switch(fifo) {
case TX_LOQ_DOMAIN:
cmdaddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
break;
case TX_HIQ_DOMAIN:
cmdaddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
break;
case TX_MIQ_DOMAIN:
cmdaddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
break;
case RX_RXFIFO_DOMAIN:
cmdaddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (addr & WLAN_RX0FF_MSK));
break;
default:
cmdaddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
break;
}
return cmdaddr;
}
void sdio_write_tx_fifo(ADAPTER *Adapter, unsigned char *buf, int reallen, unsigned int fifo)
{
struct dvobj_priv *psdiodev;
unsigned int ftaddr;
unsigned char *mem = buf;
int free_mem = 0;
int status;
unsigned int cnt = (unsigned int)reallen;
unsigned int page_num = 0;
unsigned int wait_num = 100;
unsigned int use_page = 0;
_func_enter_;
use_page = (cnt + TX_FIFO_PAGE_SZ - 1) / TX_FIFO_PAGE_SZ;
if (cnt > 512)
cnt = _RND(cnt, 512);
else
cnt = _RND(cnt, 4);
if (((u32)buf) % 4) {
mem = rtw_zmalloc(cnt);
while(!mem) {
DBG_871X("rtw_zmalloc fail, cannot write tx fifo now\n");
rtw_yield_os();
mem = rtw_zmalloc(cnt);
}
free_mem = 1;
//DBG_871X("sdio_write_tx_fifo tem_buf:%p ", mem);
rtw_memcpy(mem, buf, reallen);
} else {
mem = buf;
}
if (((u32)mem) % 4) {
DBG_871X("sdio_write_tx_fifo: Oops mem %p not 4 byte Alignment this will cause DMA wrong \n", mem);
}
psdiodev = adapter_to_dvobj(Adapter);
if (fifo == TX_HIQ_DOMAIN)
page_num = psdiodev->SdioTxFIFOFreePage[HI_QUEUE_IDX];
else if (fifo == TX_LOQ_DOMAIN)
page_num = psdiodev->SdioTxFIFOFreePage[LOW_QUEUE_IDX];
else
page_num = psdiodev->SdioTxFIFOFreePage[MID_QUEUE_IDX];
if (page_num + psdiodev->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] < use_page) {
spi_query_status_info(Adapter->dvobj);
}
while (page_num + psdiodev->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] < use_page) {
DBG_871X("Oops: spi_write_tx_fifo(): page_num is %d, padapter->pub_page is %d, wait_num is %d",
page_num, psdiodev->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX], wait_num);
rtw_msleep_os(1);
//rtw_udelay_os(20);
spi_query_status_info(Adapter->dvobj);
if (fifo == TX_HIQ_DOMAIN)
page_num = psdiodev->SdioTxFIFOFreePage[HI_QUEUE_IDX];
else if (fifo == TX_LOQ_DOMAIN)
page_num = psdiodev->SdioTxFIFOFreePage[LOW_QUEUE_IDX];
else
page_num = psdiodev->SdioTxFIFOFreePage[MID_QUEUE_IDX];
if (wait_num <= 2) {
DBG_871X("%s(): wait_num is <= 2 drop", __FUNCTION__);
return;
}
wait_num --;
}
if (fifo == TX_HIQ_DOMAIN) {
if (use_page <= page_num) {
psdiodev->SdioTxFIFOFreePage[HI_QUEUE_IDX] -= page_num;
} else {
psdiodev->SdioTxFIFOFreePage[HI_QUEUE_IDX] = 0;
psdiodev->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= use_page - psdiodev->SdioTxFIFOFreePage[HI_QUEUE_IDX];
}
} else if (fifo == TX_LOQ_DOMAIN) {
if (use_page <= page_num) {
psdiodev->SdioTxFIFOFreePage[LOW_QUEUE_IDX] -= page_num;
} else {
psdiodev->SdioTxFIFOFreePage[LOW_QUEUE_IDX] = 0;
psdiodev->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= use_page - psdiodev->SdioTxFIFOFreePage[LOW_QUEUE_IDX];
}
} else {
if (use_page <= page_num) {
psdiodev->SdioTxFIFOFreePage[MID_QUEUE_IDX] -= page_num;
} else {
psdiodev->SdioTxFIFOFreePage[MID_QUEUE_IDX] = 0;
psdiodev->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= use_page - psdiodev->SdioTxFIFOFreePage[MID_QUEUE_IDX];
}
}
//must reallen here or tx will wrong when RND(512)
ftaddr = _fifoqueue2ftaddr(fifo, reallen >> 2);
rtw_sdio_bus_ops.claim_host(psdiodev->intf_data.func);
status = rtw_sdio_bus_ops.memcpy_toio(psdiodev->intf_data.func, ftaddr, mem, cnt);
rtw_sdio_bus_ops.release_host(psdiodev->intf_data.func);
if (free_mem) {
rtw_mfree(mem, cnt);
}
if (status) {
DBG_871X("sdio_write_tx_fifo:status:%x ftaddr:%x Length:%d fifo:%x ", status, ftaddr, cnt, fifo);
}
_func_exit_;
return;
}
void sdio_read_rx_fifo(ADAPTER *Adapter, unsigned char *buf, int reallen)
{
struct dvobj_priv *psdiodev;
unsigned int ftaddr;
unsigned char *mem = buf;
int free_mem = 0;
int status;
unsigned int cnt = (unsigned int)reallen;
static unsigned int sdio_rxfifo_cnt = 0;
unsigned int fifo = RX_RXFIFO_DOMAIN;
_func_enter_;
if (cnt > 512)
cnt = _RND(cnt, 512);
else
cnt = _RND(cnt, 4);
mem = rtw_zmalloc(cnt);
if (mem) {
free_mem = 1;
//DBG_871X("sdio_read_rx_fifo tem_buf:%p ", mem);
} else {
//DBG_871X("sdio_read_rx_fifo tem_buf:Oops %p ", mem);
mem = buf;
}
if (mem == NULL) {
DBG_871X("sdio_read_rx_fifo: Oops mem is NULL \n");
return;
}
if (((u32)mem) % 4) {
DBG_871X("sdio_read_rx_fifo: Oops mem %p not 4 byte Alignment this will cause DMA wrong \n", mem);
}
psdiodev = adapter_to_dvobj(Adapter);
ftaddr = _fifoqueue2ftaddr(fifo, sdio_rxfifo_cnt++);
rtw_sdio_bus_ops.claim_host(psdiodev->intf_data.func);
status = rtw_sdio_bus_ops.memcpy_fromio(psdiodev->intf_data.func, mem, ftaddr, cnt);
rtw_sdio_bus_ops.release_host(psdiodev->intf_data.func);
if (free_mem) {
if (buf)
rtw_memcpy(buf, mem, reallen);
rtw_mfree(mem, cnt);
}
if (status) {
//error
DBG_871X("rtw_sdio_read_rx_fifo error 0x%x\n"
"***** Addr = %x *****\n"
"***** Length = %d *****\n", status, ftaddr, cnt);
}
_func_exit_;
return;
}
void sdio_cmd52_read(ADAPTER *Adapter, u32 addr, u32 cnt, u8 *pdata, int *err)
{
int i = 0;
for (i = 0; i < cnt; i++) {
pdata[i] = sdio_read8(Adapter, addr + i, err);
if (err && *err)
break;
}
}
void sdio_cmd52_write(ADAPTER *Adapter, u32 addr, u32 cnt, u8 *pdata, int *err)
{
int i = 0;
for (i = 0; i < cnt; i++) {
sdio_write8(Adapter, addr + i, pdata[i], err);
if (err && *err)
break;
}
}
u8 _sdio_read8(struct dvobj_priv *pdvobj, u32 addr, s32 *err)
{
u8 val;
ADAPTER *Adapter = pdvobj->if1;
_func_enter_;
val = sdio_read8(Adapter, addr, err);
_func_exit_;
return val;
}
u16 _sdio_read16(struct dvobj_priv *pdvobj, u32 addr, s32 *err)
{
u8 bMacPwrCtrlOn = _FALSE;
u16 val;
u8 cmd52_io = 0;
ADAPTER *Adapter = pdvobj->if1;
_func_enter_;
/* we should use CMD 52 before bMacPwrCtrlOn */
rtw_hal_get_hwreg(Adapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
cmd52_io = !bMacPwrCtrlOn;
#ifdef SDIO_CMD52_IO
cmd52_io = 1;
#endif
if (cmd52_io) {
sdio_cmd52_read(Adapter, addr, 2, (u8*)&val, err);
val = le16_to_cpu(val);
return val;
}
val = sdio_read16(Adapter, addr, err);
_func_exit_;
return val;
}
u32 _sdio_read32(struct dvobj_priv *pdvobj, u32 addr, s32 *err)
{
u8 bMacPwrCtrlOn = _FALSE;
u32 val;
u8 cmd52_io = 0;
ADAPTER *Adapter = pdvobj->if1;
_func_enter_;
/* we should use CMD 52 before bMacPwrCtrlOn */
rtw_hal_get_hwreg(Adapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
cmd52_io = !bMacPwrCtrlOn;
#ifdef SDIO_CMD52_IO
cmd52_io = 1;
#endif
if (cmd52_io) {
sdio_cmd52_read(Adapter, addr, 4, (u8*)&val, err);
val = le32_to_cpu(val);
return val;
}
val = sdio_read32(Adapter, addr, err);
_func_exit_;
return val;
}
s32 _sdio_write8(struct dvobj_priv *pdvobj, u32 addr, u8 val, s32 *err)
{
ADAPTER *Adapter = pdvobj->if1;
_func_enter_;
sdio_write8(Adapter, addr, (u32)val, err);
_func_exit_;
return _SUCCESS;
}
s32 _sdio_write16(struct dvobj_priv *pdvobj, u32 addr, u16 val, s32 *err)
{
u8 bMacPwrCtrlOn = _FALSE;
u8 cmd52_io = 0;
ADAPTER *Adapter = pdvobj->if1;
_func_enter_;
/* we should use CMD 52 before bMacPwrCtrlOn */
rtw_hal_get_hwreg(Adapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
cmd52_io = !bMacPwrCtrlOn;
#ifdef SDIO_CMD52_IO
cmd52_io = 1;
#endif
if (cmd52_io) {
val = cpu_to_le16(val);
sdio_cmd52_write(Adapter, addr, 2, (u8*)&val, err);
return _SUCCESS;
}
sdio_write16(Adapter, addr, (u32)val, err);
_func_exit_;
return _SUCCESS;
}
s32 _sdio_write32(struct dvobj_priv *pdvobj, u32 addr, u32 val, s32 *err)
{
u8 bMacPwrCtrlOn = _FALSE;
u8 cmd52_io = 0;
ADAPTER *Adapter = pdvobj->if1;
_func_enter_;
/* we should use CMD 52 before bMacPwrCtrlOn */
rtw_hal_get_hwreg(Adapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
cmd52_io = !bMacPwrCtrlOn;
#ifdef SDIO_CMD52_IO
cmd52_io = 1;
#endif
if (cmd52_io) {
val = cpu_to_le32(val);
sdio_cmd52_write(Adapter, addr, 4, (u8*)&val, err);
return _SUCCESS;
}
sdio_write32(Adapter, addr, val, err);
_func_exit_;
return _SUCCESS;
}
/*
* 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 int _sdio_read_rx_fifo(struct dvobj_priv *pdvobj, u32 addr, u8 *mem, u32 cnt, struct fifo_more_data *pmore_data)
{
ADAPTER *Adapter = pdvobj->if1;
//struct spi_more_data more_data = {0};
//DBG_8192C("%s \n", __func__);
rtw_memset(pmore_data, 0, sizeof(struct fifo_more_data));
sdio_read_rx_fifo(Adapter, mem, cnt);
return _SUCCESS;
}
/*
* Description:
* Translate sdio fifo address to Domain ID in each WLAN FIFO
*/
static u32 hwaddr2txfifo(u32 addr)
{
u32 fifo_domain_id;
switch (addr)
{
case WLAN_TX_HIQ_DEVICE_ID:
fifo_domain_id = TX_HIQ_DOMAIN;
break;
case WLAN_TX_MIQ_DEVICE_ID:
fifo_domain_id = TX_MIQ_DOMAIN;
break;
case WLAN_TX_LOQ_DEVICE_ID:
fifo_domain_id = TX_LOQ_DOMAIN;
break;
default:
fifo_domain_id = TX_LOQ_DOMAIN;
break;
}
return fifo_domain_id;
}
static int _sdio_write_tx_fifo(struct dvobj_priv *pdvobj, u32 addr, u8 *mem, u32 cnt)
{
u8 remain_len = 0;
u32 w_sz = cnt;
ADAPTER *Adapter = pdvobj->if1;
remain_len = w_sz%4;
if (remain_len != 0)
w_sz += 4 -remain_len;
#if 0//ndef LZM_TEST
if (1) {
int i = 0;
for(i = 0; i < w_sz; i += 4) {
DBG_871X("_sdio_write_port[%d]: 0x%08x ", i, *(u32*)(mem + i));
}
}
#endif
#if 0
{
static u32 write_test = 0;
u32 now_time = 0;
write_test++;
if(write_test==1000) {
now_time = xTaskGetTickCount() * portTICK_RATE_MS;
DBG_8192C("%s fifo:%d cnt:%d w_sz:%d mem:%p, now time:%d\n", __func__, addr, cnt, w_sz, mem, now_time);
write_test = 0;
}
}
#endif
sdio_write_tx_fifo(Adapter, mem, w_sz, hwaddr2txfifo(addr));
return _SUCCESS;
}
static int sdio_io_priv(struct dvobj_priv *pdvobj)
{
ADAPTER *Adapter = pdvobj->if1;
//struct dvobj_priv *pdvobj = &Adapter->dvobjpriv;
return _SUCCESS;
}
void sdio_set_intf_ops(struct _io_ops *pops)
{
pops->init_io_priv = &sdio_io_priv;
pops->write8_endian = NULL;
pops->_read8 = &_sdio_read8;
pops->_read16 = &_sdio_read16;
pops->_read32 = &_sdio_read32;
pops->_write8 = &_sdio_write8;
pops->_write16 = &_sdio_write16;
pops->_write32 = &_sdio_write32;
pops->read_rx_fifo = &_sdio_read_rx_fifo;
pops->write_tx_fifo = &_sdio_write_tx_fifo;
}
#endif

View file

@ -0,0 +1,264 @@
/******************************************************************************
*
* 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 _GSPI_INTF_C_
#include <drv_types.h>
#ifdef CONFIG_SDIO_HCI
#include "wifi_io.h" //from sdio_driver
#ifndef CONFIG_SDIO_HCI
#error "CONFIG_SDIO_HCI should be on!\n"
#endif
struct dvobj_priv *gspi_dvobj_init(void)
{
// int status = _FAIL;
struct dvobj_priv *dvobj = NULL;
PGSPI_DATA pgspi_data;
_func_enter_;
dvobj = (struct dvobj_priv*)rtw_zmalloc(sizeof(*dvobj));
if (NULL == dvobj) {
goto exit;
}
pgspi_data = &dvobj->intf_data;
rtw_mutex_init(&pgspi_data->spi_mutex);
//pgspi_data->block_transfer_len = 512; //512 blocks r/w is not required for GSPI interface
//pgspi_data->tx_block_mode = 0;
//pgspi_data->rx_block_mode = 0;
// status = _SUCCESS;
if(wifi_sdio_func) {
DBG_871X("[gspi_dvobj_init] get wifi_func:%p\n", wifi_sdio_func);
dvobj->intf_data.func = wifi_sdio_func;
} else {
DBG_871X("[gspi_dvobj_init] Oops: get wifi sdio function fail");
}
exit:
_func_exit_;
return dvobj;
}
void gspi_dvobj_deinit(struct dvobj_priv *dvobj)
{
//TODO
// struct dvobj_priv *dvobj = spi_get_drvdata(spi);
_func_enter_;
//TODO
// spi_set_drvdata(spi, NULL);
if (dvobj) {
//TODO
// gspi_deinit(dvobj);
rtw_mutex_free(&dvobj->intf_data.spi_mutex);
rtw_mfree((u8*)dvobj, sizeof(*dvobj));
}
_func_exit_;
}
void sdio_dvobj_interrupt_entry(struct sdio_func *func)
{
//DBG_871X("[sdio_wifi_interrupt_entry] func :%p\n", func);
//sdio irq have claim host, we should release it
//and claim it after SDIO IO, or SDIO IO will deadlock
rtw_sdio_bus_ops.release_host(func);
rtw_hci_interrupt_handler(func->drv_priv);
rtw_sdio_bus_ops.claim_host(func);
}
void sdio_dvobj_request_irq(struct dvobj_priv *dvobj)
{
_func_enter_;
if(dvobj->intf_data.func) {
dvobj->intf_data.func->drv_priv = (void*)dvobj->if1;
rtw_sdio_bus_ops.claim_host(dvobj->intf_data.func);
rtw_sdio_bus_ops.claim_irq(dvobj->intf_data.func, sdio_dvobj_interrupt_entry);
rtw_sdio_bus_ops.release_host(dvobj->intf_data.func);
}
_func_exit_;
}
void sdio_dvobj_free_irq(struct dvobj_priv *dvobj)
{
_func_enter_;
if(dvobj->intf_data.func) {
dvobj->intf_data.func->drv_priv = (void*)dvobj->if1;
rtw_sdio_bus_ops.claim_host(dvobj->intf_data.func);
rtw_sdio_bus_ops.release_irq(dvobj->intf_data.func);
rtw_sdio_bus_ops.release_host(dvobj->intf_data.func);
}
_func_exit_;
}
static inline u32 ffaddr2deviceId(struct dvobj_priv *pdvobj, u32 addr)
{
return pdvobj->Queue2Pipe[addr];
}
static s32 rtw_xmit_xmitbuf(_adapter * padapter, struct xmit_buf *pxmitbuf)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
u32 deviceId;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("@@@rtw_xmit_xmitbuf(): pxmitbuf->len=%d\n", pxmitbuf->len));
//translate queue index to Device Id
deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8*)pxmitbuf->pbuf);
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
return _SUCCESS;
}
s32 sdio_dvobj_xmit_mgnt(_adapter * padapter, struct xmit_frame *pmgntframe)
{
s32 ret = _SUCCESS;
struct pkt_attrib *pattrib;
struct xmit_buf *pxmitbuf;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
u8 *pframe = NULL;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("+rtw_xmit_mgnt()\n"));
pattrib = &pmgntframe->attrib;
pxmitbuf = pmgntframe->pxmitbuf;
pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
//rtw_hal_update_txdesc(padapter, pmgntframe, pmgntframe->buf_addr);
pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
//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);
//RT_TRACE(_module_rtl871x_xmit_c_, _drv_always_, ("+rtw_xmit_mgnt(): type=%d\n", GetFrameSubType(pframe)));
if(GetFrameSubType(pframe)==WIFI_BEACON) //dump beacon directly
{
//When using dedicated xmit frame for issue bcn on ap mode
//free xmit frame for bcn reserved page on station mode - Alex Fang
#if USE_DEDICATED_BCN_TX
if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE) {
rtw_free_xmitframe(pxmitpriv, pmgntframe);
pxmitbuf->priv_data = NULL;
}
rtw_write_port(padapter, ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr), pxmitbuf->len, pxmitbuf->pbuf);
if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
#else
rtw_free_xmitframe(pxmitpriv, pmgntframe);
pxmitbuf->priv_data = NULL;
rtw_xmit_xmitbuf(padapter, pxmitbuf);
#endif
}
else
{
rtw_free_xmitframe(pxmitpriv, pmgntframe);
pxmitbuf->priv_data = NULL;
rtw_xmit_xmitbuf(padapter, pxmitbuf);
}
if (ret != _SUCCESS)
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("-rtw_xmit_mgnt\n"));
return ret;
}
s32 sdio_dvobj_xmit_data(_adapter *padapter, struct xmit_frame *pxmitframe)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
_irqL irql;
s32 err;
#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
#if USE_SKB_AS_XMITBUF
rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
#endif
rtw_enter_critical_bh(&pxmitpriv->lock, &irql);
#if 1 //FIX_XMITFRAME_FAULT, move from rtw_xmit().
#ifdef CONFIG_AP_MODE
if(xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe) == _TRUE)
{
rtw_exit_critical_bh(&pxmitpriv->lock, &irql);
return 1;
}
#endif
#endif
err = rtw_xmitframe_enqueue(padapter, pxmitframe);
rtw_exit_critical_bh(&pxmitpriv->lock, &irql);
if (err != _SUCCESS) {
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("rtw_xmit_data(): enqueue xmitframe fail\n"));
rtw_free_xmitframe(pxmitpriv, pxmitframe);
// Trick, make the statistics correct
pxmitpriv->tx_pkts--;
pxmitpriv->tx_drop++;
return _TRUE;
}
#ifdef CONFIG_CONCURRENT_MODE
if (padapter->adapter_type > PRIMARY_ADAPTER){
padapter = padapter->pbuddy_adapter;
}
#endif
rtw_wakeup_task(&padapter->xmitThread);
return _FALSE;
}
const struct host_ctrl_intf_ops hci_ops = {
gspi_dvobj_init,
gspi_dvobj_deinit,
sdio_dvobj_request_irq,
sdio_dvobj_free_irq
};
#endif

View file

@ -0,0 +1,223 @@
/******************************************************************************
*
* 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 _GSPI_ISR_C_
#include <drv_types.h>
#ifdef CONFIG_SDIO_HCI
extern struct recv_buf* rtw_recv_rxfifo(_adapter * padapter, u32 size, struct fifo_more_data* more_data);
void spi_int_dpc(PADAPTER padapter, u32 sdio_hisr)
{
struct dvobj_priv *pdvobj = padapter->dvobj;
#ifdef CONFIG_LPS_LCLK
if (sdio_hisr & HCI_HISR_CPWM1)
{
struct reportpwrstate_parm report;
report.state = rtw_read8(padapter, LOCAL_REG_HCPWM1);
cpwm_int_hdl(padapter, &report);
}
#endif
if (sdio_hisr & HCI_HISR_TXERR)
{
u32 status;
status = rtw_read32(padapter, REG_TXDMA_STATUS);
rtw_write32(padapter, REG_TXDMA_STATUS, status);
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, status));
}
#ifdef CONFIG_INTERRUPT_BASED_TXBCN
#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT
if (sdio_hisr & HCI_HISR_BCNERLY_INT)
#endif
#ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR
if (sdio_hisr & (HCI_HISR_TXBCNOK|HCI_HISR_TXBCNERR))
#endif
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
#if 0 //for debug
if (sdio_hisr & SDIO_HISR_BCNERLY_INT)
DBG_8192C("%s: SDIO_HISR_BCNERLY_INT\n", __func__);
if (sdio_hisr & SDIO_HISR_TXBCNOK)
DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
if (sdio_hisr & SDIO_HISR_TXBCNERR) {
u1Byte v422, v550, v419;
v422 = rtw_read8(padapter, 0x422);
v419 = rtw_read8(padapter, 0x419);
v550 = rtw_read8(padapter, 0x550);
DBG_8192C("%s: SDIO_HISR_TXBCNERR 422=%02x, 419=%02x, 550=%02x\n", __func__, v422, v419, v550);
}
#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
if (sdio_hisr & HCI_HISR_C2HCMD)
{
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s: C2H Command\n", __func__));
//TODO
// rtw_c2h_wk_cmd(padapter);
}
if (sdio_hisr & HCI_HISR_RX_REQUEST)// || sdio_hisr & SPI_HISR_RXFOVW)
{
struct recv_buf *precvbuf;
struct fifo_more_data more_data = {0};
//RT_TRACE(_module_hci_ops_c_,_drv_info_, ("%s: RX Request, size=%d\n", __func__, pdvobj->SdioRxFIFOSize));
sdio_hisr ^= HCI_HISR_RX_REQUEST;
do {
more_data.more_data = 0;
more_data.len = 0;
if (pdvobj->SdioRxFIFOSize == 0)
{
u16 val = 0;
//s32 ret; //LZM_TODO
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s, %d, read RXFIFOsize again size=%d\n", __FUNCTION__, __LINE__, pdvobj->SdioRxFIFOSize));
val = rtw_read16(padapter, LOCAL_REG_RX0_REQ_LEN_1_BYTE);
//if (!ret) {
pdvobj->SdioRxFIFOSize = val;
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s: RX_REQUEST, read RXFIFOsize again size=%d\n", __func__, pdvobj->SdioRxFIFOSize));
//} else {
// RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s: RX_REQUEST, read RXFIFOsize ERROR!!\n", __func__));
//}
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s, %d, read RXFIFOsize again size=%d\n", __FUNCTION__, __LINE__, pdvobj->SdioRxFIFOSize));
}
if (pdvobj->SdioRxFIFOSize != 0)
{
#ifdef RTL8723A_SDIO_LOOPBACK
sd_recv_loopback(padapter, pdvobj->SdioRxFIFOSize);
#else
if (sdio_hisr & HCI_HISR_RXFOVW)
RT_TRACE(_module_hci_ops_c_, _drv_info_, ("%s RXFOVW RX\n", __func__));
precvbuf = rtw_recv_rxfifo(padapter, pdvobj->SdioRxFIFOSize, &more_data);
if (precvbuf)
rtw_rxhandler(padapter, precvbuf);
if (more_data.more_data) {
pdvobj->SdioRxFIFOSize = more_data.len;
} else {
pdvobj->SdioRxFIFOSize = 0;
}
#endif
//If Rx_request ISR is set, execute receive tasklet (sdio_hisr & SPI_HISR_RX_REQUEST)
#if defined(CONFIG_ISR_THREAD_MODE_INTERRUPT) && defined(CONFIG_RECV_TASKLET_THREAD)
rtw_wakeup_task(&padapter->recvtasklet_thread);
#endif
}
#ifdef CONFIG_INTERRUPT_BASED_TXBCN
{
//Prevent BCN update not realtime in ap mode - Alex Fang
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
if((check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) && (pmlmepriv->update_bcn == _TRUE))
break;
}
#endif
} while (more_data.more_data || pdvobj->SdioRxFIFOSize);
#ifdef PLATFORM_LINUX
#ifdef CONFIG_GSPI_HCI
tasklet_schedule(&padapter->recvpriv.recv_tasklet);
#endif
#endif
}
}
void spi_int_hdl(PADAPTER padapter)
{
struct dvobj_priv *pdvobj = padapter->dvobj;
u32 sdio_hisr = 0;
//s32 ret;
if ((padapter->bDriverStopped == _TRUE) ||
(padapter->bSurpriseRemoved == _TRUE))
return;
sdio_hisr = rtw_read32(padapter, LOCAL_REG_HISR);//, &ret);
//if (!ret) {
// RT_TRACE(_module_hci_ops_c_, _drv_err_, ("%s: read SDIO_REG_HISR FAIL!!\n", __func__));
// return;
//}
pdvobj->SdioRxFIFOSize = rtw_read16(padapter, LOCAL_REG_RX0_REQ_LEN_1_BYTE);//, &ret);
//if (!ret) {
// RT_TRACE(_module_hci_ops_c_, _drv_err_, ("%s: read SPI_REG_RX0_REQ_LEN FAIL!!\n", __func__));
// return;
//}
if (sdio_hisr & pdvobj->sdio_himr)
{
u32 v32;
sdio_hisr &= pdvobj->sdio_himr;
// clear HISR
v32 = sdio_hisr & MASK_SPI_HISR_CLEAR;
if (v32) {
rtw_write32(padapter, LOCAL_REG_HISR, v32);//, &ret);
}
spi_int_dpc(padapter, sdio_hisr);
} else {
//RT_TRACE(_module_hci_ops_c_, _drv_err_,
// ("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
// __FUNCTION__, sdio_hisr, pdvobj->sdio_himr));
}
}
#endif

View file

@ -0,0 +1,193 @@
/******************************************************************************
*
* 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
*
*******************************************************************************/
#ifndef __GSDIO_SPEC_H__
#define __GSDIO_SPEC_H__
#define SPI_LOCAL_DOMAIN 0x0
#define WLAN_IOREG_DOMAIN 0x8
#define FW_FIFO_DOMAIN 0x4
#define TX_HIQ_DOMAIN 0xc
#define TX_MIQ_DOMAIN 0xd
#define TX_LOQ_DOMAIN 0xe
#define RX_RXFIFO_DOMAIN 0x1f
//IO Bus domain address mapping
#define DEFUALT_OFFSET 0x0
#define SPI_LOCAL_OFFSET 0x10250000
#define WLAN_IOREG_OFFSET 0x10260000
#define FW_FIFO_OFFSET 0x10270000
#define TX_HIQ_OFFSET 0x10310000
#define TX_MIQ_OFFSET 0x1032000
#define TX_LOQ_OFFSET 0x10330000
#define RX_RXOFF_OFFSET 0x10340000
#define WLAN_TX_HIQ_DEVICE_ID 4 // 0b[16], 100b[15:13]
#define WLAN_TX_MIQ_DEVICE_ID 5 // 0b[16], 101b[15:13]
#define WLAN_TX_LOQ_DEVICE_ID 6 // 0b[16], 110b[15:13]
#define WLAN_TX_EXQ_DEVICE_ID 3 // 0b[16], 011b[15:13]
#define WLAN_RX0FF_DEVICE_ID 7 // 0b[16], 111b[15:13]
#define WLAN_IOREG_DEVICE_ID 8 // 1b[16]
//SPI Tx Free Page Index
#define HI_QUEUE_IDX 0
#define MID_QUEUE_IDX 1
#define LOW_QUEUE_IDX 2
#define PUBLIC_QUEUE_IDX 3
#define MAX_TX_QUEUE 3 // HIQ, MIQ and LOQ
#define MAX_RX_QUEUE 1
//SPI Local registers
#define SPI_REG_TX_CTRL (SPI_LOCAL_OFFSET | 0x0000) // SPI Tx Control
#define SPI_REG_STATUS_RECOVERY (SPI_LOCAL_OFFSET | 0x0004)
#define SPI_REG_INT_TIMEOUT (SPI_LOCAL_OFFSET | 0x0006)
#define SPI_REG_HIMR (SPI_LOCAL_OFFSET | 0x0014) // SPI Host Interrupt Mask
#define SPI_REG_HISR (SPI_LOCAL_OFFSET | 0x0018) // SPI Host Interrupt Service Routine
#define SPI_REG_RX0_REQ_LEN (SPI_LOCAL_OFFSET | 0x001C) // RXDMA Request Length
#define SPI_REG_FREE_TXPG (SPI_LOCAL_OFFSET | 0x0020) // Free Tx Buffer Page
#define SPI_REG_HCPWM1 (SPI_LOCAL_OFFSET | 0x0024) // HCI Current Power Mode 1
#define SPI_REG_HCPWM2 (SPI_LOCAL_OFFSET | 0x0026) // HCI Current Power Mode 2
#define SPI_REG_HTSFR_INFO (SPI_LOCAL_OFFSET | 0x0030) // HTSF Informaion
#define SPI_REG_HRPWM1 (SPI_LOCAL_OFFSET | 0x0080) // HCI Request Power Mode 1
#define SPI_REG_HRPWM2 (SPI_LOCAL_OFFSET | 0x0082) // HCI Request Power Mode 2
#define SPI_REG_HPS_CLKR (SPI_LOCAL_OFFSET | 0x0084) // HCI Power Save Clock
#define SPI_REG_HSUS_CTRL (SPI_LOCAL_OFFSET | 0x0086) // SPI HCI Suspend Control
#define SPI_REG_HIMR_ON (SPI_LOCAL_OFFSET | 0x0090) //SPI Host Extension Interrupt Mask Always
#define SPI_REG_HISR_ON (SPI_LOCAL_OFFSET | 0x0091) //SPI Host Extension Interrupt Status Always
#define SPI_REG_CFG (SPI_LOCAL_OFFSET | 0x00F0) //SPI Configuration Register
#define LOCAL_REG_TX_CTRL (SPI_REG_TX_CTRL |SPI_LOCAL_OFFSET)
#define LOCAL_REG_STATUS_RECOVERY (SPI_REG_STATUS_RECOVERY |SPI_LOCAL_OFFSET)
#define LOCAL_REG_INT_TIMEOUT (SPI_REG_INT_TIMEOUT |SPI_LOCAL_OFFSET)
#define LOCAL_REG_HIMR (SPI_REG_HIMR |SPI_LOCAL_OFFSET)
#define LOCAL_REG_HISR (SPI_REG_HISR |SPI_LOCAL_OFFSET)
#define LOCAL_REG_RX0_REQ_LEN_1_BYTE (SPI_REG_RX0_REQ_LEN |SPI_LOCAL_OFFSET)
#define LOCAL_REG_FREE_TXPG (SPI_REG_FREE_TXPG |SPI_LOCAL_OFFSET)
#define LOCAL_REG_HRPWM1 (SPI_REG_HRPWM1 |SPI_LOCAL_OFFSET)
#define LOCAL_REG_HCPWM1 (SPI_REG_HCPWM1 |SPI_LOCAL_OFFSET)
#define HCI_HIMR_DISABLED 0
//SPI HIMR MASK diff with SDIO
#define HCI_HISR_RX_REQUEST BIT(0)
#define HCI_HISR_AVAL BIT(1)
#define HCI_HISR_TXERR BIT(2)
#define HCI_HISR_RXERR BIT(3)
#define HCI_HISR_TXFOVW BIT(4)
#define HCI_HISR_RXFOVW BIT(5)
#define HCI_HISR_TXBCNOK BIT(6)
#define HCI_HISR_TXBCNERR BIT(7)
#define HCI_HISR_BCNERLY_INT BIT(16)
#define HCI_HISR_C2HCMD BIT(17)
#define HCI_HISR_CPWM1 BIT(18)
#define HCI_HISR_CPWM2 BIT(19)
#define HCI_HISR_HSISR_IND BIT(20)
#define HCI_HISR_GTINT3_IND BIT(21)
#define HCI_HISR_GTINT4_IND BIT(22)
#define HCI_HISR_PSTIMEOUT BIT(23)
#define HCI_HISR_OCPINT BIT(24)
#define HCI_HISR_ATIMEND BIT(25)
#define HCI_HISR_ATIMEND_E BIT(26)
#define HCI_HISR_CTWEND BIT(27)
//SPI HIMR MASK diff with SDIO
#define HCI_HIMR_RX_REQUEST BIT(0)
#define HCI_HIMR_AVAL BIT(1)
#define HCI_HIMR_TXERR BIT(2)
#define HCI_HIMR_RXERR BIT(3)
#define HCI_HIMR_TXFOVW BIT(4)
#define HCI_HIMR_RXFOVW BIT(5)
#define HCI_HIMR_TXBCNOK BIT(6)
#define HCI_HIMR_TXBCNERR BIT(7)
#define HCI_HIMR_BCNERLY_INT BIT(16)
#define HCI_HIMR_ATIMEND BIT(17)
#define HCI_HIMR_ATIMEND_E BIT(18)
#define HCI_HIMR_CTWEND BIT(19)
#define HCI_HIMR_C2HCMD BIT(20)
#define HCI_HIMR_CPWM1 BIT(21)
#define HCI_HIMR_CPWM2 BIT(22)
#define HCI_HIMR_HSISR_IND BIT(23)
#define HCI_HIMR_GTINT3_IND BIT(24)
#define HCI_HIMR_GTINT4_IND BIT(25)
#define HCI_HIMR_PSTIMEOUT BIT(26)
#define HCI_HIMR_OCPINT BIT(27)
#define HCI_HIMR_TSF_BIT32_TOGGLE BIT(29)
#define MASK_SPI_HISR_CLEAR (HCI_HIMR_TXERR |\
HCI_HIMR_RXERR |\
HCI_HIMR_TXFOVW |\
HCI_HIMR_RXFOVW |\
HCI_HIMR_TXBCNOK |\
HCI_HIMR_TXBCNERR |\
HCI_HIMR_C2HCMD |\
HCI_HIMR_CPWM1 |\
HCI_HIMR_CPWM2 |\
HCI_HIMR_HSISR_IND |\
HCI_HIMR_GTINT3_IND |\
HCI_HIMR_GTINT4_IND |\
HCI_HIMR_PSTIMEOUT |\
HCI_HIMR_OCPINT)
#define REG_LEN_FORMAT(pcmd, x) SET_BITS_TO_LE_4BYTE(pcmd, 0, 8, x)//(x<<(unsigned int)24)
#define REG_ADDR_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 8, 16, x)//(x<<(unsigned int)16)
#define REG_DOMAIN_ID_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 24, 5, x)//(x<<(unsigned int)0)
#define REG_FUN_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 29, 2, x)//(x<<(unsigned int)5)
#define REG_RW_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 31, 1, x)//(x<<(unsigned int)7)
#define FIFO_LEN_FORMAT(pcmd, x) SET_BITS_TO_LE_4BYTE(pcmd, 0, 16, x)//(x<<(unsigned int)24)
//#define FIFO_ADDR_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 8, 16, x)//(x<<(unsigned int)16)
#define FIFO_DOMAIN_ID_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 24, 5, x)//(x<<(unsigned int)0)
#define FIFO_FUN_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 29, 2, x)//(x<<(unsigned int)5)
#define FIFO_RW_FORMAT(pcmd,x) SET_BITS_TO_LE_4BYTE(pcmd, 31, 1, x)//(x<<(unsigned int)7)
//get status dword0
#define GET_STATUS_PUB_PAGE_NUM(status) LE_BITS_TO_4BYTE(status, 24, 8)
#define GET_STATUS_HI_PAGE_NUM(status) LE_BITS_TO_4BYTE(status, 18, 6)
#define GET_STATUS_MID_PAGE_NUM(status) LE_BITS_TO_4BYTE(status, 12, 6)
#define GET_STATUS_LOW_PAGE_NUM(status) LE_BITS_TO_4BYTE(status, 6, 6)
#define GET_STATUS_HISR_HI6BIT(status) LE_BITS_TO_4BYTE(status, 0, 6)
//get status dword1
#define GET_STATUS_HISR_MID8BIT(status) LE_BITS_TO_4BYTE(status + 4, 24, 8)
#define GET_STATUS_HISR_LOW8BIT(status) LE_BITS_TO_4BYTE(status + 4, 16, 8)
#define GET_STATUS_ERROR(status) LE_BITS_TO_4BYTE(status + 4, 17, 1)
#define GET_STATUS_INT(status) LE_BITS_TO_4BYTE(status + 4, 16, 1)
#define GET_STATUS_RX_LENGTH(status) LE_BITS_TO_4BYTE(status + 4, 0, 16)
#define RXDESC_SIZE 24
#define TX_FREE_PG_QUEUE 4 // The number of Tx FIFO free page
#define TX_FIFO_PAGE_SZ 128
struct spi_more_data {
unsigned long more_data;
unsigned long len;
};
extern BUS_DRV_OPS_T bus_driver_ops;
extern u8 spi_query_status_info(struct dvobj_priv *pdvobj);
extern void sdio_set_intf_ops(struct _io_ops *pops);
#endif //__GSPI_SPEC_H__