📄 ndisdevice.c
字号:
pDma = pBufInfo->BufArray;
for ( i = 0; i < pBufInfo->cnAlloc; i++ )
{
#ifndef UNDER_CE
NdisInterlockedPushEntrySList( &pBufInfo->listHead, &pDma->listEntry,
&pBufInfo->listLock );
pDma++;
#else
pPrevious = pDma;
pDma++;
pPrevious->pNext = pDma;
#endif
}
#ifdef UNDER_CE
pPrevious->pNext = NULL;
#endif
} /* InitBuffers */
/*
AllocateBuffers
Description:
This local function allocates DMA buffers for use in receiving and
transmitting.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
PBUFFER_INFO pBufInfo
Pointer to DMA buffer information structure.
int fPacket
Indication that packets are allocated for receiving.
Return (NDIS_STATUS):
NDIS_STATUS_SUCCESS if successful; otherwise an error code indicating
failure.
*/
static NDIS_STATUS AllocateBuffers (
PNDIS_ADAPTER pAdapter,
PBUFFER_INFO pBufInfo,
int fPacket )
{
NDIS_PHYSICAL_ADDRESS AllocPhysicalAddr;
NDIS_PHYSICAL_ADDRESS PhysicalAddr;
NDIS_STATUS NdisStatus;
PDMA_BUFFER pDma;
PUCHAR pAllocVirtual;
PUCHAR pVirtual;
ULONG ulAllocSize;
ULONG ulPhysical;
int i;
int nOffset;
PSHARED_MEM pBufPool = &pBufInfo->MemPool;
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
NDIS_PHYSICAL_ADDRESS_CONST( -1, -1 );
/* Attempt to allocate all the buffer space in one big block. */
/* If it fails, allocate each buffer individually. */
pBufPool->ulAllocSize = ( pBufInfo->cnAlloc * NDIS_BUFFER_SIZE ) +
BUFFER_ALIGNMENT;
pBufPool->bCached = TRUE;
NdisMAllocateSharedMemory( pAdapter->m_hAdapter,
pBufPool->ulAllocSize,
pBufPool->bCached,
&pBufPool->pAllocVirtual,
&pBufPool->AllocPhysicalAddr );
/* Big buffer not allocated. */
if ( pBufPool->pAllocVirtual == NULL )
{
pBufPool->ulAllocSize = 0;
}
else if ( NdisGetPhysicalAddressHigh( pBufPool->AllocPhysicalAddr ) != 0 )
{
NdisMFreeSharedMemory( pAdapter->m_hAdapter,
pBufPool->ulAllocSize,
pBufPool->bCached,
pBufPool->pAllocVirtual,
pBufPool->AllocPhysicalAddr );
pBufPool->pAllocVirtual = NULL;
pBufPool->ulAllocSize = 0;
}
else
{
NdisZeroMemory( pBufPool->pAllocVirtual, pBufPool->ulAllocSize );
nOffset = ((( ULONG ) pBufPool->pAllocVirtual % BUFFER_ALIGNMENT ) ?
( BUFFER_ALIGNMENT -
(( ULONG ) pBufPool->pAllocVirtual % BUFFER_ALIGNMENT )) : 0 );
pBufPool->pVirtual = pBufPool->pAllocVirtual + nOffset;
pBufPool->ulPhysical = NdisGetPhysicalAddressLow(
pBufPool->AllocPhysicalAddr ) + nOffset;
nOffset = 0;
}
#if (NDISVER >= 50)
NdisStatus = NdisAllocateMemoryWithTag(( PVOID* ) &pBufInfo->BufArray,
sizeof( DMA_BUFFER ) * pBufInfo->cnAlloc, 'rciM' );
#else
NdisStatus = NdisAllocateMemory(( PVOID* ) &pBufInfo->BufArray,
sizeof( DMA_BUFFER ) * pBufInfo->cnAlloc,
0, HighestAcceptableMax );
#endif
NdisZeroMemory( pBufInfo->BufArray, sizeof( DMA_BUFFER ) *
pBufInfo->cnAlloc );
/* Set up each buffer. */
pAllocVirtual = NULL;
NdisSetPhysicalAddressHigh( AllocPhysicalAddr, 0 );
NdisSetPhysicalAddressLow( AllocPhysicalAddr, 0 );
NdisSetPhysicalAddressHigh( PhysicalAddr, 0 );
ulAllocSize = pBufPool->ulAllocSize;
pDma = pBufInfo->BufArray;
for ( i = 0; i < pBufInfo->cnAlloc; i++ )
{
/* Big buffer allocated. */
if ( pBufPool->pAllocVirtual )
{
/* Allocate each small buffer from big buffer. */
pVirtual = pBufPool->pVirtual + nOffset;
ulPhysical = pBufPool->ulPhysical + nOffset;
NdisSetPhysicalAddressLow( PhysicalAddr, ulPhysical );
nOffset += NDIS_BUFFER_SIZE;
}
else
{
ulAllocSize = NDIS_BUFFER_SIZE + BUFFER_ALIGNMENT;
/* Allocate each small buffer from system. */
NdisMAllocateSharedMemory( pAdapter->m_hAdapter,
ulAllocSize,
TRUE,
&pAllocVirtual,
&AllocPhysicalAddr );
if ( pAllocVirtual == NULL )
{
return NDIS_STATUS_RESOURCES;
}
else if ( NdisGetPhysicalAddressHigh( AllocPhysicalAddr ) != 0 )
{
NdisMFreeSharedMemory( pAdapter->m_hAdapter,
ulAllocSize,
TRUE,
pAllocVirtual,
AllocPhysicalAddr );
return NDIS_STATUS_RESOURCES;
}
NdisZeroMemory( pAllocVirtual, ulAllocSize );
nOffset = ((( ULONG ) pAllocVirtual % BUFFER_ALIGNMENT ) ?
( BUFFER_ALIGNMENT -
(( ULONG ) pAllocVirtual % BUFFER_ALIGNMENT )) : 0 );
pVirtual = pAllocVirtual + nOffset;
ulPhysical = NdisGetPhysicalAddressLow( AllocPhysicalAddr ) +
nOffset;
NdisSetPhysicalAddressLow( PhysicalAddr, ulPhysical );
}
/* Save the allocated memory information. */
pDma->sm.ulAllocSize = ulAllocSize;
pDma->sm.pAllocVirtual = pAllocVirtual;
pDma->sm.AllocPhysicalAddr = AllocPhysicalAddr;
/* These addresses point to the data buffer. */
pDma->sm.pVirtual = pVirtual;
pDma->sm.ulPhysical = ulPhysical;
pDma->PhysicalAddr = PhysicalAddr;
pDma->ulSize = NDIS_BUFFER_SIZE;
/* Allocate an NDIS flush buffer for each buffer. */
NdisAllocateBuffer(
&NdisStatus,
&pDma->pNdisBuffer,
pAdapter->m_hBufferPool,
pDma->sm.pVirtual,
pDma->ulSize );
if ( NdisStatus != NDIS_STATUS_SUCCESS )
{
pDma->pNdisBuffer = NULL;
return NDIS_STATUS_RESOURCES;
}
if ( fPacket )
{
/* Allocate a packet for each receive buffer. */
NdisAllocatePacket(
&NdisStatus,
&pDma->pNdisPacket,
pAdapter->m_hPacketPool );
if ( NdisStatus != NDIS_STATUS_SUCCESS )
{
pDma->pNdisPacket = NULL;
return NDIS_STATUS_RESOURCES;
}
/* Set the header size in the packet's Out-Of-Band information. */
/* All other fields in the Out-Of-Band information have been */
/* initialized to 0 by NdisAllocatePacket(). */
NDIS_SET_PACKET_HEADER_SIZE(( pDma->pNdisPacket ),
ETHERNET_HEADER_SIZE );
/* Chain the buffer on the packet. */
NdisChainBufferAtFront( pDma->pNdisPacket, pDma->pNdisBuffer );
/* Save a pointer to the receive buffer with the packet. */
RESERVED( pDma->pNdisPacket )->pDma = pDma;
}
pDma++;
}
NdisAllocateSpinLock( &pBufInfo->listLock );
#ifndef UNDER_CE
NdisInitializeSListHead( &pBufInfo->listHead );
#endif
InitBuffers( pBufInfo );
return NDIS_STATUS_SUCCESS;
} /* AllocateBuffers */
#ifndef INLINE
/*
Alloc_DMA_Buffer
Description:
This function allocates a DMA buffer information block for either
transmitting or receiving.
Parameters:
PBUFFER_INFO pBufInfo
Pointer to DMA buffer information structure.
PTDesc pCurrent
Pointer to current descriptor.
Return (PDMA_BUFFER):
Pointer to the DMA buffer information block if successful; NULL
otherwise.
*/
PDMA_BUFFER Alloc_DMA_Buffer (
PBUFFER_INFO pBufInfo,
PTDesc pCurrent )
{
PDMA_BUFFER pDma;
#ifndef UNDER_CE
PSINGLE_LIST_ENTRY pEntry;
pEntry = NdisInterlockedPopEntrySList( &pBufInfo->listHead,
&pBufInfo->listLock );
ASSERT( pEntry != NULL );
pDma = CONTAINING_RECORD( pEntry, DMA_BUFFER, listEntry );
#else
ASSERT( pBufInfo->cnAvail );
pDma = pBufInfo->pTop;
pBufInfo->pTop = pDma->pNext;
pBufInfo->cnAvail--;
#endif
/* Link to current descriptor. */
pCurrent->pReserved = pDma;
return( pDma );
} // Alloc_DMA_Buffer
/*
Free_DMA_Buffer
Description:
This routine frees the DMA buffer information block.
Parameters:
PBUFFER_INFO pBufInfo
Pointer to DMA buffer information structure.
PDMA_BUFFER pDma
Pointer to DMA buffer information block.
Return (None):
*/
VOID Free_DMA_Buffer (
PBUFFER_INFO pBufInfo,
PDMA_BUFFER pDma )
{
#ifndef UNDER_CE
NdisInterlockedPushEntrySList( &pBufInfo->listHead, &pDma->listEntry,
&pBufInfo->listLock );
#else
pDma->pNext = pBufInfo->pTop;
pBufInfo->pTop = pDma;
pBufInfo->cnAvail++;
#endif
} // Free_DMA_Buffer
#endif
/*
InitReceiveBuffers
Description:
This routine initializes DMA buffers for receiving.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
Return (None):
*/
void InitReceiveBuffers (
PNDIS_ADAPTER pAdapter )
{
int i;
PTDesc pDesc;
PDMA_BUFFER pDma;
PHARDWARE pHardware = &pAdapter->m_Hardware;
PTDescInfo pInfo = &pHardware->m_RxDescInfo;
for ( i = 0; i < pHardware->m_RxDescInfo.cnAlloc; i++ )
{
GetRxPacket( pInfo, pDesc );
/* Get a new buffer for this descriptor. */
pDma = Alloc_DMA_Buffer( &pAdapter->m_RxBufInfo, pDesc );
/* Set descriptor. */
SetReceiveBuffer( pDesc, pDma->sm.ulPhysical );
SetReceiveLength( pDesc, pDma->ulSize );
ReleasePacket( pDesc );
}
} /* InitReceiveBuffers */
/*
AllocateMemory
Description:
This function allocates memory for use by hardware descriptors for
receiving and transmitting.
Parameters:
PNDIS_ADAPTER pAdapter
Pointer to adapter information structure.
Return (NDIS_STATUS):
NDIS_STATUS_SUCCESS if successful; otherwise an error code indicating
failure.
*/
NDIS_STATUS AllocateMemory (
PNDIS_ADAPTER pAdapter )
{
PHARDWARE pHardware = &pAdapter->m_Hardware;
NDIS_STATUS NdisStatus;
/* Determine the number of receive and transmit descriptors. */
/* Determine the descriptor size. */
pHardware->m_RxDescInfo.nSize =
((( sizeof( THw_Desc ) + DESC_ALIGNMENT - 1 ) / DESC_ALIGNMENT ) *
DESC_ALIGNMENT );
pHardware->m_TxDescInfo.nSize =
((( sizeof( THw_Desc ) + DESC_ALIGNMENT - 1 ) / DESC_ALIGNMENT ) *
DESC_ALIGNMENT );
if ( pHardware->m_RxDescInfo.nSize != sizeof( THw_Desc ) )
{
DBG_PRINT( "Hardware descriptor size not right!"NEWLINE );
}
CheckDescriptorNum( &pHardware->m_RxDescInfo );
CheckDescriptorNum( &pHardware->m_TxDescInfo );
/* TX/RX buffers we need. */
#if 1
/* More receive buffers so that they can be used by upper layer and
returned later in the MiniportReturnPacket call.
*/
pAdapter->m_RxBufInfo.cnAlloc = pHardware->m_RxDescInfo.cnAlloc << 1;
#else
pAdapter->m_RxBufInfo.cnAlloc = pHardware->m_RxDescInfo.cnAlloc;
#endif
pAdapter->m_TxBufInfo.cnAlloc = pHardware->m_TxDescInfo.cnAlloc;
/* Allocate map registers. */
NdisStatus = AllocateMapRegisters( pAdapter );
if ( NdisStatus != NDIS_STATUS_SUCCESS )
{
return NdisStatus;
}
/* Allocate descriptors */
NdisStatus = AllocateDescriptors( pAdapter );
if ( NdisStatus != NDIS_STATUS_SUCCESS )
{
return NdisStatus;
}
/* Allocate a pool of NDIS buffers. */
NdisAllocateBufferPool(
&NdisStatus,
&pAdapter->m_hBufferPool,
pAdapter->m_RxBufInfo.cnAlloc + pAdapter->m_TxBufInfo.cnAlloc );
if ( NdisStatus != NDIS_STATUS_SUCCESS )
{
return NdisStatus;
}
/* Allocate a pool of packets. */
NdisAllocatePacketPool(
&NdisStatus,
&pAdapter->m_hPacketPool,
pAdapter->m_RxBufInfo.cnAlloc,
0 );
if ( NdisStatus != NDIS_STATUS_SUCCESS )
{
return NdisStatus;
}
/* Allocate receive buffers. */
NdisStatus = AllocateBuffers( pAdapter, &pAdapter->m_RxBufInfo, TRUE );
if ( NdisStatus != NDIS_STATUS_SUCCESS )
{
return NdisStatus;
}
/* Allocate transmit buffers. */
NdisStatus = AllocateBuffers( pAdapter, &pAdapter->m_TxBufInfo, FALSE );
if ( NdisStatus != NDIS_STATUS_SUCCESS )
{
return NdisStatus;
}
InitReceiveBuffers( pAdapter );
#ifdef DBG_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -