📄 receive.c
字号:
/*++
Copyright (c) 2000 Microsoft Corporation. All rights reserved.
File: receive.c
Developed for Toshiba by Elisa Research Inc., CA
http://www.elisaresearch.com
(510) 770-4920
Abstract:
This routine contains all of receive related handlers.
Author:
A. Wang
Environment:
Kernel mode
Revision History:
09/23/96 kyleb Added support for NdisAllocateMemoryWithTag
10/01/96 kyleb Added async receive buffer allocation.
10/18/96 kyleb Added async receive indication.
01/07/97 awang Initial of Toshiba ATM 155 Device Driver.
02/16/99 hhan Use synchronize mode to allocate xmit buffer.
--*/
#include "precomp.h"
#pragma hdrstop
#define MODULE_NUMBER MODULE_RECEIVE
NDIS_STATUS
tbAtm155FreeReceiveBufferInfo(
IN PADAPTER_BLOCK pAdapter,
IN PRECV_BUFFER_INFO pRecvInfo
)
/*++
Routine Description:
This routine will attempt to free the receive buffer information.
Arguments:
pAdapter - Poitner to the ADAPTER_BLOCK.
pRecvInfo - Pointer to the RECV_BUFFER_INFO structure that
describes one or more receive pools to free up.
Return Value:
NDIS_STATUS_SUCCESS if the data structures were correctly free'd up.
--*/
{
UNREFERENCED_PARAMETER(pAdapter);
ASSERT(RECV_BUFFER_INFO_SIG == pRecvInfo->Signature);
//
// Free up the receive information buffer.
//
NdisFreeSpinLock(&pRecvInfo->lock);
FREE_MEMORY(pRecvInfo, sizeof(RECV_BUFFER_INFO));
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
tbAtm155AllocateReceiveBufferInfo(
OUT PRECV_BUFFER_INFO *pRecvInfo,
IN PVC_BLOCK pVc
)
/*++
Routine Description:
This routine will allocate receive buffer information.
Arguments:
pRecvInfo - Pointer to storage for the receive buffer
information structure.
pVc - Pointer to the VC block that this receive information
is for.
Return Value:
NDIS_STATUS_SUCCESS if we successfully allocated storage.
NDIS_STATUS_RESOURCES if the allocation failed.
--*/
{
PRECV_BUFFER_INFO ptmpRecvInfo;
NDIS_STATUS Status;
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("==>tbAtm155AllocateReceiveBufferInfo\n"));
//
// Allocate memory for the receive buffer information structure.
//
ALLOCATE_MEMORY(
&Status,
&ptmpRecvInfo,
sizeof(RECV_BUFFER_INFO),
'60DA');
if (NDIS_STATUS_SUCCESS != Status)
{
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_ERR,
("Unable to allocate RECV_BUFFER_INFO\n"));
return(Status);
}
//
// This will initialize the list's heads and counts...
//
ZERO_MEMORY(ptmpRecvInfo, sizeof(RECV_BUFFER_INFO));
//
// Allocate the spin lock that will protect this structure.
//
NdisAllocateSpinLock(&ptmpRecvInfo->lock);
#if DBG
//
// Set the signature for the receive buffer information structure.
//
ptmpRecvInfo->Signature = RECV_BUFFER_INFO_SIG;
#endif
//
// Save the VC_BLOCK with the receive information.
//
ptmpRecvInfo->pVc = pVc;
//
// Return the buffer information structure back to the caller.
//
*pRecvInfo = ptmpRecvInfo;
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("<==tbAtm155AllocateReceiveBufferInfo\n"));
return(NDIS_STATUS_SUCCESS);
}
VOID
tbAtm155FreeReceiveBufferPool(
IN PADAPTER_BLOCK pAdapter,
IN PRECV_BUFFER_POOL pRecvPool
)
/*++
Routine Description:
This routine will free up a receive buffer pool and it's resources.
If the VC that these resources belong to is deactivating then we also
need to check to see if we can complete the deactivation.
Arguments:
pAdapter - Pointer to the adapter block.
pRecvPool - Pointer to the receive buffer pool that we are freeing.
Return Value:
None.
Note:
The receive buffer information spin lock is already held.
--*/
{
PRECV_BUFFER_HEADER ptmpRecvHeader;
PRECV_BUFFER_HEADER pNextRecvHeader;
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
("==>tbAtm155FreeReceiveBufferPool\n"));
ASSERT(RECV_BUFFER_POOL_SIG == pRecvPool->Signature);
//
// Walk through the free buffer list and free the NDIS buffers and
// packets for each. Also if the buffers were individually
// allocated then we need to free the shared memory for them also.
//
ptmpRecvHeader = pRecvPool->FreeBuffersHead;
for (ptmpRecvHeader = pRecvPool->FreeBuffersHead;
ptmpRecvHeader != NULL;
ptmpRecvHeader = pNextRecvHeader)
{
//
// Save the pointer to the next receive header.
//
pNextRecvHeader = ptmpRecvHeader->Next;
//
// Free the flush buffer.
//
if (NULL != ptmpRecvHeader->FlushBuffer)
{
NdisFreeBuffer(ptmpRecvHeader->FlushBuffer);
}
//
// Free the NDIS buffer.
//
if (NULL != ptmpRecvHeader->NdisBuffer)
{
NdisFreeBuffer(ptmpRecvHeader->NdisBuffer);
}
//
// Free the NDIS packet.
//
if (NULL != ptmpRecvHeader->Packet)
{
NdisFreePacket(ptmpRecvHeader->Packet);
}
//
// Was this buffer individually allocated?
//
if (!RECV_POOL_TEST_FLAG(pRecvPool, fRECV_POOL_BLOCK_ALLOC))
{
NdisMFreeSharedMemory(
pAdapter->MiniportAdapterHandle,
ptmpRecvHeader->Alloc[RECV_BUFFER_ORIGINAL].Size,
TRUE,
ptmpRecvHeader->Alloc[RECV_BUFFER_ORIGINAL].VirtualAddress,
ptmpRecvHeader->Alloc[RECV_BUFFER_ORIGINAL].PhysicalAddress);
}
}
//
// Were the receive buffers allocated in one big chunk?
//
if ((RECV_POOL_TEST_FLAG(pRecvPool, fRECV_POOL_BLOCK_ALLOC)) &&
(NULL != pRecvPool->VirtualAddress))
{
NdisMFreeSharedMemory(
pAdapter->MiniportAdapterHandle,
pRecvPool->Size,
TRUE,
pRecvPool->VirtualAddress,
pRecvPool->PhysicalAddress);
}
//
// Free the buffer pools and packet pools.
//
if (NULL != pRecvPool->hFlushBufferPool)
{
NdisFreeBufferPool(pRecvPool->hFlushBufferPool);
}
if (NULL != pRecvPool->hNdisBufferPool)
{
NdisFreeBufferPool(pRecvPool->hNdisBufferPool);
}
if (NULL != pRecvPool->hNdisPacketPool)
{
NdisFreePacketPool(pRecvPool->hNdisPacketPool);
}
//
// Free the memory used for the RECV_BUFFER_POOL structure.
//
FREE_MEMORY(pRecvPool, sizeof(RECV_BUFFER_POOL));
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
("<==tbAtm155FreeReceiveBufferPool\n"));
}
NDIS_STATUS
tbAtm155InitializeReceiveBuffer(
IN PRECV_BUFFER_POOL pRecvPool,
IN PRECV_BUFFER_HEADER pRecvHeader,
IN PVOID VirtualAddress,
IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG SizeOfReceiveBuffer
)
/*++
Routine Description:
This routine will initialize the receive header with the allocation info,
(tempVa, tempPa and size of receive buffer). It will also allocate
resources from the receive pool (buffers and packets) for use by the
receive buffer.
Arguments:
pRecvPool - Pointer to the receive pool that this receive
header belongs to.
pRecvHeader - Pointer to the receive header that we are
initializing.
VirtualAddress - This is the virtual address for the receive buffer.
PhysicalAddress - This is the physical address for the receive
buffer.
SizeOfReceiveBuffer - Size of the receive buffer in bytes.
Return Value:
NDIS_STATUS_SUCCESS if the initialization is successful.
--*/
{
NDIS_STATUS Status;
PMEDIA_SPECIFIC_INFORMATION pMediaSpecificInfo;
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
("==>tbAtm155InitializeReceiveBuffer\n"));
ASSERT(RECV_BUFFER_POOL_SIG == pRecvPool->Signature);
//
// Determine the pointers to where the data will start.
//
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].VirtualAddress =
(PUCHAR)VirtualAddress + pRecvPool->ReceiveHeaderSize;
NdisSetPhysicalAddressLow(
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].PhysicalAddress,
NdisGetPhysicalAddressLow(PhysicalAddress) + pRecvPool->ReceiveHeaderSize);
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].Size = SizeOfReceiveBuffer;
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
("pRecvBuf[ALIGNED]: Va(%lx), Pa(%lx)\n",
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].VirtualAddress,
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].PhysicalAddress));
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_INFO,
("pRecvBuf[ALIGNED]: Size(%lx)\n",
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].Size));
do
{
//
// Allocate a flush buffer.
//
NdisAllocateBuffer(
&Status,
&pRecvHeader->FlushBuffer,
pRecvPool->hFlushBufferPool,
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].VirtualAddress,
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].Size);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unable to allocate an NDIS_BUFFER for the flush buffer\n"));
break;
}
//
// Allocate a buffer to describe the data to be indicated.
//
NdisAllocateBuffer(
&Status,
&pRecvHeader->NdisBuffer,
pRecvPool->hNdisBufferPool,
(PUCHAR)pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].VirtualAddress,
pRecvHeader->Alloc[RECV_BUFFER_ALIGNED].Size);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unabled to allocate an NDIS_BUFFER for the receive buffer\n"));
break;
}
//
// Allocate a packet from the pool for the receive buffer.
//
NdisAllocatePacket(
&Status,
&pRecvHeader->Packet,
pRecvPool->hNdisPacketPool);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_RECV, DBG_LEVEL_ERR,
("Unable to allocate an NDIS_PACKET for the receive packet\n"));
break;
}
} while (FALSE);
if (NDIS_STATUS_SUCCESS == Status)
{
//
// Initialize the media specific information.
// Our media specific storage is right after the protocol's
// reserved area.
//
pMediaSpecificInfo = (PMEDIA_SPECIFIC_INFORMATION)((PUCHAR)pRecvHeader->Packet +
FIELD_OFFSET(NDIS_PACKET, ProtocolReserved) +
PROTOCOL_RESERVED_SIZE_IN_PACKET +
sizeof(RECV_PACKET_RESERVED));
pMediaSpecificInfo->NextEntryOffset = 0;
pMediaSpecificInfo->ClassId = NdisClassAtmAALInfo;
pMediaSpecificInfo->Size = sizeof(ATM_AAL_OOB_INFO);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -