NDIS_STATUS NDIS_API PacketReceiveIndicate(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookaheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize) { // upcall on packet arrival POPEN_INSTANCE Open; PLIST_ENTRY PacketListEntry; PNDIS_PACKET pPacket; NDIS_STATUS Status; UINT BytesTransfered = 0; PPACKET_RESERVED pReserved; if (HeaderBufferSize != ETHERNET_HEADER_LENGTH) return NDIS_STATUS_NOT_ACCEPTED; Open = (POPEN_INSTANCE) ProtocolBindingContext; // See if there are any pending reads that we can satisfy NdisAcquireSpinLock(&Open->RcvQSpinLock); // fixed 5.11.97 if (IsListEmpty(&Open->RcvList)) { NdisReleaseSpinLock(&Open->RcvQSpinLock); return NDIS_STATUS_NOT_ACCEPTED; } PacketListEntry = RemoveHeadList(&Open->RcvList); NdisReleaseSpinLock(&Open->RcvQSpinLock); pReserved = CONTAINING_RECORD(PacketListEntry, PACKET_RESERVED, ListElement); pPacket = CONTAINING_RECORD(pReserved, NDIS_PACKET, ProtocolReserved); // Copy the MAC header NdisMoveMemory(RESERVED(pPacket)->lpBuffer, HeaderBuffer, HeaderBufferSize); // Call the Mac to transfer the data portion of the packet NdisTransferData(&Status, Open->AdapterHandle, MacReceiveContext, 0, PacketSize, pPacket, &BytesTransfered); if (Status == NDIS_STATUS_PENDING) return NDIS_STATUS_PENDING; if (Status == NDIS_STATUS_SUCCESS) { PacketTransferDataComplete(Open, pPacket, Status, BytesTransfered); return NDIS_STATUS_SUCCESS; } PacketTransferDataComplete(Open, pPacket, Status, 0); return NDIS_STATUS_SUCCESS; }
VOID NDIS_API PacketUnbindAdapter(OUT PNDIS_STATUS Status, IN POPEN_INSTANCE Open, IN POPEN_INSTANCE junk) { // detach protocol from the NIC clean up any pending I/O requests PLIST_ENTRY PacketListEntry; PNDIS_PACKET pPacket; // The open instance of the device is about to close // We need to complete all pending I/O requests // First we complete any pending read requests NdisAcquireSpinLock(&Open->RcvQSpinLock); while (!IsListEmpty(&Open->RcvList)) { PacketListEntry = RemoveHeadList(&Open->RcvList); pPacket = CONTAINING_RECORD(PacketListEntry, NDIS_PACKET, ProtocolReserved); // complete normally PacketTransferDataComplete(Open, pPacket, NDIS_STATUS_SUCCESS, 0); } NdisReleaseSpinLock(&Open->RcvQSpinLock); // close the adapter NdisCloseAdapter(Status, Open->AdapterHandle); // Save status returned from NdisCloseAdapter for completion routine Open->Status = *Status; if (*Status != NDIS_STATUS_PENDING) PacketUnbindAdapterComplete(Open, *Status); }
/************************************************************ Function that frees the pending requests ************************************************************/ VOID PacketCleanUp( PNDIS_STATUS Status, POPEN_INSTANCE Open ) { PLIST_ENTRY PacketListEntry; PNDIS_PACKET pPacket; PPACKET_RESERVED Reserved; TRACE_ENTER( "Cleanup" ); /*clean all the pending requests*/ NdisAcquireSpinLock( &(Open->RcvQSpinLock) ); while( (PacketListEntry = PacketRemoveHeadList( &(Open->RcvList) )) != NULL ) { IF_VERY_LOUD( "CleanUp - Completing read" ); Reserved = CONTAINING_RECORD( PacketListEntry, PACKET_RESERVED, ListElement ); pPacket = CONTAINING_RECORD( Reserved, NDIS_PACKET, ProtocolReserved ); /*emulate the end of a transfer to wake the processes that are waiting on a request */ PacketTransferDataComplete( Open, pPacket, NDIS_STATUS_SUCCESS, 0 ); } NdisReleaseSpinLock( &(Open->RcvQSpinLock) ); TRACE_LEAVE( "Cleanup" ); return; }
NDIS_STATUS PacketReceiveIndicate ( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize ) { POPEN_INSTANCE open; PIO_STACK_LOCATION irpSp; PIRP irp; PLIST_ENTRY packetListEntry; PNDIS_PACKET pPacket; ULONG sizeToTransfer; NDIS_STATUS status; UINT bytesTransfered = 0; ULONG bufferLength; PPACKET_RESERVED reserved; PMDL pMdl; // DebugPrint(("ReceiveIndicate\n")); open= (POPEN_INSTANCE)ProtocolBindingContext; if (HeaderBufferSize > ETHERNET_HEADER_LENGTH) { return NDIS_STATUS_SUCCESS; } // See if there are any pending read that we can satisfy packetListEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock ); if (packetListEntry == NULL) { // DebugPrint(("No pending read, dropping packets\n")); return NDIS_STATUS_NOT_ACCEPTED; } reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement); pPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); irp = RESERVED(pPacket)->Irp; irpSp = IoGetCurrentIrpStackLocation(irp); // We don't have to worry about the situation where the IRP is cancelled // after we remove it from the queue and before we reset the cancel // routine because the cancel routine has been coded to cancel an IRP // only if it's in the queue. IoSetCancelRoutine(irp, NULL); bufferLength = irpSp->Parameters.Read.Length-ETHERNET_HEADER_LENGTH; sizeToTransfer = (PacketSize < bufferLength) ? PacketSize : bufferLength; NdisMoveMappedMemory( MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority), HeaderBuffer, HeaderBufferSize ); pMdl=IoAllocateMdl( MmGetMdlVirtualAddress(irp->MdlAddress), MmGetMdlByteCount(irp->MdlAddress), FALSE, FALSE, NULL ); if (pMdl == NULL) { // DebugPrint(("Packet: Read-Failed to allocate Mdl\n")); status = NDIS_STATUS_RESOURCES; goto ERROR; } IoBuildPartialMdl( irp->MdlAddress, pMdl, ((PUCHAR)MmGetMdlVirtualAddress(irp->MdlAddress))+ETHERNET_HEADER_LENGTH, 0 ); pMdl->Next = NULL; RESERVED(pPacket)->pMdl=pMdl; NdisChainBufferAtFront(pPacket,pMdl); NdisTransferData( &status, open->AdapterHandle, MacReceiveContext, 0, sizeToTransfer, pPacket, &bytesTransfered ); if (status == NDIS_STATUS_PENDING) { return NDIS_STATUS_SUCCESS; } ERROR: PacketTransferDataComplete( open, pPacket, status, bytesTransfered ); return NDIS_STATUS_SUCCESS; }