#define _RTL8712_XMIT_C_
#include "osdep_service.h"
#include "drv_types.h"
#include "wifi.h"
#include "osdep_intf.h"
#include "usb_ops.h"
static void dump_xframe(struct _adapter *padapter,
struct xmit_frame *pxmitframe);
static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz);
sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag)
{ … }
int r8712_txframes_sta_ac_pending(struct _adapter *padapter,
struct pkt_attrib *pattrib)
{ … }
static u32 get_ff_hwaddr(struct xmit_frame *pxmitframe)
{ … }
static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv,
struct hw_xmit *phwxmit, struct tx_servq *ptxservq,
struct __queue *pframe_queue)
{ … }
static struct xmit_frame *dequeue_xframe_ex(struct xmit_priv *pxmitpriv,
struct hw_xmit *phwxmit_i, sint entry)
{ … }
void r8712_do_queue_select(struct _adapter *padapter, struct pkt_attrib *pattrib)
{ … }
#ifdef CONFIG_R8712_TX_AGGR
void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf)
{
struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ & 0xffff);
ptx_desc->txdw0 |=
cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
0x00ff0000);
ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00);
}
void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf)
{
struct xmit_frame *pxmitframe = (struct xmit_frame *)
pxmitbuf->priv_data;
struct _adapter *padapter = pxmitframe->padapter;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
(pxmitbuf->pbuf + TXDESC_SIZE);
pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) |
(pcmdpriv->cmd_seq << 24));
pcmdpriv->cmd_seq++;
}
void r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf,
struct xmit_frame *pxmitframe)
{
struct _adapter *padapter = pxmitframe->padapter;
struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
int last_txcmdsz = 0;
int padding_sz = 0;
r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
r8712_xmit_complete(padapter, pxmitframe);
if (pxmitframe->attrib.ether_type != 0x0806) {
if ((pxmitframe->attrib.ether_type != 0x888e) &&
(pxmitframe->attrib.dhcp_pkt != 1)) {
r8712_issue_addbareq_cmd(padapter, pxmitframe->attrib.priority);
}
}
pxmitframe->last[0] = 1;
update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr), pxmitframe->attrib.last_txcmdsz);
last_txcmdsz = pxmitframe->attrib.last_txcmdsz;
padding_sz = (8 - (last_txcmdsz % 8));
if ((last_txcmdsz % 8) != 0) {
int i;
for (i = 0; i < padding_sz; i++)
*(pxmitframe->buf_addr + TXDESC_SIZE + last_txcmdsz +
i) = 0;
}
ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0 & 0xffff0000) |
((ptx_desc->txdw0 & 0x0000ffff) +
((TXDESC_SIZE + last_txcmdsz + padding_sz) &
0x0000ffff)));
}
void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
struct xmit_frame *pxmitframe)
{
pxmitframe->pxmitbuf = pxmitbuf;
pxmitbuf->priv_data = pxmitframe;
pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + CMD_HDR_SZ;
r8712_construct_txaggr_cmd_desc(pxmitbuf);
r8712_construct_txaggr_cmd_hdr(pxmitbuf);
r8712_append_mpdu_unit(pxmitbuf, pxmitframe);
pxmitbuf->aggr_nr = 1;
}
u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, struct xmit_frame *pxmitframe)
{
pxmitframe->pxmitbuf = pxmitbuf;
pxmitbuf->priv_data = pxmitframe;
pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE +
(((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
r8712_append_mpdu_unit(pxmitbuf, pxmitframe);
r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv,
pxmitframe);
pxmitbuf->aggr_nr++;
return TXDESC_SIZE +
(((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
}
void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
struct xmit_frame *pxmitframe)
{
struct _adapter *padapter = pxmitframe->padapter;
struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
struct tx_desc *ptxdesc = pxmitbuf->pbuf;
struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
(pxmitbuf->pbuf + TXDESC_SIZE);
u16 total_length = (u16)(ptxdesc->txdw0 & 0xffff);
xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length - CMD_HDR_SZ) &
0x0000ffff) | (pcmd_hdr->cmd_dw0 &
0xffff0000));
pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff) |
((total_length + TXDESC_SIZE) << 16));
pxmitframe->last[0] = 1;
pxmitframe->bpending[0] = false;
pxmitframe->mem_addr = pxmitbuf->pbuf;
if ((pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % 0x200) == 0) ||
((!pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) %
0x40) == 0))) {
ptxdesc->txdw0 |= cpu_to_le32
(((TXDESC_SIZE + OFFSET_SZ + 8) << OFFSET_SHT) &
0x00ff0000);
} else {
ptxdesc->txdw0 |= cpu_to_le32
(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
0x00ff0000);
}
r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, total_length + TXDESC_SIZE,
(u8 *)pxmitframe);
}
#endif
static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
{ … }
int r8712_xmitframe_complete(struct _adapter *padapter,
struct xmit_priv *pxmitpriv,
struct xmit_buf *pxmitbuf)
{ … }
static void dump_xframe(struct _adapter *padapter,
struct xmit_frame *pxmitframe)
{ … }
void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe)
{ … }
int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe)
{ … }