diff options
Diffstat (limited to 'drivers/net/wireless/rtl8192ce/core/rtw_iol.c')
-rwxr-xr-x | drivers/net/wireless/rtl8192ce/core/rtw_iol.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtl8192ce/core/rtw_iol.c b/drivers/net/wireless/rtl8192ce/core/rtw_iol.c new file mode 100755 index 000000000000..0d9dfb1695e6 --- /dev/null +++ b/drivers/net/wireless/rtl8192ce/core/rtw_iol.c @@ -0,0 +1,266 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ + +#include<rtw_iol.h> + +#ifdef CONFIG_IOL +struct xmit_frame *rtw_IOL_accquire_xmit_frame(ADAPTER *adapter) +{ + struct xmit_frame *xmit_frame; + struct xmit_buf *xmitbuf; + struct pkt_attrib *pattrib; + struct xmit_priv *pxmitpriv = &(adapter->xmitpriv); + +#if 1 + if ((xmit_frame = rtw_alloc_xmitframe(pxmitpriv)) == NULL) + { + DBG_871X("%s rtw_alloc_xmitframe return null\n", __FUNCTION__); + goto exit; + } + + if ((xmitbuf = rtw_alloc_xmitbuf(pxmitpriv)) == NULL) + { + DBG_871X("%s rtw_alloc_xmitbuf return null\n", __FUNCTION__); + rtw_free_xmitframe_ex(pxmitpriv, xmit_frame); + xmit_frame=NULL; + goto exit; + } + + xmit_frame->frame_tag = MGNT_FRAMETAG; + xmit_frame->pxmitbuf = xmitbuf; + xmit_frame->buf_addr = xmitbuf->pbuf; + xmitbuf->priv_data = xmit_frame; + + pattrib = &xmit_frame->attrib; + update_mgntframe_attrib(adapter, pattrib); + pattrib->qsel = 0x10; + pattrib->pktlen = pattrib->last_txcmdsz = 0; + +#else + if ((xmit_frame = alloc_mgtxmitframe(pxmitpriv)) == NULL) + { + DBG_871X("%s alloc_mgtxmitframe return null\n", __FUNCTION__); + } + else { + pattrib = &xmit_frame->attrib; + update_mgntframe_attrib(adapter, pattrib); + pattrib->qsel = 0x10; + pattrib->pktlen = pattrib->last_txcmdsz = 0; + } +#endif + +exit: + return xmit_frame; +} + + +int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len) +{ + struct pkt_attrib *pattrib = &xmit_frame->attrib; + u16 buf_offset; + u32 ori_len; + +//Todo: bulkout without this offset +#ifdef CONFIG_USB_HCI + buf_offset = TXDESC_OFFSET; +#else + buf_offset = 0; +#endif + + ori_len = buf_offset+pattrib->pktlen; + + //check if the io_buf can accommodate new cmds + if(ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) { + DBG_871X("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate new cmds\n", __FUNCTION__ + , ori_len + cmd_len + 8, MAX_XMITBUF_SZ); + return _FAIL; + } + + _rtw_memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len); + pattrib->pktlen += cmd_len; + pattrib->last_txcmdsz += cmd_len; + + //DBG_871X("%s ori:%u + cmd_len:%u = %u\n", __FUNCTION__, ori_len, cmd_len, buf_offset+pattrib->pktlen); + + return _SUCCESS; +} + +int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary) +{ + IOL_CMD cmd = {0x0, IOL_CMD_LLT, 0x0, 0x0}; + + RTW_PUT_BE32((u8*)&cmd.value, (u32)page_boundary); + + return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8); +} + +int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value) +{ + IOL_CMD cmd = {0x0, IOL_CMD_WB_REG, 0x0, 0x0}; + + RTW_PUT_BE16((u8*)&cmd.address, (u16)addr); + RTW_PUT_BE32((u8*)&cmd.value, (u32)value); + + return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8); +} + +int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value) +{ + IOL_CMD cmd = {0x0, IOL_CMD_WW_REG, 0x0, 0x0}; + + RTW_PUT_BE16((u8*)&cmd.address, (u16)addr); + RTW_PUT_BE32((u8*)&cmd.value, (u32)value); + + return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8); +} + +int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value) +{ + IOL_CMD cmd = {0x0, IOL_CMD_WD_REG, 0x0, 0x0}; + u8* pos = (u8 *)&cmd; + + RTW_PUT_BE16((u8*)&cmd.address, (u16)addr); + RTW_PUT_BE32((u8*)&cmd.value, (u32)value); + + return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8); +} + +#ifdef DBG_IO +int dbg_rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, const char *caller, const int line) +{ + if (match_write_sniff_ranges(addr, 1)) + DBG_871X("DBG_IO %s:%d IOL_WB(0x%04x, 0x%02x)\n", caller, line, addr, value); + + return _rtw_IOL_append_WB_cmd(xmit_frame, addr, value); +} + +int dbg_rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, const char *caller, const int line) +{ + if (match_write_sniff_ranges(addr, 2)) + DBG_871X("DBG_IO %s:%d IOL_WW(0x%04x, 0x%04x)\n", caller, line, addr, value); + + return _rtw_IOL_append_WW_cmd(xmit_frame, addr, value); +} + +int dbg_rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, const char *caller, const int line) +{ + if (match_write_sniff_ranges(addr, 4)) + DBG_871X("DBG_IO %s:%d IOL_WD(0x%04x, 0x%08x)\n", caller, line, addr, value); + + return _rtw_IOL_append_WD_cmd(xmit_frame, addr, value); +} +#endif + +int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us) +{ + IOL_CMD cmd = {0x0, IOL_CMD_DELAY_US, 0x0, 0x0}; + + RTW_PUT_BE32((u8*)&cmd.value, (u32)us); + + //DBG_871X("%s %u\n", __FUNCTION__, us); + + return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8); +} + +int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms) +{ + IOL_CMD cmd = {0x0, IOL_CMD_DELAY_MS, 0x0, 0x0}; + + RTW_PUT_BE32((u8*)&cmd.value, (u32)ms); + + //DBG_871X("%s %u\n", __FUNCTION__, ms); + + return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8); +} + +int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame) +{ + struct pkt_attrib *pattrib = &xmit_frame->attrib; + u16 buf_offset; + u32 ori_len; + IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0}; + +//Todo: bulkout without this offset +#ifdef CONFIG_USB_HCI + buf_offset = TXDESC_OFFSET; +#else + buf_offset = 0; +#endif + + ori_len = buf_offset+pattrib->pktlen; + + //check if the io_buf can accommodate new cmds + if(ori_len + 8 > MAX_XMITBUF_SZ) { + DBG_871X("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate end cmd\n", __FUNCTION__ + , ori_len + 8, MAX_XMITBUF_SZ); + return _FAIL; + } + + _rtw_memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, (u8*)&end_cmd, 8); + pattrib->pktlen += 8; + pattrib->last_txcmdsz += 8; + + //DBG_871X("%s ori:%u + 8 = %u\n", __FUNCTION__ , ori_len, buf_offset+pattrib->pktlen); + + return _SUCCESS; +} + +int rtw_IOL_exec_cmds_sync(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms) +{ + if(adapter->HalFunc.IOL_exec_cmds_sync) + return adapter->HalFunc.IOL_exec_cmds_sync(adapter, xmit_frame, max_wating_ms); + + return _FAIL; +} + +int rtw_IOL_exec_cmd_array_sync(PADAPTER adapter, u8 *IOL_cmds, u32 cmd_num, u32 max_wating_ms) +{ + struct xmit_frame *xmit_frame; + + if((xmit_frame=rtw_IOL_accquire_xmit_frame(adapter)) == NULL) + return _FAIL; + + if(rtw_IOL_append_cmds(xmit_frame, IOL_cmds, cmd_num<<3) == _FAIL) + return _FAIL; + + return rtw_IOL_exec_cmds_sync(adapter, xmit_frame, max_wating_ms); +} + +int rtw_IOL_exec_empty_cmds_sync(ADAPTER *adapter, u32 max_wating_ms) +{ + IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0}; + return rtw_IOL_exec_cmd_array_sync(adapter, (u8*)&end_cmd, 1, max_wating_ms); +} + +bool rtw_IOL_applied(ADAPTER *adapter) +{ + if(adapter->registrypriv.force_iol) + return _TRUE; + +#ifdef CONFIG_USB_HCI + if(!adapter->dvobjpriv.ishighspeed) + return _TRUE; +#endif + + return _FALSE; +} + +#endif //CONFIG_IOL + |