📄 send.c
字号:
PLIST_ENTRY pEntry = NULL;
PNDIS_PACKET Packet = NULL;
PTCB pTCB = NULL;
DEBUGP(MP_TRACE, ("--> NICFreeBusySendPackets\n"));
if(!MP_TEST_FLAG(Adapter, fMP_SEND_SIDE_RESOURCE_ALLOCATED)){
return;
}
NdisAcquireSpinLock(&Adapter->SendLock);
while(!IsListEmpty(&Adapter->SendBusyList))
{
pEntry = (PLIST_ENTRY)RemoveHeadList(&Adapter->SendBusyList);
pTCB = CONTAINING_RECORD(pEntry, TCB, List);
NdisInitializeListHead(&pTCB->List);
NdisReleaseSpinLock(&Adapter->SendLock);
if (InterlockedExchange((PVOID)&pTCB->IrpLock, IRPLOCK_CANCEL_STARTED)
== IRPLOCK_CANCELABLE) {
//
// we got it to the IRP before it was completed. We can cancel
// the IRP without fear of losing it, as the completion routine
// will not let go of the IRP until we say so.
//
IoCancelIrp(pTCB->Irp);
//
// Release the completion routine. If it already got there,
// then we need to free it yourself. Otherwise, we got
// through IoCancelIrp before the IRP completed entirely.
//
if (InterlockedExchange((PVOID)&pTCB->IrpLock, IRPLOCK_CANCEL_COMPLETE)
== IRPLOCK_COMPLETED) {
if(NdisInterlockedDecrement(&pTCB->Ref) == 0) {
DEBUGP(MP_VERY_LOUD, ("Calling NdisMSendComplete \n"));
NdisMSendComplete(Adapter->AdapterHandle,
pTCB->OrgSendPacket,
NDIS_STATUS_SUCCESS);
//
// Initialize the head so that we don't barf in NICFreeSendTCB
// while doing RemoveEntryList.
//
NdisInitializeListHead(&pTCB->List);
NICFreeSendTCB(Adapter, pTCB);
}else {
ASSERTMSG("Only we have the right to free TCB\n", FALSE);
}
}
}
NdisAcquireSpinLock(&Adapter->SendLock);
}
NdisReleaseSpinLock(&Adapter->SendLock);
DEBUGP(MP_TRACE, ("<-- NICFreeBusySendPackets\n"));
return ;
}
VOID
NICFreeSendTCB(
IN PMP_ADAPTER Adapter,
IN PTCB pTCB)
/*++
Routine Description:
Adapter - pointer to the adapter structure
pTCB - pointer to TCB block
Arguments:
This routine reinitializes the TCB block and puts it back
into the SendFreeList for reuse.
Return Value:
VOID
--*/
{
DEBUGP(MP_TRACE, ("--> NICFreeSendTCB %p\n", pTCB));
pTCB->OrgSendPacket = NULL;
pTCB->Buffer->Next = NULL;
pTCB->Mdl = NULL;
ASSERT(pTCB->Irp);
ASSERT(!pTCB->Ref);
//
// Reinitialize the IRP for reuse.
//
IoReuseIrp(pTCB->Irp, STATUS_SUCCESS);
//
// Set the MDL field to NULL so that we don't end up free the
// MDL in our call to IoFreeIrp.
//
pTCB->Irp->MdlAddress = NULL;
//
// Re adjust the length to the originl size
//
NdisAdjustBufferLength(pTCB->Buffer, NIC_BUFFER_SIZE);
//
// Insert the TCB back in the send free list
//
NdisAcquireSpinLock(&Adapter->SendLock);
RemoveEntryList(&pTCB->List);
InsertTailList(&Adapter->SendFreeList, &pTCB->List);
NdisInterlockedDecrement(&Adapter->nBusySend);
ASSERT(Adapter->nBusySend >= 0);
NdisReleaseSpinLock(&Adapter->SendLock);
DEBUGP(MP_TRACE, ("<-- NICFreeSendTCB\n"));
}
VOID
NICFreeQueuedSendPackets(
PMP_ADAPTER Adapter
)
/*++
Routine Description:
This routine is called by the Halt handler to fail all
the queued up SendPackets because the device is either
gone, being stopped for resource rebalance.
Arguments:
Adapter - pointer to the adapter structure
Return Value:
VOID
--*/
{
PLIST_ENTRY pEntry = NULL;
PNDIS_PACKET Packet = NULL;
DEBUGP(MP_TRACE, ("--> NICFreeQueuedSendPackets\n"));
while(MP_TEST_FLAG(Adapter, fMP_SEND_SIDE_RESOURCE_ALLOCATED))
{
pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
&Adapter->SendWaitList,
&Adapter->SendLock);
if(!pEntry)
{
break;
}
Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
NdisMSendComplete(
Adapter->AdapterHandle,
Packet,
NDIS_STATUS_FAILURE);
}
DEBUGP(MP_TRACE, ("<-- NICFreeQueuedSendPackets\n"));
}
BOOLEAN
NICCopyPacket(
PMP_ADAPTER Adapter,
PTCB pTCB,
PNDIS_PACKET Packet)
/*++
Routine Description:
This routine copies the packet data into the TCB data block and
inserts the TCB in the SendBusyList.
Arguments:
Adapter - pointer to the MP_ADAPTER structure
pTCB - pointer to TCB block
Packet - packet to be transfered.
Return Value:
VOID
--*/
{
PNDIS_BUFFER CurrentBuffer = NULL;
PVOID VirtualAddress = NULL;
UINT CurrentLength;
UINT BytesToCopy;
UINT BytesCopied = 0;
UINT PacketLength;
PUCHAR pDest = pTCB->pData;
BOOLEAN bResult = TRUE, bPadding = FALSE;
PETH_HEADER pEthHeader;
UINT DestBufferSize = NIC_BUFFER_SIZE;
DEBUGP(MP_TRACE, ("--> NICCopyPacket\n"));
//
// Initialize TCB structure
//
pTCB->OrgSendPacket = Packet;
pTCB->Ref = 1;
NdisInitializeListHead(&pTCB->List);
//
// Query the packet to get length and pointer to the first buffer.
//
NdisQueryPacket(Packet,
NULL,
NULL,
&CurrentBuffer,
&PacketLength);
ASSERT(PacketLength <= NIC_BUFFER_SIZE);
PacketLength = min(PacketLength, NIC_BUFFER_SIZE);
if(PacketLength < ETH_MIN_PACKET_SIZE)
{
PacketLength = ETH_MIN_PACKET_SIZE; // padding
bPadding = TRUE;
}
if(Adapter->TargetSupportsChainedMdls
&& bPadding == FALSE) {
//
// If the lower driver supports chained MDLs, we will
// assign the MDL to the request and send it down. However if
// the packet is less than 60 bytes, we need to pad zero to
// make it atleast 60bytes long. In that case we will just use
// our preallocated flat buffer. If this driver is adapted for
// a real device, the user should only preallocate 60 bytes TCB
// Buffer instead of NIC_BUFFER_SIZE.
//
pTCB->Mdl = (PMDL)CurrentBuffer;
pTCB->ulSize = PacketLength;
Adapter->nBytesArrived += PacketLength;
} else {
BytesToCopy = PacketLength;
//
// Copy the data from chained buffers to our TCB flat buffer.
//
while(CurrentBuffer)
{
NdisQueryBufferSafe(
CurrentBuffer,
&VirtualAddress,
&CurrentLength,
NormalPagePriority);
if(!VirtualAddress) {
bResult = FALSE;
break;
}
CurrentLength = min(CurrentLength, DestBufferSize);
if(CurrentLength)
{
// Copy the data.
NdisMoveMemory(pDest, VirtualAddress, CurrentLength);
BytesCopied += CurrentLength;
DestBufferSize -= CurrentLength;
pDest += CurrentLength;
}
NdisGetNextBuffer(
CurrentBuffer,
&CurrentBuffer);
}
if(bResult) {
Adapter->nBytesArrived += BytesCopied;
//
// If the packet size is less than ETH_MIN_PACKET_SIZE. Pad the buffer
// up to ETH_MIN_PACKET_SIZE with zero bytes for security reason.
//
if(BytesCopied < BytesToCopy)
{
NdisZeroMemory(pDest, BytesToCopy-BytesCopied);
BytesCopied = BytesToCopy;
}
//
// Adjust the buffer length to reflect the new length
//
NdisAdjustBufferLength(pTCB->Buffer, BytesCopied);
pTCB->ulSize = BytesCopied;
pTCB->Mdl = pTCB->Buffer;
if(PacketLength >= sizeof(ETH_HEADER)) {
pEthHeader = (PETH_HEADER)pTCB->pData;
//memcpy(pEthHeader->SrcAddr, Adapter->PhyNicMacAddress,
// ETH_LENGTH_OF_ADDRESS);
DEBUGP(MP_LOUD, ("Src Address = %02x-%02x-%02x-%02x-%02x-%02x",
pEthHeader->SrcAddr[0],
pEthHeader->SrcAddr[1],
pEthHeader->SrcAddr[2],
pEthHeader->SrcAddr[3],
pEthHeader->SrcAddr[4],
pEthHeader->SrcAddr[5]));
DEBUGP(MP_LOUD, (" Dest Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
pEthHeader->DstAddr[0],
pEthHeader->DstAddr[1],
pEthHeader->DstAddr[2],
pEthHeader->DstAddr[3],
pEthHeader->DstAddr[4],
pEthHeader->DstAddr[5]));
}else{
ASSERTMSG("Packet length is less than ETH_HEADER\n", FALSE);
bResult = FALSE;
}
}
}
if(bResult){
NdisInterlockedInsertTailList(
&Adapter->SendBusyList,
&pTCB->List,
&Adapter->SendLock);
}
DEBUGP(MP_TRACE, ("<-- NICCopyPacket\n"));
return bResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -