📄 receive.c
字号:
//
// Let's link to the "Small" buffer pool.
//
pFreeBufQ = pRecvSegInfo->FreeSmallBufQ;
pRecvPoolTail = pSar->SmallRecvPoolTail;
pRecvPoolQ = pSar->SmallRecvPoolQ;
pAllocatedRecvBuffers = &pSar->AllocatedSmallRecvBuffers;
}
else
{
//
// Let's link to the "Big" buffer pool.
//
pFreeBufQ = pRecvSegInfo->FreeBigBufQ;
pRecvPoolTail = pSar->BigRecvPoolTail;
pRecvPoolQ = pSar->BigRecvPoolQ;
pAllocatedRecvBuffers = &pSar->AllocatedBigRecvBuffers;
}
//
// Walk the list of receive buffers on the pool and add them
// to the free list.
//
for (pRecvHeader = pRecvPool->FreeBuffersHead;
pRecvHeader != NULL;
pRecvHeader = pNextRecvHeader)
{
//
// Save the real next pointer.
//
pNextRecvHeader = pRecvHeader->Next;
//
// Queue the buffer to the end of queue.
//
tbAtm155InsertRecvBufferAtTail(pFreeBufQ, pRecvHeader, TRUE);
}
//
// There are no more receive buffers in the pool.
// They all have been allocated for use and placed in the
// receive buffer information's free list.
//
//
// Queue pRecvPool to the (Big or Small) Recv_Buffer_Pool Queue.
//
if (NULL == pRecvPoolQ)
{
//
// Queue is empty
//
pRecvPoolQ = pRecvPool;
pRecvPoolTail = pRecvPool;
}
else
{
pRecvPoolTail->Next = pRecvPool;
pRecvPoolTail = pRecvPool;
}
*pAllocatedRecvBuffers += (USHORT) (pRecvPool->BuffersFreed);
pRecvPool->FreeBuffersHead = NULL;
pRecvPool->BuffersFreed = 0;
//
// Reset to NULL to dettach from pVc and its data structures.
//
pRecvPool->RecvBufferInfo = NULL;
NdisReleaseSpinLock(&pRecvInfo->lock);
}
NDIS_STATUS
tbAtm155AllocateReceiveBufferPool(
IN PADAPTER_BLOCK pAdapter,
IN PRECV_BUFFER_INFO pRecvInfo,
IN ULONG NumberOfReceiveBuffers,
IN ULONG SizeOfReceiveBuffer
)
/*++
Routine Description:
This routine will allocate a pool of receive buffers, NDIS_BUFFERs
to identify them and packets to package them.
Arguments:
pAdapter - Pointer to the adapter block.
pRecvInfo - Pointer to the receive buffer information that
will keep track of the buffer pool that we
allocate.
NumberOfReceiveBuffers - Number of buffers to allocate.
SizeOfReceiveBuffers - Size of each receive buffer.
Return Value:
NDIS_STATUS_SUCCESS if the allocation was successful.
NDIS_STATUS_RESOURCES if the allocation failed due to memory constraints.
--*/
{
NDIS_STATUS Status;
PRECV_BUFFER_POOL pRecvPool = NULL;
ULONG TotalBufferSize;
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
("==>tbAtm155AllocateReceiveBufferPool\n"));
ASSERT(RECV_BUFFER_INFO_SIG == pRecvInfo->Signature);
do
{
//
// Allocate storage for the buffer pool.
//
ALLOCATE_MEMORY(
&Status,
&pRecvPool,
sizeof(RECV_BUFFER_POOL),
'80DA');
if (NDIS_STATUS_SUCCESS != Status)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unable to allocate a buffer pool\n"));
break;
}
ZERO_MEMORY(pRecvPool, sizeof(RECV_BUFFER_POOL));
pRecvPool->Signature = RECV_BUFFER_POOL_SIG;
//
// Save a back pointer to the owning receive buffer information
// structure.
//
pRecvPool->RecvBufferInfo = pRecvInfo;
//
// Allocate the packet pool.
//
NdisAllocatePacketPool(
&Status,
&pRecvPool->hNdisPacketPool,
NumberOfReceiveBuffers,
PROTOCOL_RESERVED_SIZE_IN_PACKET + TBATM155_PROTOCOL_RESERVED);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unable to allocate NDIS packet pool\n"));
break;
}
//
// Allocate a buffer pool.
//
NdisAllocateBufferPool(
&Status,
&pRecvPool->hFlushBufferPool,
NumberOfReceiveBuffers);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unable to allocate a NDIS_BUFFER pool for flush buffers.\n"));
break;
}
//
// Allocate a buffer pool.
//
NdisAllocateBufferPool(
&Status,
&pRecvPool->hNdisBufferPool,
NumberOfReceiveBuffers);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unable to allocate a NDIS_BUFFER pool for receive buffers.\n"));
break;
}
//
// Save the number of buffers needed and the size for each buffer
// with the pool.
//
pRecvPool->ReceiveBufferCount = NumberOfReceiveBuffers;
pRecvPool->ReceiveBufferSize =
(((SizeOfReceiveBuffer + gDmaAlignmentRequired - 1) /
gDmaAlignmentRequired) * gDmaAlignmentRequired);
//
// Using the alignment determine the size of the header
// for the receive buffers.
//
pRecvPool->ReceiveHeaderSize =
(((sizeof(RECV_BUFFER_HEADER) + gDmaAlignmentRequired - 1) /
gDmaAlignmentRequired) * gDmaAlignmentRequired);
//
// Determine the total size needed for each buffer.
//
TotalBufferSize = pRecvPool->ReceiveHeaderSize + SizeOfReceiveBuffer;
//
// We are going to first attempt to allocate this in one
// large chunk.
//
pRecvPool->Size = (NumberOfReceiveBuffers * TotalBufferSize) +
gDmaAlignmentRequired;
//
// If we are doing this from the tbAtm155ActivateVc handler then
// we need to call async allocate to get our shared memory.
//
if (!ADAPTER_TEST_FLAG(pAdapter, fADAPTER_INITIALIZING))
{
ASSERT(NULL != pRecvInfo->pVc);
//
// Setup for the staged allocation.
//
RECV_POOL_SET_FLAG(pRecvPool, fRECV_POOL_ALLOCATING_BLOCK);
//
// Attempt to allocate the shared memory.
//
Status = NdisMAllocateSharedMemoryAsync(
pAdapter->MiniportAdapterHandle,
pRecvPool->Size,
TRUE,
pRecvPool);
//
// The call above will either return pending or some error code.
//
break;
}
//
// Allocate a chunk of shared ram for the receive buffers.
//
NdisMAllocateSharedMemory(
pAdapter->MiniportAdapterHandle,
pRecvPool->Size,
TRUE,
&pRecvPool->VirtualAddress,
&pRecvPool->PhysicalAddress);
if (NULL != pRecvPool->VirtualAddress)
{
//
// Initialize the receive pool.
//
Status = tbAtm155InitializeBlockReceivePool(pRecvPool);
if (NDIS_STATUS_SUCCESS != Status)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unable to initialize the receive block\n"));
break;
}
}
else
{
//
// Do the individual buffer allocations.
//
Status = tbAtm155AllocateIndividualReceiveBuffers(
pAdapter,
pRecvPool);
if (NDIS_STATUS_SUCCESS != Status)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unable to allocate individual receive buffers\n"));
break;
}
}
//
// Did we successfully set up our receive packets and
// buffers?
//
if (NDIS_STATUS_SUCCESS == Status)
{
//
// Place the receive pool's buffers onto the receive info's
// free buffer list.
//
tbAtm155QueueReceivePoolToSarInfo(pRecvInfo, pRecvPool);
}
} while (FALSE);
//
// If we failed the routine then we need to free the resources
// that were allocated.
//
if ((NDIS_STATUS_SUCCESS != Status) && (NDIS_STATUS_PENDING != Status))
{
if (NULL != pRecvPool)
{
tbAtm155FreeReceiveBufferPool(pAdapter, pRecvPool);
}
}
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
("<==tbAtm155AllocateReceiveBufferPool\n"));
return(Status);
}
BOOLEAN
tbAtm155RxInterruptOnCompletion(
IN PADAPTER_BLOCK pAdapter
)
/*++
Routine Description:
This routine will process the Receive Interrupt On Completion
for the different receive buffers. This interrupt will be generated
when a packet has been received from a Rx Active Slot list of a VC.
If the packet(s) have been receive without error, pass up to NDIS.
Otherwise, discard the packet and return the buffers into free pool
for the next receiving.
Arguments:
pAdapter - Pointer to the adapter block.
Return Value:
None.
--*/
{
PHARDWARE_INFO pHwInfo = pAdapter->HardwareInfo;
PSAR_INFO pSar = pHwInfo->SarInfo;
PRECV_DMA_QUEUE pRecvDmaQ = &pSar->RecvDmaQ;
AAL5_PDU_TRAILER Trailer;
PNDIS_PACKET Packet;
PVC_BLOCK pVc;
PRX_REPORT_QUEUE pRxReportQ = &pAdapter->RxReportQueue;
PRX_REPORT_QUEUE_ENTRY RxReportQueue;
RX_REPORT_PTR RxReportPtrReg;
ULONG CurrentRxReportPtrPa;
UINT CurrentRxReportQIdx;
UINT i;
ULONG Vci;
PRECV_SEG_INFO pRecvSegInfo;
PRECV_BUFFER_HEADER pRecvBufHead;
PRECV_BUFFER_QUEUE pFreeBufQ;
PRECV_BUFFER_QUEUE pSegCompleting;
PNDIS_BUFFER LastBuffer;
PUCHAR LastBufferVa;
UINT LastBufferLength;
PNDIS_BUFFER prevLastBuffer;
PUCHAR prevLastBufferVa;
UINT prevLastBufferLength;
ULONG TrimAmount;
UINT PacketLength;
UINT PhysicalBufferCount;
PMEDIA_SPECIFIC_INFORMATION pMediaSpecificInfo;
ULONG MediaSpecificInfoSize;
PATM_AAL_OOB_INFO pAtmOobInfo;
LONG tmpBufferType;
BOOLEAN fReturnStatus = FALSE;
BOOLEAN fRxSlotsLowOrNone;
PRX_REPORT_QUEUE_ENTRY pEntryOfRxReportQ;
NDIS_STATUS Status;
ULONG Dest;
PULONG pTmpFreeSlots;
PRECV_PACKET_RESERVED Reserved;
BOOLEAN fCorruptedPacket = FALSE;
BOOLEAN fQueryBufferFail = FALSE;
#if DBG
PULONG pdbgTotalUsedRxSlots;
#endif // end of DBG
TBATM155_READ_PORT(
&pHwInfo->TbAtm155_SAR->Rx_Report_Ptr,
&RxReportPtrReg.reg);
//
// Got the position of 155 PCI SAR's internal Rx report queue.
// This pointer indicates the address in host memory to whcih 155 SAR
// will write the next Rx report. So we will only process up to the
// previous entry to make sure the status is valid
//
CurrentRxReportPtrPa = RxReportPtrReg.reg & ~0x3;
//
// Calcuate the index of Rx Report Queue which is pointed by controller.
// HANDLING RULE:
// We only handle up to the entry before this one.
//
CurrentRxReportQIdx =
(CurrentRxReportPtrPa -
NdisGetPhysicalAddressLow(pRxReportQ->RxReportQptrPa)) /
sizeof(RX_REPORT_QUEUE_ENTRY);
//
// Get the starting point where the entry of Rx report queue
// needs to be handled.
//
RxReportQueue = (PRX_REPORT_QUEUE_ENTRY)pRxReportQ->RxReportQptrVa;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -