USHORT RtmpUSB_WriteFragTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN TxQLastRound = FALSE; QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if(fragNum == 0) { Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } else { Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE , FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->USBDMATxburst = 0; if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; TxQLastRound = TRUE; } } else { pTxInfo->USBDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext->CurWritePosition += pTxBlk->Priv; if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return(Status); }
u16 RtmpUSB_WriteFragTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, u8 fragNum, u16 * FreeNumber) { struct rt_ht_tx_context *pHTTXContext; u16 hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */ u32 fillOffset; struct rt_txinfo *pTxInfo; struct rt_txwi *pTxWI; u8 *pWirelessPacket = NULL; u8 QueIdx; int Status; unsigned long IrqFlags; u32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN TxQLastRound = FALSE; /* */ /* get Tx Ring Resource & Dma Buffer address */ /* */ QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if (fragNum == 0) { /* Check if we have enough space for this bulk-out batch. */ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; /* Reserve space for 8 bytes padding. */ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return (Status); } } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return (Status); } } NdisZeroMemory((u8 *)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Build our URB for USBD */ DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */ RTMPWriteTxInfo(pAd, pTxInfo, (u16)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid */ , FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->USBDMATxburst = 0; if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906) > MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; TxQLastRound = TRUE; } } else { pTxInfo->USBDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); /* Zero the last padding. */ pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. */ pHTTXContext->CurWritePosition += pTxBlk->Priv; if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; /* Finally, set bCurWriting as FALSE */ pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* succeed and release the skb buffer */ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return (Status); }
USHORT RtmpUSB_WriteMultiTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR frameNum, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if(frameNum == 0) { Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->CurWritePosition += 8; pHTTXContext->ENextBulkOutPosition += 8; } fillOffset = pHTTXContext->CurWritePosition; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE , FALSE); NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); pHTTXContext->CurWriteRealPos += pTxBlk->Priv; pWirelessPacket += pTxBlk->Priv; } } else { Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); pWirelessPacket += (pTxBlk->MpduHeaderLen); pTxBlk->Priv += pTxBlk->MpduHeaderLen; } else { DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); Status = NDIS_STATUS_FAILURE; } } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); goto done; } NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; pTxBlk->Priv += pTxBlk->SrcBufLen; done: RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }
u16 RtmpUSB_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, IN BOOLEAN bIsLast, u16 * FreeNumber) { struct rt_ht_tx_context *pHTTXContext; u16 hwHdrLen; u32 fillOffset; struct rt_txinfo *pTxInfo; struct rt_txwi *pTxWI; u8 *pWirelessPacket; u8 QueIdx; unsigned long IrqFlags; int Status; u32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN bTxQLastRound = FALSE; /* For USB, didn't need PCI_MAP_SINGLE() */ /*SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); */ /* */ /* get Tx Ring Resource & Dma Buffer address */ /* */ QueIdx = pTxBlk->QueIdx; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; /* Check ring full. */ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); /* Reserve space for 8 bytes padding. */ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field. WirelessPacket[fillOffset]; /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Build our URB for USBD */ DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ USBDMApktLen += padding; pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */ RTMPWriteTxInfo(pAd, pTxInfo, (u16)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid */ , FALSE); if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; bTxQLastRound = TRUE; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); /* We unlock it here to prevent the first 8 bytes maybe over-writed issue. */ /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. */ /* 2. An interrupt break our routine and handle bulk-out complete. */ /* 3. In the bulk-out compllete, it need to do another bulk-out, */ /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */ /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */ /* 4. Interrupt complete. */ /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */ /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */ /* and the packet will wrong. */ pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext->CurWritePosition += pTxBlk->Priv; if (bTxQLastRound) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* succeed and release the skb buffer */ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return (Status); }
u16 RtmpUSB_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, u8 frameNum, u16 * FreeNumber) { struct rt_ht_tx_context *pHTTXContext; u16 hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */ u32 fillOffset; struct rt_txinfo *pTxInfo; struct rt_txwi *pTxWI; u8 *pWirelessPacket = NULL; u8 QueIdx; int Status; unsigned long IrqFlags; /*u32 USBDMApktLen = 0, DMAHdrLen, padding; */ /* */ /* get Tx Ring Resource & Dma Buffer address */ /* */ QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (frameNum == 0) { /* Check if we have enough space for this bulk-out batch. */ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); /* Reserve space for 8 bytes padding. */ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->CurWritePosition += 8; pHTTXContext->ENextBulkOutPosition += 8; } fillOffset = pHTTXContext->CurWritePosition; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field. WirelessPacket[fillOffset]; /* */ /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ /* */ if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Update the pTxBlk->Priv. */ pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; /* pTxInfo->USBDMApktLen now just a temp value and will to correct latter. */ RTMPWriteTxInfo(pAd, pTxInfo, (u16)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid */ , FALSE); /* Copy it. */ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); pHTTXContext->CurWriteRealPos += pTxBlk->Priv; pWirelessPacket += pTxBlk->Priv; } } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); pWirelessPacket = &pHTTXContext->TransferBuffer->field. WirelessPacket[fillOffset]; /*hwHdrLen = pTxBlk->MpduHeaderLen; */ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); pWirelessPacket += (pTxBlk->MpduHeaderLen); pTxBlk->Priv += pTxBlk->MpduHeaderLen; } else { /* It should not happened now unless we are going to shutdown. */ DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); Status = NDIS_STATUS_FAILURE; } } /* We unlock it here to prevent the first 8 bytes maybe over-write issue. */ /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. */ /* 2. An interrupt break our routine and handle bulk-out complete. */ /* 3. In the bulk-out compllete, it need to do another bulk-out, */ /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */ /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */ /* 4. Interrupt complete. */ /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */ /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */ /* and the packet will wrong. */ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); goto done; } /* Copy the frame content into DMA buffer and update the pTxBlk->Priv */ NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; pTxBlk->Priv += pTxBlk->SrcBufLen; done: /* Release the skb buffer here */ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return (Status); }
USHORT RtmpUSB_WriteMultiTxResource( IN RTMP_ADAPTER *pAd, IN TX_BLK *pTxBlk, IN UCHAR frmNum, OUT USHORT *freeCnt) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length.*/ UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; UCHAR *pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT8 TXWISize = pAd->chipCap.TXWISize; /* get Tx Ring Resource & Dma Buffer address*/ QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if(frmNum == 0) { /* Check if we have enough space for this bulk-out batch.*/ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (TXINFO_STRUC *)(&pTxBlk->HeaderBuf[0]); pTxWI= (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); #ifndef USB_BULK_BUF_ALIGMENT /* Reserve space for 8 bytes padding.*/ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->CurWritePosition += 8; pHTTXContext->ENextBulkOutPosition += 8; } #endif /* USB_BULK_BUF_ALIGMENT */ fillOffset = pHTTXContext->CurWritePosition; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer*/ if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;*/ hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;*/ hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Update the pTxBlk->Priv.*/ pTxBlk->Priv = TXINFO_SIZE + TXWISize + hwHdrLen; /* pTxInfo->USBDMApktLen now just a temp value and will to correct latter.*/ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); /* Copy it.*/ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket+ TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE); #endif /* RT_BIG_ENDIAN */ pHTTXContext->CurWriteRealPos += pTxBlk->Priv; pWirelessPacket += pTxBlk->Priv; } } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.*/ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /*hwHdrLen = pTxBlk->MpduHeaderLen;*/ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); pWirelessPacket += (pTxBlk->MpduHeaderLen); pTxBlk->Priv += pTxBlk->MpduHeaderLen; } else { /* It should not happened now unless we are going to shutdown.*/ DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); Status = NDIS_STATUS_FAILURE; } } /* We unlock it here to prevent the first 8 bytes maybe over-write issue. 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. 2. An interrupt break our routine and handle bulk-out complete. 3. In the bulk-out compllete, it need to do another bulk-out, if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. 4. Interrupt complete. 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. and the packet will wrong. */ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); goto done; } /* Copy the frame content into DMA buffer and update the pTxBlk->Priv*/ NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; pTxBlk->Priv += pTxBlk->SrcBufLen; done: /* Release the skb buffer here*/ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }
USHORT RtmpUSB_WriteSingleTxResource( IN RTMP_ADAPTER *pAd, IN TX_BLK *pTxBlk, IN BOOLEAN bIsLast, OUT USHORT *freeCnt) { HT_TX_CONTEXT *pHTTXContext; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; UCHAR *pWirelessPacket, *buf; UCHAR QueIdx; unsigned long IrqFlags; NDIS_STATUS Status; UINT32 hdr_copy_len, hdr_len, dma_len = 0, padding; #ifndef USB_BULK_BUF_ALIGMENT BOOLEAN bTxQLastRound = FALSE; #endif /* USB_BULK_BUF_ALIGMENT */ UINT8 TXWISize = pAd->chipCap.TXWISize; /* get Tx Ring Resource & Dma Buffer address*/ QueIdx = pTxBlk->QueIdx; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; /* Check ring full */ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if(Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; buf = &pTxBlk->HeaderBuf[0]; pTxInfo = (TXINFO_STRUC *)buf; pTxWI= (TXWI_STRUC *)&buf[TXINFO_SIZE]; #ifndef USB_BULK_BUF_ALIGMENT /* Reserve space for 8 bytes padding.*/ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } #endif /* USB_BULK_BUF_ALIGMENT */ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /* Build our URB for USBD */ hdr_len = TXWISize + TSO_SIZE + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; hdr_copy_len = TXINFO_SIZE + hdr_len; dma_len = hdr_len + pTxBlk->SrcBufLen; padding = (4 - (dma_len % 4)) & 0x03; /* round up to 4 byte alignment*/ dma_len += padding; pTxBlk->Priv = (TXINFO_SIZE + dma_len); /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + TSO_SIZE + 802.11 header + payload */ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(dma_len), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); #ifndef USB_BULK_BUF_ALIGMENT if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) { pTxInfo->TxInfoSwLstRnd = 1; bTxQLastRound = TRUE; } #endif /* USB_BULK_BUF_ALIGMENT */ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, hdr_copy_len); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWISize + TSO_SIZE), DIR_WRITE, FALSE); #endif /* RT_BIG_ENDIAN */ pWirelessPacket += (hdr_copy_len); /* We unlock it here to prevent the first 8 bytes maybe over-writed issue.*/ /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.*/ /* 2. An interrupt break our routine and handle bulk-out complete.*/ /* 3. In the bulk-out compllete, it need to do another bulk-out, */ /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,*/ /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.*/ /* 4. Interrupt complete.*/ /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.*/ /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.*/ /* and the packet will wrong.*/ pHTTXContext->CurWriteRealPos += hdr_copy_len; #ifndef USB_BULK_BUF_ALIGMENT RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); #endif /* USB_BULK_BUF_ALIGMENT */ #ifdef TX_PKT_SG if (pTxBlk->pkt_info.BufferCount > 1) { INT i, len; void *data; PKT_SG_T *sg = &pTxBlk->pkt_info.sg_list[0]; for (i = 0 ; i < pTxBlk->pkt_info.BufferCount; i++) { data = sg[i].data; len = sg[i].len; if (i == 0) { len -= ((ULONG)pTxBlk->pSrcBufData - (ULONG)sg[i].data); data = pTxBlk->pSrcBufData; } //DBGPRINT(RT_DEBUG_TRACE, ("%s:sg[%d]=0x%x, len=%d\n", __FUNCTION__, i, data, len)); if (len <= 0) { DBGPRINT(RT_DEBUG_ERROR, ("%s():sg[%d] info error, sg.data=0x%x, sg.len=%d, pTxBlk->pSrcBufData=0x%x, pTxBlk->SrcBufLen=%d, data=0x%x, len=%d\n", __FUNCTION__, i, sg[i].data, sg[i].len, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, data, len)); break; } NdisMoveMemory(pWirelessPacket, data, len); pWirelessPacket += len; } } else #endif /* TX_PKT_SG */ { NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; } #ifndef USB_BULK_BUF_ALIGMENT NdisZeroMemory(pWirelessPacket, padding + 8); RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); #endif /* USB_BULK_BUF_ALIGMENT */ pHTTXContext->CurWritePosition += pTxBlk->Priv; #ifdef UAPSD_SUPPORT #endif /* UAPSD_SUPPORT */ #ifdef USB_BULK_BUF_ALIGMENT /* when CurWritePosition > 0x6000 mean that it is at the max bulk out size, we CurWriteIdx must move to the next alignment section. Otherwirse, CurWriteIdx will be moved to the next section at databulkout. Writingflag = TRUE ,mean that when we writing resource ,and databulkout happen, So we bulk out when this packet finish. */ if ( (pHTTXContext->CurWritePosition & 0x00006000) == 0x00006000) { pHTTXContext->CurWritePosition = ((CUR_WRITE_IDX_INC(pHTTXContext->CurWriteIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000); } #else if (bTxQLastRound) pHTTXContext->CurWritePosition = 8; #endif /* USB_BULK_BUF_ALIGMENT */ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* succeed and release the skb buffer*/ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }
USHORT RtmpUSB_WriteFragTxResource( IN RTMP_ADAPTER *pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *freeCnt) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length.*/ UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; #ifdef USB_BULK_BUF_ALIGMENT BOOLEAN bLasAlignmentsectiontRound = FALSE; #else BOOLEAN TxQLastRound = FALSE; #endif /* USB_BULK_BUF_ALIGMENT */ UINT8 TXWISize = pAd->chipCap.TXWISize; /* get Tx Ring Resource & Dma Buffer address*/ QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if(fragNum == 0) { /* Check if we have enough space for this bulk-out batch.*/ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; #ifndef USB_BULK_BUF_ALIGMENT /* Reserve space for 8 bytes padding.*/ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } #endif /* USB_BULK_BUF_ALIGMENT */ pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.*/ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (TXINFO_STRUC *)(&pTxBlk->HeaderBuf[0]); pTxWI= (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /* copy TXWI + WLAN Header + LLC into DMA Header Buffer*/ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Build our URB for USBD*/ DMAHdrLen = TXWISize + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment*/ USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload*/ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->TxInfoUDMATxburst = 0; #ifdef USB_BULK_BUF_ALIGMENT /* when CurWritePosition > 0x6000 mean that it is at the max bulk out size, we CurWriteIdx must move to the next alignment section. Otherwirse, CurWriteIdx will be moved to the next section at databulkout. (((pHTTXContext->CurWritePosition + 3906)& 0x00007fff) & 0xffff6000) == 0x00006000) we must make sure that the last fragNun packet just over the 0x6000 otherwise it will error because the last frag packet will at the section but will not bulk out. ex: when secoend packet writeresouce and it > 0x6000 And the last packet writesource and it also > 0x6000 at this time CurWriteIdx++ but when data bulk out , because at second packet it will > 0x6000 , the last packet will not bulk out. */ if ( ((pHTTXContext->CurWritePosition + 3906) & 0x00006000) == 0x00006000) { bLasAlignmentsectiontRound = TRUE; pTxInfo->bFragLasAlignmentsectiontRound = 1; } #else if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) { pTxInfo->TxInfoSwLstRnd = 1; TxQLastRound = TRUE; } #endif /* USB_BULK_BUF_ALIGMENT */ } else { pTxInfo->TxInfoUDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWISize + hwHdrLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE); #endif /* RT_BIG_ENDIAN */ pWirelessPacket += (TXINFO_SIZE + TXWISize + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWISize + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); /* Zero the last padding.*/ pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame.*/ pHTTXContext->CurWritePosition += pTxBlk->Priv; #ifndef USB_BULK_BUF_ALIGMENT if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; #endif /* USB_BULK_BUF_ALIGMENT */ #ifdef USB_BULK_BUF_ALIGMENT if(bLasAlignmentsectiontRound == TRUE) { pHTTXContext->CurWritePosition = ((CUR_WRITE_IDX_INC(pHTTXContext->CurWriteIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000); } #endif /* USB_BULK_BUF_ALIGMENT */ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; #ifdef UAPSD_SUPPORT #endif /* UAPSD_SUPPORT */ /* Finally, set bCurWriting as FALSE*/ pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* succeed and release the skb buffer*/ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return(Status); }
USHORT RtmpUSB_WriteFragTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length. UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN TxQLastRound = FALSE; // // get Tx Ring Resource & Dma Buffer address // QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if(fragNum == 0) { // Check if we have enough space for this bulk-out batch. Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; // Reserve space for 8 bytes padding. if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } else { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; // copy TXWI + WLAN Header + LLC into DMA Header Buffer //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; // Build our URB for USBD DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->USBDMATxburst = 0; if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; TxQLastRound = TRUE; } } else { pTxInfo->USBDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); #endif // RT_BIG_ENDIAN // pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); // Zero the last padding. pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. pHTTXContext->CurWritePosition += pTxBlk->Priv; if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; // Finally, set bCurWriting as FALSE pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // succeed and release the skb buffer RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return(Status); }
USHORT RtmpUSB_WriteSingleTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN BOOLEAN bIsLast, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket; UCHAR QueIdx; unsigned long IrqFlags; NDIS_STATUS Status; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN bTxQLastRound = FALSE; // For USB, didn't need PCI_MAP_SINGLE() //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); // // get Tx Ring Resource & Dma Buffer address // QueIdx = pTxBlk->QueIdx; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; // Check ring full. Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if(Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); // Reserve space for 8 bytes padding. if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; // copy TXWI + WLAN Header + LLC into DMA Header Buffer //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; // Build our URB for USBD DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment USBDMApktLen += padding; pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; bTxQLastRound = TRUE; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); #endif // RT_BIG_ENDIAN // pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); // We unlock it here to prevent the first 8 bytes maybe over-writed issue. // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. // 2. An interrupt break our routine and handle bulk-out complete. // 3. In the bulk-out compllete, it need to do another bulk-out, // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. // 4. Interrupt complete. // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. // and the packet will wrong. pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext->CurWritePosition += pTxBlk->Priv; if (bTxQLastRound) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // succeed and release the skb buffer RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }