Beispiel #1
0
static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size)
{
	u32 readsize, ret;
	u8 *readbuf;
	struct recv_priv *recv_priv;
	struct recv_buf	*recvbuf;


	/*  Patch for some SDIO Host 4 bytes issue */
	/*  ex. RK3188 */
	readsize = RND4(size);

	/* 3 1. alloc recvbuf */
	recv_priv = &adapter->recvpriv;
	recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue);
	if (!recvbuf) {
		DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__);
		return NULL;
	}

	/* 3 2. alloc skb */
	if (!recvbuf->pskb) {
		SIZE_PTR tmpaddr = 0;
		SIZE_PTR alignment = 0;

		recvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);

		if (recvbuf->pskb) {
			recvbuf->pskb->dev = adapter->pnetdev;

			tmpaddr = (SIZE_PTR)recvbuf->pskb->data;
			alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
			skb_reserve(recvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
		}

		if (!recvbuf->pskb) {
			DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, readsize);
			return NULL;
		}
	}

	/* 3 3. read data from rxfifo */
	readbuf = recvbuf->pskb->data;
	ret = sdio_read_port(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, readbuf);
	if (ret == _FAIL) {
		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __func__));
		return NULL;
	}


	/* 3 4. init recvbuf */
	recvbuf->len = size;
	recvbuf->phead = recvbuf->pskb->head;
	recvbuf->pdata = recvbuf->pskb->data;
	skb_set_tail_pointer(recvbuf->pskb, size);
	recvbuf->ptail = skb_tail_pointer(recvbuf->pskb);
	recvbuf->pend = skb_end_pointer(recvbuf->pskb);

	return recvbuf;
}
Beispiel #2
0
/*
 * Todo: align address to 4 bytes.
 */
static s32 _sdio_local_read(
	struct adapter *adapter,
	u32 addr,
	u32 cnt,
	u8 *buf
)
{
	struct intf_hdl *intfhdl;
	u8 mac_pwr_ctrl_on;
	s32 err;
	u8 *tmpbuf;
	u32 n;


	intfhdl = &adapter->iopriv.intf;

	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);

	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
	if (!mac_pwr_ctrl_on)
		return _sd_cmd52_read(intfhdl, addr, cnt, buf);

	n = RND4(cnt);
	tmpbuf = rtw_malloc(n);
	if (!tmpbuf)
		return (-1);

	err = _sd_read(intfhdl, addr, n, tmpbuf);
	if (!err)
		memcpy(buf, tmpbuf, cnt);

	kfree(tmpbuf);

	return err;
}
Beispiel #3
0
/*
 * Todo: align address to 4 bytes.
 */
s32 sdio_local_read(
	PADAPTER	padapter,
	u32			addr,
	u32			cnt,
	u8			*pbuf)
{
	PSDIO_DATA psdio;
	u8 bMacPwrCtrlOn;
	s32 err;
	u8 *ptmpbuf;
	u32 n;


	psdio = &adapter_to_dvobj(padapter)->intf_data;

	HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);

	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
	if ((_FALSE == bMacPwrCtrlOn)
#ifdef CONFIG_LPS_LCLK
		|| (_TRUE == padapter->pwrctrlpriv.bFwCurrentInPSMode)
#endif
		)
	{
		err = sd_cmd52_read(psdio, addr, cnt, pbuf);
		return err;
	}

	n = RND4(cnt);
	ptmpbuf = (u8*)rtw_malloc(n);
	if (!ptmpbuf)
		return (-1);

	err = sd_read(psdio, addr, n, ptmpbuf);
	if (!err)
		_rtw_memcpy(pbuf, ptmpbuf, cnt);

	if (ptmpbuf)
		rtw_mfree(ptmpbuf, n);

	return err;
}
Beispiel #4
0
/*
 * Todo: align address to 4 bytes.
 */
s32 _sdio_local_read(
	PADAPTER	padapter,
	u32		addr,
	u32		cnt,
	u8		*pbuf)
{
	struct intf_hdl * pintfhdl;
	u8 bMacPwrCtrlOn;
	s32 err;
	u8 *ptmpbuf;
	u32 n;

	pintfhdl=&padapter->iopriv.intf;

	HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);

	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
	if ((_FALSE == bMacPwrCtrlOn)
#ifdef CONFIG_LPS_LCLK
//		|| (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
#endif
		)
	{
		err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
		return err;
	}

        n = RND4(cnt);
	ptmpbuf = (u8*)rtw_malloc(n);
	if(!ptmpbuf)
		return (-1);

	err = _sd_read(pintfhdl, addr, n, ptmpbuf);
	if (!err)
		_rtw_memcpy(pbuf, ptmpbuf, cnt);

	if(ptmpbuf)
		rtw_mfree(ptmpbuf, n);

	return err;
}
Beispiel #5
0
/*
 * Todo: align address to 4 bytes.
 */
s32 _sdio_local_read(
	PADAPTER	padapter,
	u32			addr,
	u32			cnt,
	u8			*pbuf)
{
	struct intf_hdl * pintfhdl;
	u8 bMacPwrCtrlOn;
	s32 err;
	u8 *ptmpbuf;
	u32 n;


	pintfhdl=&padapter->iopriv.intf;

	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);

	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
	if (_FALSE == bMacPwrCtrlOn)
	{
		err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
		return err;
	}

	n = RND4(cnt);
	ptmpbuf = (u8*)rtw_malloc(n);
	if (!ptmpbuf)
		return (-1);

	err = _sd_read(pintfhdl, addr, n, ptmpbuf);
	if (!err)
		_rtw_memcpy(pbuf, ptmpbuf, cnt);

	if (ptmpbuf)
		rtw_mfree(ptmpbuf, n);

	return err;
}
Beispiel #6
0
/*
 * Todo: align address to 4 bytes.
 */
s32 _sdio_local_read(
	PADAPTER	padapter,
	u32			addr,
	u32			cnt,
	u8			*pbuf)
{
	PSDIO_DATA psdio;
	u8 bMacPwrCtrlOn;
	s32 err;
	u8 *ptmpbuf;
	u32 n;


	psdio = &adapter_to_dvobj(padapter)->intf_data;

	HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);

	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
	if (_FALSE == bMacPwrCtrlOn)
	{
		err = _sd_cmd52_read(psdio, addr, cnt, pbuf);
		return err;
	}

	n = RND4(cnt);
	ptmpbuf = (u8*)rtw_malloc(n);
	if (!ptmpbuf)
		return (-1);

	err = _sd_read(psdio, addr, n, ptmpbuf);
	if (!err)
		_rtw_memcpy(pbuf, ptmpbuf, cnt);

	if (ptmpbuf)
		rtw_mfree(ptmpbuf, n);

	return err;
}
//for non-agg data frame or  management frame
static s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe)
{
	s32 ret = _SUCCESS;
	s32 inner_ret = _SUCCESS;
	int t, sz, w_sz, pull=0;
	u8 *mem_addr;
	u32 ff_hwaddr;
	struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
	struct pkt_attrib *pattrib = &pxmitframe->attrib;
	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
	struct security_priv *psecuritypriv = &padapter->securitypriv;
#ifdef CONFIG_80211N_HT
	if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
	    (pxmitframe->attrib.ether_type != 0x0806) &&
	    (pxmitframe->attrib.ether_type != 0x888e) &&
	    (pxmitframe->attrib.ether_type != 0x88b4) &&
	    (pxmitframe->attrib.dhcp_pkt != 1))
	{
		rtw_issue_addbareq_cmd(padapter, pxmitframe);
	}
#endif //CONFIG_80211N_HT
	mem_addr = pxmitframe->buf_addr;

       RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_dump_xframe()\n"));
	
	for (t = 0; t < pattrib->nr_frags; t++)
	{
		if (inner_ret != _SUCCESS && ret == _SUCCESS)
			ret = _FAIL;
			
		if (t != (pattrib->nr_frags - 1))
		{
			RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("pattrib->nr_frags=%d\n", pattrib->nr_frags));

			sz = pxmitpriv->frag_len;
			sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);					
		}
		else //no frag
		{
			sz = pattrib->last_txcmdsz;
		}

		pull = update_txdesc(pxmitframe, mem_addr, sz, _FALSE);
             
		if(pull)
		{
			mem_addr += PACKET_OFFSET_SZ; //pull txdesc head
			
			//pxmitbuf ->pbuf = mem_addr;			
			pxmitframe->buf_addr = mem_addr;

			w_sz = sz + TXDESC_SIZE;
		}
		else
		{
			w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
		}	

		ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);

#ifdef CONFIG_XMIT_THREAD_MODE
		pxmitbuf->len = w_sz;
		pxmitbuf->ff_hwaddr = ff_hwaddr;
		enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
#else
		inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, (unsigned char*)pxmitbuf);
#endif
		rtw_count_tx_stats(padapter, pxmitframe, sz);

		RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_write_port, w_sz=%d\n", w_sz));
		//DBG_8192C("rtw_write_port, w_sz=%d, sz=%d, txdesc_sz=%d, tid=%d\n", w_sz, sz, w_sz-sz, pattrib->priority);      

		mem_addr += w_sz;

		mem_addr = (u8 *)RND4(((SIZE_PTR)(mem_addr)));

	}
	
	rtw_free_xmitframe(pxmitpriv, pxmitframe);
	
	if  (ret != _SUCCESS)
		rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
	
	return ret;
}
Beispiel #8
0
/* for non-agg data frame or  management frame */
static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
{
	s32 ret = _SUCCESS;
	s32 inner_ret = _SUCCESS;
	int t, sz, w_sz, pull = 0;
	u8 *mem_addr;
	u32 ff_hwaddr;
	struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
	struct pkt_attrib *pattrib = &pxmitframe->attrib;
	struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
	struct security_priv *psecuritypriv = &adapt->securitypriv;
	if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
	    (pxmitframe->attrib.ether_type != 0x0806) &&
	    (pxmitframe->attrib.ether_type != 0x888e) &&
	    (pxmitframe->attrib.ether_type != 0x88b4) &&
	    (pxmitframe->attrib.dhcp_pkt != 1))
		rtw_issue_addbareq_cmd(adapt, pxmitframe);
	mem_addr = pxmitframe->buf_addr;

	RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));

	for (t = 0; t < pattrib->nr_frags; t++) {
		if (inner_ret != _SUCCESS && ret == _SUCCESS)
			ret = _FAIL;

		if (t != (pattrib->nr_frags - 1)) {
			RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("pattrib->nr_frags=%d\n", pattrib->nr_frags));

			sz = pxmitpriv->frag_len;
			sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);
		} else {
			/* no frag */
			sz = pattrib->last_txcmdsz;
		}

		pull = update_txdesc(pxmitframe, mem_addr, sz, false);

		if (pull) {
			mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */
			pxmitframe->buf_addr = mem_addr;
			w_sz = sz + TXDESC_SIZE;
		} else {
			w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
		}
		ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);

		inner_ret = rtw_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf);

		rtw_count_tx_stats(adapt, pxmitframe, sz);

		RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_write_port, w_sz=%d\n", w_sz));

		mem_addr += w_sz;

		mem_addr = (u8 *)RND4(((size_t)(mem_addr)));
	}

	rtw_free_xmitframe(pxmitpriv, pxmitframe);

	if  (ret != _SUCCESS)
		rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);

	return ret;
}
Beispiel #9
0
static struct recv_buf* sd_recv_rxfifo(PADAPTER padapter, u32 size)
{
	u32 sdioblksize, readsize, allocsize, ret;
	u8 *preadbuf;
	_pkt *ppkt;
	struct recv_priv *precvpriv;
	struct recv_buf	*precvbuf;


	sdioblksize = adapter_to_dvobj(padapter)->intf_data.block_transfer_len;
#if 0
	readsize = size;
#else
	// Patch for some SDIO Host 4 bytes issue
	// ex. RK3188
	readsize = RND4(size);
#endif

	//3 1. alloc skb
	// align to block size
	if (readsize > sdioblksize)
		allocsize = _RND(readsize, sdioblksize);
	else
		allocsize = readsize;

	ppkt = rtw_skb_alloc(allocsize);

	if (ppkt == NULL) {
		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc_skb fail! alloc=%d read=%d\n", __FUNCTION__, allocsize, readsize));
		return NULL;
	}

	//3 2. read data from rxfifo
	preadbuf = skb_put(ppkt, size);
//	rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
	ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
	if (ret == _FAIL) {
		rtw_skb_free(ppkt);
		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __FUNCTION__));
		return NULL;
	}

	//3 3. alloc recvbuf
	precvpriv = &padapter->recvpriv;
	precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
	if (precvbuf == NULL) {
		rtw_skb_free(ppkt);
		DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __FUNCTION__);
		return NULL;
	}

	//3 4. init recvbuf
	precvbuf->pskb = ppkt;

	precvbuf->len = ppkt->len;

	precvbuf->phead = ppkt->head;
	precvbuf->pdata = ppkt->data;
	precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
	precvbuf->pend = skb_end_pointer(precvbuf->pskb);

	return precvbuf;
}
Beispiel #10
0
static struct recv_buf* sd_recv_rxfifo(PADAPTER padapter, u32 size)
{
	u32 readsize, ret;
	u8 *preadbuf;
	struct recv_priv *precvpriv;
	struct recv_buf	*precvbuf;


#if 0
	readsize = size;
#else
	// Patch for some SDIO Host 4 bytes issue
	// ex. RK3188
	readsize = RND4(size);
#endif

	//3 1. alloc recvbuf
	precvpriv = &padapter->recvpriv;
	precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
	if (precvbuf == NULL) {
		DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __FUNCTION__);
		return NULL;
	}

	//3 2. alloc skb
	if (precvbuf->pskb == NULL) {
		SIZE_PTR tmpaddr=0;
		SIZE_PTR alignment=0;

		precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);

		if(precvbuf->pskb)
		{
			precvbuf->pskb->dev = padapter->pnetdev;

			tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
			alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
			skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
		}

		if (precvbuf->pskb == NULL) {
			DBG_871X("%s: alloc_skb fail! read=%d\n", __FUNCTION__, readsize);
			return NULL;
		}
	}

	//3 3. read data from rxfifo
	preadbuf = precvbuf->pskb->data;
//	rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
	ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
	if (ret == _FAIL) {
		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __FUNCTION__));
		return NULL;
	}


	//3 4. init recvbuf
	precvbuf->len = size;
	precvbuf->phead = precvbuf->pskb->head;
	precvbuf->pdata = precvbuf->pskb->data;
	skb_set_tail_pointer(precvbuf->pskb, size);
	precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
	precvbuf->pend = skb_end_pointer(precvbuf->pskb);

	return precvbuf;
}
Beispiel #11
0
s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe)
{
	s32 ret = _SUCCESS;
	s32 inner_ret = _SUCCESS;
	int t, sz, w_sz, pull=0;
	u8 *mem_addr;
	u32 ff_hwaddr;
	struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
	struct pkt_attrib *pattrib = &pxmitframe->attrib;
	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
	struct security_priv *psecuritypriv = &padapter->securitypriv;
#ifdef CONFIG_TDLS
	struct sta_priv 	*pstapriv = &padapter->stapriv;
	struct sta_info *ptdls_sta=NULL, *psta_backup=NULL;
	u8 ra_backup[6];
#endif //CONFIG_TDLS

	if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
	    (pxmitframe->attrib.ether_type != 0x0806) &&
	    (pxmitframe->attrib.ether_type != 0x888e) &&
	    (pxmitframe->attrib.dhcp_pkt != 1))
	{
#ifdef CONFIG_TDLS
		ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
		if((ptdls_sta!=NULL)&&(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
		{
			psta_backup = pattrib->psta;
			pattrib->psta = ptdls_sta;
			_rtw_memcpy(ra_backup, pattrib->ra, ETH_ALEN);
			_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
			rtw_issue_addbareq_cmd(padapter, pxmitframe);
			pattrib->psta = psta_backup;
			_rtw_memcpy(pattrib->ra, ra_backup, ETH_ALEN);
		}
#endif //CONFIG_TDLS
		rtw_issue_addbareq_cmd(padapter, pxmitframe);
	}

	mem_addr = pxmitframe->buf_addr;

       RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_dump_xframe()\n"));
	
	for (t = 0; t < pattrib->nr_frags; t++)
	{
		if (inner_ret != _SUCCESS && ret == _SUCCESS)
			ret = _FAIL;

		if (t != (pattrib->nr_frags - 1))
		{
			RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("pattrib->nr_frags=%d\n", pattrib->nr_frags));

			sz = pxmitpriv->frag_len;
			sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);					
		}
		else //no frag
		{
			sz = pattrib->last_txcmdsz;
		}

		pull = update_txdesc(pxmitframe, mem_addr, sz, _FALSE);
		
		if(pull)
		{
			mem_addr += PACKET_OFFSET_SZ; //pull txdesc head
			
			//pxmitbuf ->pbuf = mem_addr;			
			pxmitframe->buf_addr = mem_addr;

			w_sz = sz + TXDESC_SIZE;
		}
		else
		{
			w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
		}	

		ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);

		inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, (unsigned char*)pxmitbuf);

		rtw_count_tx_stats(padapter, pxmitframe, sz);


		RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_write_port, w_sz=%d\n", w_sz));
		//DBG_8192C("rtw_write_port, w_sz=%d, sz=%d, txdesc_sz=%d, tid=%d\n", w_sz, sz, w_sz-sz, pattrib->priority);      

		mem_addr += w_sz;

		mem_addr = (u8 *)RND4(((SIZE_PTR)(mem_addr)));

	}
	
	rtw_free_xmitframe(pxmitpriv, pxmitframe);

	if  (ret != _SUCCESS)
		rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);

	return ret;
}
Beispiel #12
0
/*
 * This sub-routine will perform all the following:
 * 1. remove 802.3 header.
 * 2. create wlan_header, based on the info in pxmitframe
 * 3. append sta's iv/ext-iv
 * 4. append LLC
 * 5. move frag chunk from pframe to pxmitframe->mem
 * 6. apply sw-encrypt, if necessary.
 */
sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
			struct xmit_frame *pxmitframe)
{
	struct pkt_file pktfile;

	sint	frg_len, mpdu_len, llc_sz;
	u32	mem_sz;
	u8	frg_inx;
	addr_t addr;
	u8 *pframe, *mem_start, *ptxdesc;
	struct sta_info		*psta;
	struct security_priv	*psecuritypriv = &padapter->securitypriv;
	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
	u8 *pbuf_start;
	sint bmcst = IS_MCAST(pattrib->ra);

	if (pattrib->psta == NULL)
		return _FAIL;
	psta = pattrib->psta;
	if (pxmitframe->buf_addr == NULL)
		return _FAIL;
	pbuf_start = pxmitframe->buf_addr;
	ptxdesc = pbuf_start;
	mem_start = pbuf_start + TXDESC_OFFSET;
	if (make_wlanhdr(padapter, mem_start, pattrib) == _FAIL)
		return _FAIL;
	_r8712_open_pktfile(pkt, &pktfile);
	_r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen);
	if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
		/* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
		if (pattrib->ether_type == 0x8712) {
			/* take care -  update_txdesc overwrite this */
			_r8712_pktfile_read(&pktfile, ptxdesc, TXDESC_SIZE);
		}
	}
	pattrib->pktlen = pktfile.pkt_len;
	frg_inx = 0;
	frg_len = pxmitpriv->frag_len - 4;
	while (1) {
		llc_sz = 0;
		mpdu_len = frg_len;
		pframe = mem_start;
		SetMFrag(mem_start);
		pframe += pattrib->hdrlen;
		mpdu_len -= pattrib->hdrlen;
		/* adding icv, if necessary...*/
		if (pattrib->iv_len) {
			if (psta != NULL) {
				switch (pattrib->encrypt) {
				case _WEP40_:
				case _WEP104_:
					WEP_IV(pattrib->iv, psta->txpn,
					       (u8)psecuritypriv->
					       PrivacyKeyIndex);
					break;
				case _TKIP_:
					if (bmcst)
						TKIP_IV(pattrib->iv,
						    psta->txpn,
						    (u8)psecuritypriv->
						    XGrpKeyid);
					else
						TKIP_IV(pattrib->iv, psta->txpn,
							0);
					break;
				case _AES_:
					if (bmcst)
						AES_IV(pattrib->iv, psta->txpn,
						    (u8)psecuritypriv->
						    XGrpKeyid);
					else
						AES_IV(pattrib->iv, psta->txpn,
						       0);
					break;
				}
			}
			memcpy(pframe, pattrib->iv, pattrib->iv_len);
			pframe += pattrib->iv_len;
			mpdu_len -= pattrib->iv_len;
		}
		if (frg_inx == 0) {
			llc_sz = r8712_put_snap(pframe, pattrib->ether_type);
			pframe += llc_sz;
			mpdu_len -= llc_sz;
		}
		if ((pattrib->icv_len > 0) && (pattrib->bswenc))
			mpdu_len -= pattrib->icv_len;
		if (bmcst)
			mem_sz = _r8712_pktfile_read(&pktfile, pframe,
				 pattrib->pktlen);
		else
			mem_sz = _r8712_pktfile_read(&pktfile, pframe,
				 mpdu_len);
		pframe += mem_sz;
		if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
			memcpy(pframe, pattrib->icv, pattrib->icv_len);
			pframe += pattrib->icv_len;
		}
		frg_inx++;
		if (bmcst || r8712_endofpktfile(&pktfile)) {
			pattrib->nr_frags = frg_inx;
			pattrib->last_txcmdsz = pattrib->hdrlen +
						pattrib->iv_len +
						((pattrib->nr_frags == 1) ?
						llc_sz : 0) +
						((pattrib->bswenc) ?
						pattrib->icv_len : 0) + mem_sz;
			ClearMFrag(mem_start);
			break;
		}
		addr = (addr_t)(pframe);
		mem_start = (unsigned char *)RND4(addr) + TXDESC_OFFSET;
		memcpy(mem_start, pbuf_start + TXDESC_OFFSET, pattrib->hdrlen);
	}

	if (xmitframe_addmic(padapter, pxmitframe) == _FAIL)
		return _FAIL;
	xmitframe_swencrypt(padapter, pxmitframe);
	return _SUCCESS;
}
Beispiel #13
0
static sint xmitframe_addmic(struct _adapter *padapter,
			     struct xmit_frame *pxmitframe)
{
	u32	curfragnum, length;
	u8	*pframe, *payload, mic[8];
	struct	mic_data micdata;
	struct	sta_info *stainfo;
	struct	qos_priv *pqospriv = &(padapter->mlmepriv.qospriv);
	struct	pkt_attrib  *pattrib = &pxmitframe->attrib;
	struct	security_priv *psecuritypriv = &padapter->securitypriv;
	struct	xmit_priv *pxmitpriv = &padapter->xmitpriv;
	u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
	sint bmcst = IS_MCAST(pattrib->ra);

	if (pattrib->psta)
		stainfo = pattrib->psta;
	else
		stainfo = r8712_get_stainfo(&padapter->stapriv,
					    &pattrib->ra[0]);
	if (pattrib->encrypt == _TKIP_) {
		/*encode mic code*/
		if (stainfo != NULL) {
			u8 null_key[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
					   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
					   0x0, 0x0};
			pframe = pxmitframe->buf_addr + TXDESC_OFFSET;
			if (bmcst) {
				if (!memcmp(psecuritypriv->XGrptxmickey
				   [psecuritypriv->XGrpKeyid].skey,
				   null_key, 16))
					return _FAIL;
				/*start to calculate the mic code*/
				r8712_secmicsetkey(&micdata,
					 psecuritypriv->
					 XGrptxmickey[psecuritypriv->
					XGrpKeyid].skey);
			} else {
				if (!memcmp(&stainfo->tkiptxmickey.skey[0],
					    null_key, 16))
					return _FAIL;
				/* start to calculate the mic code */
				r8712_secmicsetkey(&micdata,
					     &stainfo->tkiptxmickey.skey[0]);
			}
			if (pframe[1] & 1) {   /* ToDS==1 */
				r8712_secmicappend(&micdata,
						   &pframe[16], 6); /*DA*/
				if (pframe[1] & 2)  /* From Ds==1 */
					r8712_secmicappend(&micdata,
							   &pframe[24], 6);
				else
					r8712_secmicappend(&micdata,
							   &pframe[10], 6);
			} else {	/* ToDS==0 */
				r8712_secmicappend(&micdata,
						   &pframe[4], 6); /* DA */
				if (pframe[1] & 2)  /* From Ds==1 */
					r8712_secmicappend(&micdata,
							   &pframe[16], 6);
				else
					r8712_secmicappend(&micdata,
							   &pframe[10], 6);
			}
			if (pqospriv->qos_option == 1)
				priority[0] = (u8)pxmitframe->attrib.priority;
			r8712_secmicappend(&micdata, &priority[0], 4);
			payload = pframe;
			for (curfragnum = 0; curfragnum < pattrib->nr_frags;
			     curfragnum++) {
				payload = (u8 *)RND4((addr_t)(payload));
				payload += pattrib->hdrlen + pattrib->iv_len;
				if ((curfragnum + 1) == pattrib->nr_frags) {
					length = pattrib->last_txcmdsz -
						  pattrib->hdrlen -
						  pattrib->iv_len -
						  ((psecuritypriv->sw_encrypt)
						  ? pattrib->icv_len : 0);
					r8712_secmicappend(&micdata, payload,
							   length);
					payload = payload + length;
				} else {
					length = pxmitpriv->frag_len -
					    pattrib->hdrlen - pattrib->iv_len -
					    ((psecuritypriv->sw_encrypt) ?
					    pattrib->icv_len : 0);
					r8712_secmicappend(&micdata, payload,
							   length);
					payload = payload + length +
						  pattrib->icv_len;
				}
			}
			r8712_secgetmic(&micdata, &(mic[0]));
			/* add mic code  and add the mic code length in
			 * last_txcmdsz
			 */
			memcpy(payload, &(mic[0]), 8);
			pattrib->last_txcmdsz += 8;
			payload = payload - pattrib->last_txcmdsz + 8;
		}
	}
	return _SUCCESS;
}