- Visual C++源码
- Visual Basic源码
- C++ Builder源码
- Java源码
- Delphi源码
- C/C++源码
- PHP源码
- Perl源码
- Python源码
- Asm源码
- Pascal源码
- Borland C++源码
- Others源码
- SQL源码
- VBScript源码
- JavaScript源码
- ASP/ASPX源码
- C#源码
- Flash/ActionScript源码
- matlab源码
- PowerBuilder源码
- LabView源码
- Flex源码
- MathCAD源码
- VBA源码
- IDL源码
- Lisp/Scheme源码
- VHDL源码
- Objective-C源码
- Fortran源码
- tcl/tk源码
- QT源码
recv.c
资源名称:1336ndis.rar [点击查看]
上传用户:yanxuanwei
上传日期:2008-05-17
资源大小:53k
文件大小:33k
源码类别:
驱动编程
开发平台:
Visual C++
- /*++
- Copyright (c) 2000 Microsoft Corporation
- Module Name:
- recv.c
- Abstract:
- NDIS protocol entry points and utility routines to handle receiving
- data.
- Environment:
- Kernel mode only.
- Revision History:
- arvindm 4/6/2000 Created
- --*/
- #include "precomp.h"
- #define __FILENUMBER 'VCER'
- NTSTATUS
- NdisuioRead(
- IN PDEVICE_OBJECT pDeviceObject,
- IN PIRP pIrp
- )
- /*++
- Routine Description:
- Dispatch routine to handle IRP_MJ_READ.
- Arguments:
- pDeviceObject - pointer to our device object
- pIrp - Pointer to request packet
- Return Value:
- NT status code.
- --*/
- {
- PIO_STACK_LOCATION pIrpSp;
- ULONG FunctionCode;
- NTSTATUS NtStatus;
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
- pOpenContext = pIrpSp->FileObject->FsContext;
- do
- {
- //
- // Validate!
- //
- if (pOpenContext == NULL)
- {
- DEBUGP(DL_FATAL, ("Read: NULL FsContext on FileObject %pn",
- pIrpSp->FileObject));
- NtStatus = STATUS_INVALID_HANDLE;
- break;
- }
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- if (pIrp->MdlAddress == NULL)
- {
- DEBUGP(DL_FATAL, ("Read: NULL MDL address on IRP %pn", pIrp));
- NtStatus = STATUS_INVALID_PARAMETER;
- break;
- }
- //
- // Try to get a virtual address for the MDL.
- //
- #ifndef WIN9X
- if (MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority) == NULL)
- {
- DEBUGP(DL_FATAL, ("Read: MmGetSystemAddr failed for IRP %p, MDL %pn",
- pIrp, pIrp->MdlAddress));
- NtStatus = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- #endif
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- if (!NUIO_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
- {
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- NtStatus = STATUS_INVALID_HANDLE;
- break;
- }
- //
- // Add this IRP to the list of pended Read IRPs
- //
- NUIO_INSERT_TAIL_LIST(&pOpenContext->PendedReads, &pIrp->Tail.Overlay.ListEntry);
- NUIO_REF_OPEN(pOpenContext); // pended read IRP
- pOpenContext->PendedReadCount++;
- //
- // Set up the IRP for possible cancellation.
- //
- pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pOpenContext;
- IoMarkIrpPending(pIrp);
- IoSetCancelRoutine(pIrp, NdisuioCancelRead);
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- NtStatus = STATUS_PENDING;
- //
- // Run the service routine for reads.
- //
- ndisuioServiceReads(pOpenContext);
- break;
- }
- while (FALSE);
- if (NtStatus != STATUS_PENDING)
- {
- NUIO_ASSERT(NtStatus != STATUS_SUCCESS);
- pIrp->IoStatus.Information = 0;
- pIrp->IoStatus.Status = NtStatus;
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- }
- return (NtStatus);
- }
- VOID
- NdisuioCancelRead(
- IN PDEVICE_OBJECT pDeviceObject,
- IN PIRP pIrp
- )
- /*++
- Routine Description:
- Cancel a pending read IRP. We unlink the IRP from the open context
- queue and complete it.
- Arguments:
- pDeviceObject - pointer to our device object
- pIrp - IRP to be cancelled
- Return Value:
- None
- --*/
- {
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- PLIST_ENTRY pEnt;
- PLIST_ENTRY pIrpEntry;
- BOOLEAN Found;
- IoReleaseCancelSpinLock(pIrp->CancelIrql);
- Found = FALSE;
- pOpenContext = (PNDISUIO_OPEN_CONTEXT) pIrp->Tail.Overlay.DriverContext[0];
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- //
- // Locate the IRP in the pended read queue and remove it if found.
- //
- for (pIrpEntry = pOpenContext->PendedReads.Flink;
- pIrpEntry != &pOpenContext->PendedReads;
- pIrpEntry = pIrpEntry->Flink)
- {
- if (pIrp == CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry))
- {
- NUIO_REMOVE_ENTRY_LIST(&pIrp->Tail.Overlay.ListEntry);
- pOpenContext->PendedReadCount--;
- Found = TRUE;
- break;
- }
- }
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- if (Found)
- {
- DEBUGP(DL_INFO, ("CancelRead: Open %p, IRP %pn", pOpenContext, pIrp));
- pIrp->IoStatus.Status = STATUS_CANCELLED;
- pIrp->IoStatus.Information = 0;
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- NUIO_DEREF_OPEN(pOpenContext); // Cancel removed pended Read
- }
- }
- VOID
- ndisuioServiceReads(
- IN PNDISUIO_OPEN_CONTEXT pOpenContext
- )
- /*++
- Routine Description:
- Utility routine to copy received data into user buffers and
- complete READ IRPs.
- Arguments:
- pOpenContext - pointer to open context
- Return Value:
- None
- --*/
- {
- PIRP pIrp;
- PLIST_ENTRY pIrpEntry;
- PNDIS_PACKET pRcvPacket;
- PLIST_ENTRY pRcvPacketEntry;
- PUCHAR pSrc, pDst;
- ULONG BytesRemaining; // at pDst
- PNDIS_BUFFER pNdisBuffer;
- ULONG BytesAvailable;
- DEBUGP(DL_VERY_LOUD, ("ServiceReads: open %p/%xn",
- pOpenContext, pOpenContext->Flags));
- NUIO_REF_OPEN(pOpenContext); // temp ref - service reads
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- while (!NUIO_IS_LIST_EMPTY(&pOpenContext->PendedReads) &&
- !NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
- {
- //
- // Get the first pended Read IRP
- //
- pIrpEntry = pOpenContext->PendedReads.Flink;
- pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);
- //
- // Check to see if it is being cancelled.
- //
- if (IoSetCancelRoutine(pIrp, NULL))
- {
- //
- // It isn't being cancelled, and can't be cancelled henceforth.
- //
- NUIO_REMOVE_ENTRY_LIST(pIrpEntry);
- //
- // NOTE: we decrement PendedReadCount way below in the
- // while loop, to avoid letting through a thread trying
- // to unbind.
- //
- }
- else
- {
- //
- // The IRP is being cancelled; let the cancel routine handle it.
- //
- DEBUGP(DL_INFO, ("ServiceReads: open %p, skipping cancelled IRP %pn",
- pOpenContext, pIrp));
- continue;
- }
- //
- // Get the first queued receive packet
- //
- pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
- NUIO_REMOVE_ENTRY_LIST(pRcvPacketEntry);
- pOpenContext->RecvPktCount --;
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- NUIO_DEREF_OPEN(pOpenContext); // Service: dequeue rcv packet
- pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);
- //
- // Copy as much data as possible from the receive packet to
- // the IRP MDL.
- //
- #ifndef WIN9X
- pDst = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
- NUIO_ASSERT(pDst != NULL); // since it was already mapped
- #else
- pDst = MmGetSystemAddressForMdl(pIrp->MdlAddress); // Win9x
- #endif
- BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);
- pNdisBuffer = pRcvPacket->Private.Head;
- while (BytesRemaining && (pNdisBuffer != NULL))
- {
- #ifndef WIN9X
- NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);
- if (pSrc == NULL)
- {
- DEBUGP(DL_FATAL,
- ("ServiceReads: Open %p, QueryBuffer failed for buffer %pn",
- pOpenContext, pNdisBuffer));
- break;
- }
- #else
- NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable);
- #endif
- if (BytesAvailable)
- {
- ULONG BytesToCopy = MIN(BytesAvailable, BytesRemaining);
- NUIO_COPY_MEM(pDst, pSrc, BytesToCopy);
- BytesRemaining -= BytesToCopy;
- pDst += BytesToCopy;
- }
- NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
- }
- //
- // Complete the IRP.
- //
- pIrp->IoStatus.Status = STATUS_SUCCESS;
- pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining;
- DEBUGP(DL_INFO, ("ServiceReads: Open %p, IRP %p completed with %d bytesn",
- pOpenContext, pIrp, pIrp->IoStatus.Information));
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- //
- // Free up the receive packet - back to the miniport if it
- // belongs to it, else reclaim it (local copy).
- //
- if (NdisGetPoolFromPacket(pRcvPacket) != pOpenContext->RecvPacketPool)
- {
- NdisReturnPackets(&pRcvPacket, 1);
- }
- else
- {
- ndisuioFreeReceivePacket(pOpenContext, pRcvPacket);
- }
- NUIO_DEREF_OPEN(pOpenContext); // took out pended Read
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- pOpenContext->PendedReadCount--;
- }
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- NUIO_DEREF_OPEN(pOpenContext); // temp ref - service reads
- }
- NDIS_STATUS
- NdisuioReceive(
- IN NDIS_HANDLE ProtocolBindingContext,
- IN NDIS_HANDLE MacReceiveContext,
- IN PVOID pHeaderBuffer,
- IN UINT HeaderBufferSize,
- IN PVOID pLookaheadBuffer,
- IN UINT LookaheadBufferSize,
- IN UINT PacketSize
- )
- /*++
- Routine Description:
- Our protocol receive handler called by NDIS, typically if we have
- a miniport below that doesn't indicate packets.
- We make a local packet/buffer copy of this data, queue it up, and
- kick off the read service routine.
- Arguments:
- ProtocolBindingContext - pointer to open context
- MacReceiveContext - for use in NdisTransferData
- pHeaderBuffer - pointer to data header
- HeaderBufferSize - size of the above
- pLookaheadBuffer - pointer to buffer containing lookahead data
- LookaheadBufferSize - size of the above
- PacketSize - size of the entire packet, minus header size.
- Return Value:
- NDIS_STATUS_NOT_ACCEPTED - if this packet is uninteresting
- NDIS_STATUS_SUCCESS - if we processed this successfully
- --*/
- {
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- NDIS_STATUS Status;
- PNDISUIO_ETH_HEADER pEthHeader;
- PNDIS_PACKET pRcvPacket;
- PUCHAR pRcvData;
- UINT BytesTransferred;
- PNDIS_BUFFER pOriginalNdisBuffer, pPartialNdisBuffer;
- pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- pRcvPacket = NULL;
- pRcvData = NULL;
- Status = NDIS_STATUS_SUCCESS;
- do
- {
- if (HeaderBufferSize != sizeof(NDISUIO_ETH_HEADER))
- {
- Status = NDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- pEthHeader = (PNDISUIO_ETH_HEADER)pHeaderBuffer;
- //
- // Check the EtherType. If the Ether type indicates presence of
- // a tag, then the "real" Ether type is 4 bytes further down.
- //
- if (pEthHeader->EthType == NUIO_8021P_TAG_TYPE)
- {
- USHORT UNALIGNED *pEthType;
- pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4);
- if (*pEthType != Globals.EthType)
- {
- Status = NDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- }
- else if (pEthHeader->EthType != Globals.EthType)
- {
- Status = NDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- //
- // Allocate resources for queueing this up.
- //
- pRcvPacket = ndisuioAllocateReceivePacket(
- pOpenContext,
- PacketSize + HeaderBufferSize,
- &pRcvData
- );
- if (pRcvPacket == NULL)
- {
- Status = NDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- NdisMoveMappedMemory(pRcvData, pHeaderBuffer, HeaderBufferSize);
- //
- // Check if the entire packet is within the lookahead.
- //
- if (PacketSize == LookaheadBufferSize)
- {
- NdisCopyLookaheadData(pRcvData+HeaderBufferSize,
- pLookaheadBuffer,
- LookaheadBufferSize,
- pOpenContext->MacOptions);
- //
- // Queue this up for receive processing, and
- // try to complete some read IRPs.
- //
- ndisuioQueueReceivePacket(pOpenContext, pRcvPacket);
- }
- else
- {
- //
- // Allocate an NDIS buffer to map the receive area
- // at an offset "HeaderBufferSize" from the current
- // start. This is so that NdisTransferData can copy
- // in at the right point in the destination buffer.
- //
- NdisAllocateBuffer(
- &Status,
- &pPartialNdisBuffer,
- pOpenContext->RecvBufferPool,
- pRcvData + HeaderBufferSize,
- PacketSize);
- if (Status == NDIS_STATUS_SUCCESS)
- {
- //
- // Unlink and save away the original NDIS Buffer
- // that maps the full receive buffer.
- //
- NdisUnchainBufferAtFront(pRcvPacket, &pOriginalNdisBuffer);
- NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pOriginalNdisBuffer;
- //
- // Link in the partial buffer for NdisTransferData to
- // operate on.
- //
- NdisChainBufferAtBack(pRcvPacket, pPartialNdisBuffer);
- DEBUGP(DL_LOUD, ("Receive: setting up for TransferData:"
- " Pkt %p, OriginalBuf %p, PartialBuf %pn",
- pRcvPacket, pOriginalNdisBuffer, pPartialNdisBuffer));
- NdisTransferData(
- &Status,
- pOpenContext->BindingHandle,
- MacReceiveContext,
- 0, // ByteOffset
- PacketSize,
- pRcvPacket,
- &BytesTransferred);
- }
- else
- {
- //
- // Failure handled below in TransferDataComplete.
- //
- BytesTransferred = 0;
- }
- if (Status != NDIS_STATUS_PENDING)
- {
- NdisuioTransferDataComplete(
- (NDIS_HANDLE)pOpenContext,
- pRcvPacket,
- Status,
- BytesTransferred);
- }
- }
- break;
- }
- while (FALSE);
- return Status;
- DEBUGP(DL_LOUD, ("Receive: Open %p, Pkt %p, Size %dn",
- pOpenContext, pRcvPacket, PacketSize));
- }
- VOID
- NdisuioTransferDataComplete(
- IN NDIS_HANDLE ProtocolBindingContext,
- IN PNDIS_PACKET pNdisPacket,
- IN NDIS_STATUS TransferStatus,
- IN UINT BytesTransferred
- )
- /*++
- Routine Description:
- NDIS entry point called to signal completion of a call to
- NdisTransferData that had pended.
- Arguments:
- ProtocolBindingContext - pointer to open context
- pNdisPacket - our receive packet into which data is transferred
- TransferStatus - status of the transfer
- BytesTransferred - bytes copied into the packet.
- Return Value:
- None
- --*/
- {
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- PNDIS_BUFFER pOriginalBuffer, pPartialBuffer;
- pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- //
- // Check if an NDIS_BUFFER was created to map part of the receive buffer;
- // if so, free it and link back the original NDIS_BUFFER that maps
- // the full receive buffer to the packet.
- //
- pOriginalBuffer = NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pNdisPacket);
- if (pOriginalBuffer != NULL)
- {
- //
- // We had stashed off the NDIS_BUFFER for the full receive
- // buffer in the packet reserved area. Unlink the partial
- // buffer and link in the full buffer.
- //
- NdisUnchainBufferAtFront(pNdisPacket, &pPartialBuffer);
- NdisChainBufferAtBack(pNdisPacket, pOriginalBuffer);
- DEBUGP(DL_LOUD, ("TransferComp: Pkt %p, OrigBuf %p, PartialBuf %pn",
- pNdisPacket, pOriginalBuffer, pPartialBuffer));
- //
- // Free up the partial buffer.
- //
- NdisFreeBuffer(pPartialBuffer);
- }
- if (TransferStatus == NDIS_STATUS_SUCCESS)
- {
- //
- // Queue this up for receive processing, and
- // try to complete some read IRPs.
- //
- ndisuioQueueReceivePacket(pOpenContext, pNdisPacket);
- }
- else
- {
- ndisuioFreeReceivePacket(pOpenContext, pNdisPacket);
- }
- }
- VOID
- NdisuioReceiveComplete(
- IN NDIS_HANDLE ProtocolBindingContext
- )
- /*++
- Routine Description:
- Protocol entry point called by NDIS when the miniport
- has finished indicating up a batch of receives.
- We ignore this.
- Arguments:
- ProtocolBindingContext - pointer to open context
- Return Value:
- None
- --*/
- {
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- return;
- }
- INT
- NdisuioReceivePacket(
- IN NDIS_HANDLE ProtocolBindingContext,
- IN PNDIS_PACKET pNdisPacket
- )
- /*++
- Routine Description:
- Protocol entry point called by NDIS if the driver below
- uses NDIS 4 style receive packet indications.
- If the miniport allows us to hold on to this packet, we
- use it as is, otherwise we make a copy.
- Arguments:
- ProtocolBindingContext - pointer to open context
- pNdisPacket - the packet being indicated up.
- Return Value:
- None
- --*/
- {
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- PNDIS_BUFFER pNdisBuffer;
- UINT BufferLength;
- PNDISUIO_ETH_HEADER pEthHeader;
- PNDIS_PACKET pCopyPacket;
- PUCHAR pCopyBuf;
- UINT TotalPacketLength;
- UINT BytesCopied;
- INT RefCount = 0;
- NDIS_STATUS Status;
- pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- #ifdef NDIS51
- NdisGetFirstBufferFromPacketSafe(
- pNdisPacket,
- &pNdisBuffer,
- &pEthHeader,
- &BufferLength,
- &TotalPacketLength,
- NormalPagePriority);
- if (pEthHeader == NULL)
- {
- //
- // The system is low on resources. Set up to handle failure
- // below.
- //
- BufferLength = 0;
- }
- #else
- NdisGetFirstBufferFromPacket(
- pNdisPacket,
- &pNdisBuffer,
- &pEthHeader,
- &BufferLength,
- &TotalPacketLength);
- #endif
- do
- {
- if (BufferLength < sizeof(NDISUIO_ETH_HEADER))
- {
- DEBUGP(DL_WARN,
- ("ReceivePacket: Open %p, runt pkt %p, first buffer length %dn",
- pOpenContext, pNdisPacket, BufferLength));
- Status = NDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- //
- // Check the EtherType. If the Ether type indicates presence of
- // a tag, then the "real" Ether type is 4 bytes further down.
- //
- if (pEthHeader->EthType == NUIO_8021P_TAG_TYPE)
- {
- USHORT UNALIGNED *pEthType;
- pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4);
- if (*pEthType != Globals.EthType)
- {
- Status = NDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- }
- else if (pEthHeader->EthType != Globals.EthType)
- {
- Status = NDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- DEBUGP(DL_LOUD, ("ReceivePacket: Open %p, interesting pkt %pn",
- pOpenContext, pNdisPacket));
- //
- // If the miniport is out of resources, we can't queue
- // this packet - make a copy if this is so.
- //
- if ((NDIS_GET_PACKET_STATUS(pNdisPacket) == NDIS_STATUS_RESOURCES) ||
- pOpenContext->bRunningOnWin9x)
- {
- pCopyPacket = ndisuioAllocateReceivePacket(
- pOpenContext,
- TotalPacketLength,
- &pCopyBuf
- );
- if (pCopyPacket == NULL)
- {
- DEBUGP(DL_FATAL, ("ReceivePacket: Open %p, failed to"
- " alloc copy, %d bytesn", pOpenContext, TotalPacketLength));
- break;
- }
- NdisCopyFromPacketToPacket(
- pCopyPacket,
- 0,
- TotalPacketLength,
- pNdisPacket,
- 0,
- &BytesCopied);
- NUIO_ASSERT(BytesCopied == TotalPacketLength);
- pNdisPacket = pCopyPacket;
- }
- else
- {
- //
- // We can queue the original packet - return
- // a packet reference count indicating that
- // we will call NdisReturnPackets when we are
- // done with this packet.
- //
- RefCount = 1;
- }
- //
- // Queue this up and service any pending Read IRPs.
- //
- ndisuioQueueReceivePacket(pOpenContext, pNdisPacket);
- break;
- }
- while (FALSE);
- return (RefCount);
- }
- VOID
- ndisuioQueueReceivePacket(
- IN PNDISUIO_OPEN_CONTEXT pOpenContext,
- IN PNDIS_PACKET pRcvPacket
- )
- /*++
- Routine Description:
- Queue up a received packet on the open context structure.
- If the queue size goes beyond a water mark, discard a packet
- at the head of the queue.
- Finally, run the queue service routine.
- Arguments:
- pOpenContext - pointer to open context
- pRcvPacket - the received packet
- Return Value:
- None
- --*/
- {
- PLIST_ENTRY pEnt;
- PLIST_ENTRY pDiscardEnt;
- PNDIS_PACKET pDiscardPkt;
- do
- {
- pEnt = NUIO_RCV_PKT_TO_LIST_ENTRY(pRcvPacket);
- NUIO_REF_OPEN(pOpenContext); // queued rcv packet
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- //
- // Check if the binding is in the proper state to receive
- // this packet.
- //
- if (NUIO_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE) &&
- (pOpenContext->PowerState == NetDeviceStateD0))
- {
- NUIO_INSERT_TAIL_LIST(&pOpenContext->RecvPktQueue, pEnt);
- pOpenContext->RecvPktCount++;
- DEBUGP(DL_VERY_LOUD, ("QueueReceivePacket: open %p,"
- " queued pkt %p, queue size %dn",
- pOpenContext, pRcvPacket, pOpenContext->RecvPktCount));
- }
- else
- {
- //
- // Received this packet when the binding is going away.
- // Drop this.
- //
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- ndisuioFreeReceivePacket(pOpenContext, pRcvPacket);
- NUIO_DEREF_OPEN(pOpenContext); // dropped rcv packet - bad state
- break;
- }
- //
- // Trim the queue if it has grown too big.
- //
- if (pOpenContext->RecvPktCount > MAX_RECV_QUEUE_SIZE)
- {
- //
- // Remove the head of the queue.
- //
- pDiscardEnt = pOpenContext->RecvPktQueue.Flink;
- NUIO_REMOVE_ENTRY_LIST(pDiscardEnt);
- pOpenContext->RecvPktCount --;
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- pDiscardPkt = NUIO_LIST_ENTRY_TO_RCV_PKT(pDiscardEnt);
- ndisuioFreeReceivePacket(pOpenContext, pDiscardPkt);
- NUIO_DEREF_OPEN(pOpenContext); // dropped rcv packet - queue too long
- DEBUGP(DL_INFO, ("QueueReceivePacket: open %p queue"
- " too long, discarded pkt %pn",
- pOpenContext, pDiscardPkt));
- }
- else
- {
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- }
- //
- // Run the receive queue service routine now.
- //
- ndisuioServiceReads(pOpenContext);
- }
- while (FALSE);
- }
- PNDIS_PACKET
- ndisuioAllocateReceivePacket(
- IN PNDISUIO_OPEN_CONTEXT pOpenContext,
- IN UINT DataLength,
- OUT PUCHAR * ppDataBuffer
- )
- /*++
- Routine Description:
- Allocate resources to copy and queue a received packet.
- Arguments:
- pOpenContext - pointer to open context for received packet
- DataLength - total length in bytes of the packet
- ppDataBuffer - place to return pointer to allocated buffer
- Return Value:
- Pointer to NDIS packet if successful, else NULL.
- --*/
- {
- PNDIS_PACKET pNdisPacket;
- PNDIS_BUFFER pNdisBuffer;
- PUCHAR pDataBuffer;
- NDIS_STATUS Status;
- pNdisPacket = NULL;
- pNdisBuffer = NULL;
- pDataBuffer = NULL;
- do
- {
- NUIO_ALLOC_MEM(pDataBuffer, DataLength);
- if (pDataBuffer == NULL)
- {
- DEBUGP(DL_FATAL, ("AllocRcvPkt: open %p, failed to alloc"
- " data buffer %d bytesn", pOpenContext, DataLength));
- break;
- }
- //
- // Make this an NDIS buffer.
- //
- NdisAllocateBuffer(
- &Status,
- &pNdisBuffer,
- pOpenContext->RecvBufferPool,
- pDataBuffer,
- DataLength);
- if (Status != NDIS_STATUS_SUCCESS)
- {
- DEBUGP(DL_FATAL, ("AllocateRcvPkt: open %p, failed to alloc"
- " NDIS buffer, %d bytesn", pOpenContext, DataLength));
- break;
- }
- NdisAllocatePacket(&Status, &pNdisPacket, pOpenContext->RecvPacketPool);
- if (Status != NDIS_STATUS_SUCCESS)
- {
- DEBUGP(DL_FATAL, ("AllocateRcvPkt: open %p, failed to alloc"
- " NDIS packet, %d bytesn", pOpenContext, DataLength));
- break;
- }
- NDIS_SET_PACKET_STATUS(pNdisPacket, 0);
- NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pNdisPacket) = NULL;
- NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
- *ppDataBuffer = pDataBuffer;
- break;
- }
- while (FALSE);
- if (pNdisPacket == NULL)
- {
- //
- // Clean up
- //
- if (pNdisBuffer != NULL)
- {
- NdisFreeBuffer(pNdisBuffer);
- }
- if (pDataBuffer != NULL)
- {
- NUIO_FREE_MEM(pDataBuffer);
- }
- }
- return (pNdisPacket);
- }
- VOID
- ndisuioFreeReceivePacket(
- IN PNDISUIO_OPEN_CONTEXT pOpenContext,
- IN PNDIS_PACKET pNdisPacket
- )
- /*++
- Routine Description:
- Free up all resources associated with a received packet. If this
- is a local copy, free the packet to our receive pool, else return
- this to the miniport.
- Arguments:
- pOpenContext - pointer to open context
- pNdisPacket - pointer to packet to be freed.
- Return Value:
- None
- --*/
- {
- PNDIS_BUFFER pNdisBuffer;
- UINT TotalLength;
- UINT BufferLength;
- PUCHAR pCopyData;
- if (NdisGetPoolFromPacket(pNdisPacket) == pOpenContext->RecvPacketPool)
- {
- //
- // This is a local copy.
- //
- #ifdef NDIS51
- NdisGetFirstBufferFromPacketSafe(
- pNdisPacket,
- &pNdisBuffer,
- (PVOID *)&pCopyData,
- &BufferLength,
- &TotalLength,
- NormalPagePriority);
- #else
- NdisGetFirstBufferFromPacket(
- pNdisPacket,
- &pNdisBuffer,
- (PVOID *)&pCopyData,
- &BufferLength,
- &TotalLength);
- #endif
- NUIO_ASSERT(BufferLength == TotalLength);
- NUIO_ASSERT(pNdisBuffer != NULL);
- NUIO_ASSERT(pCopyData != NULL); // we would have allocated non-paged pool
- NdisFreePacket(pNdisPacket);
- NdisFreeBuffer(pNdisBuffer);
- NUIO_FREE_MEM(pCopyData);
- }
- else
- {
- NdisReturnPackets(&pNdisPacket, 1);
- }
- }
- VOID
- ndisuioCancelPendingReads(
- IN PNDISUIO_OPEN_CONTEXT pOpenContext
- )
- /*++
- Routine Description:
- Cancel any pending read IRPs queued on the given open.
- Arguments:
- pOpenContext - pointer to open context
- Return Value:
- None
- --*/
- {
- PIRP pIrp;
- PLIST_ENTRY pIrpEntry;
- NUIO_REF_OPEN(pOpenContext); // temp ref - cancel reads
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- while (!NUIO_IS_LIST_EMPTY(&pOpenContext->PendedReads))
- {
- //
- // Get the first pended Read IRP
- //
- pIrpEntry = pOpenContext->PendedReads.Flink;
- pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);
- //
- // Check to see if it is being cancelled.
- //
- if (IoSetCancelRoutine(pIrp, NULL))
- {
- //
- // It isn't being cancelled, and can't be cancelled henceforth.
- //
- NUIO_REMOVE_ENTRY_LIST(pIrpEntry);
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- //
- // Complete the IRP.
- //
- pIrp->IoStatus.Status = STATUS_CANCELLED;
- pIrp->IoStatus.Information = 0;
- DEBUGP(DL_INFO, ("CancelPendingReads: Open %p, IRP %p cancelledn",
- pOpenContext, pIrp));
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- NUIO_DEREF_OPEN(pOpenContext); // took out pended Read for cancelling
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- pOpenContext->PendedReadCount--;
- }
- else
- {
- //
- // It is being cancelled, let the cancel routine handle it.
- //
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- //
- // Give the cancel routine some breathing space, otherwise
- // we might end up examining the same (cancelled) IRP over
- // and over again.
- //
- NUIO_SLEEP(1);
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- }
- }
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- NUIO_DEREF_OPEN(pOpenContext); // temp ref - cancel reads
- }
- VOID
- ndisuioFlushReceiveQueue(
- IN PNDISUIO_OPEN_CONTEXT pOpenContext
- )
- /*++
- Routine Description:
- Free any receive packets queued up on the specified open
- Arguments:
- pOpenContext - pointer to open context
- Return Value:
- None
- --*/
- {
- PLIST_ENTRY pRcvPacketEntry;
- PNDIS_PACKET pRcvPacket;
- NUIO_REF_OPEN(pOpenContext); // temp ref - flushRcvQueue
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- while (!NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
- {
- //
- // Get the first queued receive packet
- //
- pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
- NUIO_REMOVE_ENTRY_LIST(pRcvPacketEntry);
- pOpenContext->RecvPktCount --;
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);
- DEBUGP(DL_LOUD, ("FlushReceiveQueue: open %p, pkt %pn",
- pOpenContext, pRcvPacket));
- ndisuioFreeReceivePacket(pOpenContext, pRcvPacket);
- NUIO_DEREF_OPEN(pOpenContext); // took out pended Read
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- }
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- NUIO_DEREF_OPEN(pOpenContext); // temp ref - flushRcvQueue
- }