static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen, u32 cmd_num, u32 *pelement_id, u32 *pcmd_len, u8 **pcmb_buffer, u8 *cmd_start_seq) { u32 totallen = 0, len = 0, tx_desclen = 0; u32 pre_continueoffset = 0; u8 *ph2c_buffer; u8 i = 0; do { /* 8 - Byte aligment */ len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); /* Buffer length is not enough */ if (h2cbufferlen < totallen + len + tx_desclen) break; /* Clear content */ ph2c_buffer = (u8 *) skb_put(skb, (u32)len); memset((ph2c_buffer + totallen + tx_desclen), 0, len); /* CMD len */ SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), 0, 16, pcmd_len[i]); /* CMD ID */ SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), 16, 8, pelement_id[i]); /* CMD Sequence */ *cmd_start_seq = *cmd_start_seq % 0x80; SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), 24, 7, *cmd_start_seq); ++*cmd_start_seq; /* Copy memory */ memcpy((ph2c_buffer + totallen + tx_desclen + H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]); /* CMD continue */ /* set the continue in prevoius cmd. */ if (i < cmd_num - 1) SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset), 31, 1, 1); pre_continueoffset = totallen; totallen += len; } while (++i < cmd_num); return totallen; }
u32 FillH2CCmd( struct sk_buff *skb, u32 H2CBufferLen, u32 CmdNum, u32* pElementID, u32* pCmdLen, u8** pCmbBuffer, u8* CmdStartSeq ) { u8 i = 0; u32 TotalLen = 0, Len = 0, TxDescLen = 0; u32 preContinueOffset = 0; u8* pH2CBuffer; do { Len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pCmdLen[i], 8); if(H2CBufferLen < TotalLen + Len + TxDescLen) break; pH2CBuffer = (u8 *) skb_put(skb, (u32)Len); memset((pH2CBuffer + TotalLen + TxDescLen),0,Len); SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 0, 16, pCmdLen[i]); SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 16, 8, pElementID[i]); *CmdStartSeq = *CmdStartSeq % 0x80; SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 24, 7, *CmdStartSeq); ++ *CmdStartSeq; memcpy((pH2CBuffer + TotalLen + TxDescLen + H2C_TX_CMD_HDR_LEN), pCmbBuffer[i], pCmdLen[i]); if(i < CmdNum - 1) SET_BITS_TO_LE_4BYTE((pH2CBuffer + preContinueOffset), 31, 1, 1); preContinueOffset = TotalLen; TotalLen += Len; }while(++ i < CmdNum); return TotalLen; }
void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, bool lastseg, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "DMA mapping error\n"); return; } /* Clear all status */ CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); /* This bit indicate this packet is used for FW download. */ if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) { /* For firmware downlaod we only need to set LINIP */ SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt); /* 92SE must set as 1 for firmware download HW DMA error */ SET_TX_DESC_FIRST_SEG(pdesc, 1); SET_TX_DESC_LAST_SEG(pdesc, 1); /* 92SE need not to set TX packet size when firmware download */ SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); wmb(); SET_TX_DESC_OWN(pdesc, 1); } else { /* H2C Command Desc format (Host TXCMD) */ /* 92SE must set as 1 for firmware download HW DMA error */ SET_TX_DESC_FIRST_SEG(pdesc, 1); SET_TX_DESC_LAST_SEG(pdesc, 1); SET_TX_DESC_OFFSET(pdesc, 0x20); /* Buffer size + command header */ SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); /* Fixed queue of H2C command */ SET_TX_DESC_QUEUE_SEL(pdesc, 0x13); SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq); SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); wmb(); SET_TX_DESC_OWN(pdesc, 1); } }