3 Copyright(c) 1992-2000 Microsoft Corporation
11 Ndis Intermediate Miniport driver sample. This is a passthru driver.
27 #define MAX_PACKET_POOL_SIZE 0x0000FFFF
28 #define MIN_PACKET_POOL_SIZE 0x000000FF
31 // NDIS version as 0xMMMMmmmm, where M=Major/m=minor (0x00050001 = 5.1);
32 // initially unknown (0)
34 ULONG NdisDotSysVersion = 0x0;
37 #define NDIS_SYS_VERSION_51 0x00050001
42 OUT PNDIS_STATUS Status,
43 IN NDIS_HANDLE BindContext,
44 IN PNDIS_STRING DeviceName,
45 IN PVOID SystemSpecific1,
46 IN PVOID SystemSpecific2
52 Called by NDIS to bind to a miniport below.
56 Status - Return status of bind here.
57 BindContext - Can be passed to NdisCompleteBindAdapter if this call is pended.
58 DeviceName - Device name to bind to. This is passed to NdisOpenAdapter.
59 SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to read per-binding information
60 SystemSpecific2 - Unused
64 NDIS_STATUS_PENDING if this call is pended. In this case call NdisCompleteBindAdapter
66 Anything else Completes this call synchronously
70 NDIS_HANDLE ConfigHandle = NULL;
71 PNDIS_CONFIGURATION_PARAMETER Param;
72 NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings");
73 NDIS_STRING NdisVersionStr = NDIS_STRING_CONST("NdisVersion");
78 BOOLEAN NoCleanUpNeeded = FALSE;
81 UNREFERENCED_PARAMETER(BindContext);
82 UNREFERENCED_PARAMETER(SystemSpecific2);
84 DBGPRINT(("==> Protocol BindAdapter\n"));
89 // Access the configuration section for our binding-specific
92 NdisOpenProtocolConfiguration(Status,
96 if (*Status != NDIS_STATUS_SUCCESS)
100 if (NdisDotSysVersion == 0)
102 NdisReadConfiguration(Status,
105 &NdisVersionStr, // "NdisVersion"
106 NdisParameterInteger);
107 if (*Status != NDIS_STATUS_SUCCESS)
112 NdisDotSysVersion = Param->ParameterData.IntegerData;
117 // Read the "UpperBindings" reserved key that contains a list
118 // of device names representing our miniport instances corresponding
119 // to this lower binding. Since this is a 1:1 IM driver, this key
120 // contains exactly one name.
122 // If we want to implement a N:1 mux driver (N adapter instances
123 // over a single lower binding), then UpperBindings will be a
124 // MULTI_SZ containing a list of device names - we would loop through
125 // this list, calling NdisIMInitializeDeviceInstanceEx once for
128 NdisReadConfiguration(Status,
132 NdisParameterString);
133 if (*Status != NDIS_STATUS_SUCCESS)
139 // Allocate memory for the Adapter structure. This represents both the
140 // protocol context as well as the adapter structure when the miniport
143 // In addition to the base structure, allocate space for the device
146 TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength;
148 NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG);
152 *Status = NDIS_STATUS_RESOURCES;
157 // Initialize the adapter structure. We copy in the IM device
158 // name as well, because we may need to use it in a call to
159 // NdisIMCancelInitializeDeviceInstance. The string returned
160 // by NdisReadConfiguration is active (i.e. available) only
161 // for the duration of this call to our BindAdapter handler.
163 NdisZeroMemory(pAdapt, TotalSize);
164 pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength;
165 pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length;
166 pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT));
167 NdisMoveMemory(pAdapt->DeviceName.Buffer,
168 Param->ParameterData.StringData.Buffer,
169 Param->ParameterData.StringData.MaximumLength);
173 NdisInitializeEvent(&pAdapt->Event);
174 NdisAllocateSpinLock(&pAdapt->Lock);
177 // Allocate a packet pool for sends. We need this to pass sends down.
178 // We cannot use the same packet descriptor that came down to our send
179 // handler (see also NDIS 5.1 packet stacking).
181 NdisAllocatePacketPoolEx(Status,
182 &pAdapt->SendPacketPoolHandle,
183 MIN_PACKET_POOL_SIZE,
184 MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
187 if (*Status != NDIS_STATUS_SUCCESS)
193 // Allocate a packet pool for receives. We need this to indicate receives.
194 // Same consideration as sends (see also NDIS 5.1 packet stacking).
196 NdisAllocatePacketPoolEx(Status,
197 &pAdapt->RecvPacketPoolHandle,
198 MIN_PACKET_POOL_SIZE,
199 MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
200 PROTOCOL_RESERVED_SIZE_IN_PACKET);
202 if (*Status != NDIS_STATUS_SUCCESS)
208 // Now open the adapter below and complete the initialization
210 NdisOpenAdapter(Status,
212 &pAdapt->BindingHandle,
215 sizeof(MediumArray)/sizeof(NDIS_MEDIUM),
222 if (*Status == NDIS_STATUS_PENDING)
224 NdisWaitEvent(&pAdapt->Event, 0);
225 *Status = pAdapt->Status;
228 if (*Status != NDIS_STATUS_SUCCESS)
232 PtReferenceAdapt(pAdapt);
234 #pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW, "Ndis guarantees MediumIndex to be within bounds");
235 pAdapt->Medium = MediumArray[MediumIndex];
238 // Now ask NDIS to initialize our miniport (upper) edge.
239 // Set the flag below to synchronize with a possible call
240 // to our protocol Unbind handler that may come in before
241 // our miniport initialization happens.
243 pAdapt->MiniportInitPending = TRUE;
244 NdisInitializeEvent(&pAdapt->MiniportInitEvent);
246 PtReferenceAdapt(pAdapt);
248 *Status = NdisIMInitializeDeviceInstanceEx(DriverHandle,
252 if (*Status != NDIS_STATUS_SUCCESS)
254 if (pAdapt->MiniportIsHalted == TRUE)
256 NoCleanUpNeeded = TRUE;
259 DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n",
262 if (PtDereferenceAdapt(pAdapt))
270 PtDereferenceAdapt(pAdapt);
275 // Close the configuration handle now - see comments above with
276 // the call to NdisIMInitializeDeviceInstanceEx.
278 if (ConfigHandle != NULL)
280 NdisCloseConfiguration(ConfigHandle);
283 if ((*Status != NDIS_STATUS_SUCCESS) && (NoCleanUpNeeded == FALSE))
287 if (pAdapt->BindingHandle != NULL)
289 NDIS_STATUS LocalStatus;
292 // Close the binding we opened above.
295 NdisResetEvent(&pAdapt->Event);
297 NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle);
298 pAdapt->BindingHandle = NULL;
300 if (LocalStatus == NDIS_STATUS_PENDING)
302 NdisWaitEvent(&pAdapt->Event, 0);
303 LocalStatus = pAdapt->Status;
307 if (PtDereferenceAdapt(pAdapt))
316 DBGPRINT(("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status));
321 PtOpenAdapterComplete(
322 IN NDIS_HANDLE ProtocolBindingContext,
323 IN NDIS_STATUS Status,
324 IN NDIS_STATUS OpenErrorStatus
330 Completion routine for NdisOpenAdapter issued from within the PtBindAdapter. Simply
335 ProtocolBindingContext Pointer to the adapter
336 Status Status of the NdisOpenAdapter call
337 OpenErrorStatus Secondary status(ignored by us).
345 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
347 UNREFERENCED_PARAMETER(OpenErrorStatus);
349 DBGPRINT(("==> PtOpenAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));
350 pAdapt->Status = Status;
351 NdisSetEvent(&pAdapt->Event);
357 OUT PNDIS_STATUS Status,
358 IN NDIS_HANDLE ProtocolBindingContext,
359 IN NDIS_HANDLE UnbindContext
365 Called by NDIS when we are required to unbind to the adapter below.
366 This functions shares functionality with the miniport's HaltHandler.
367 The code should ensure that NdisCloseAdapter and NdisFreeMemory is called
368 only once between the two functions
372 Status Placeholder for return status
373 ProtocolBindingContext Pointer to the adapter structure
374 UnbindContext Context for NdisUnbindComplete() if this pends
378 Status for NdisIMDeinitializeDeviceContext
382 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
383 NDIS_STATUS LocalStatus;
385 UNREFERENCED_PARAMETER(UnbindContext);
387 DBGPRINT(("==> PtUnbindAdapter: Adapt %p\n", pAdapt));
390 // Set the flag that the miniport below is unbinding, so the request handlers will
391 // fail any request comming later
393 NdisAcquireSpinLock(&pAdapt->Lock);
394 pAdapt->UnbindingInProcess = TRUE;
395 if (pAdapt->QueuedRequest == TRUE)
397 pAdapt->QueuedRequest = FALSE;
398 NdisReleaseSpinLock(&pAdapt->Lock);
400 PtRequestComplete(pAdapt,
402 NDIS_STATUS_FAILURE );
407 NdisReleaseSpinLock(&pAdapt->Lock);
411 // Check if we had called NdisIMInitializeDeviceInstanceEx and
412 // we are awaiting a call to MiniportInitialize.
414 if (pAdapt->MiniportInitPending == TRUE)
417 // Try to cancel the pending IMInit process.
419 LocalStatus = NdisIMCancelInitializeDeviceInstance(
421 &pAdapt->DeviceName);
423 if (LocalStatus == NDIS_STATUS_SUCCESS)
426 // Successfully cancelled IM Initialization; our
427 // Miniport Initialize routine will not be called
430 pAdapt->MiniportInitPending = FALSE;
431 ASSERT(pAdapt->MiniportHandle == NULL);
436 // Our Miniport Initialize routine will be called
437 // (may be running on another thread at this time).
438 // Wait for it to finish.
440 NdisWaitEvent(&pAdapt->MiniportInitEvent, 0);
441 ASSERT(pAdapt->MiniportInitPending == FALSE);
448 // Call NDIS to remove our device-instance. We do most of the work
449 // inside the HaltHandler.
451 // The Handle will be NULL if our miniport Halt Handler has been called or
452 // if the IM device was never initialized
455 if (pAdapt->MiniportHandle != NULL)
457 *Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);
459 if (*Status != NDIS_STATUS_SUCCESS)
461 *Status = NDIS_STATUS_FAILURE;
467 // We need to do some work here.
468 // Close the binding below us
469 // and release the memory allocated.
472 if(pAdapt->BindingHandle != NULL)
474 NdisResetEvent(&pAdapt->Event);
476 NdisCloseAdapter(Status, pAdapt->BindingHandle);
479 // Wait for it to complete
481 if(*Status == NDIS_STATUS_PENDING)
483 NdisWaitEvent(&pAdapt->Event, 0);
484 *Status = pAdapt->Status;
486 pAdapt->BindingHandle = NULL;
491 // Both Our MiniportHandle and Binding Handle should not be NULL.
493 *Status = NDIS_STATUS_FAILURE;
498 // Free the memory here, if was not released earlier(by calling the HaltHandler)
500 MPFreeAllPacketPools(pAdapt);
501 NdisFreeSpinLock(&pAdapt->Lock);
502 NdisFreeMemory(pAdapt, 0, 0);
505 DBGPRINT(("<== PtUnbindAdapter: Adapt %p\n", pAdapt));
515 if (ProtHandle != NULL)
517 NdisDeregisterProtocol(&Status, ProtHandle);
521 DBGPRINT(("PtUnloadProtocol: done!\n"));
527 PtCloseAdapterComplete(
528 IN NDIS_HANDLE ProtocolBindingContext,
529 IN NDIS_STATUS Status
535 Completion for the CloseAdapter call.
539 ProtocolBindingContext Pointer to the adapter structure
540 Status Completion status
548 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
550 DBGPRINT(("CloseAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));
551 pAdapt->Status = Status;
552 NdisSetEvent(&pAdapt->Event);
558 IN NDIS_HANDLE ProtocolBindingContext,
559 IN NDIS_STATUS Status
565 Completion for the reset.
569 ProtocolBindingContext Pointer to the adapter structure
570 Status Completion status
579 UNREFERENCED_PARAMETER(ProtocolBindingContext);
580 UNREFERENCED_PARAMETER(Status);
582 // We never issue a reset, so we should not be here.
590 IN NDIS_HANDLE ProtocolBindingContext,
591 IN PNDIS_REQUEST NdisRequest,
592 IN NDIS_STATUS Status
598 Completion handler for the previously posted request. All OIDS
599 are completed by and sent to the same miniport that they were requested for.
600 If Oid == OID_PNP_QUERY_POWER then the data structure needs to returned with all entries =
601 NdisDeviceStateUnspecified
605 ProtocolBindingContext Pointer to the adapter structure
606 NdisRequest The posted request
607 Status Completion status
615 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
616 NDIS_OID Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;
619 // Since our request is not outstanding anymore
621 ASSERT(pAdapt->OutstandingRequests == TRUE);
623 pAdapt->OutstandingRequests = FALSE;
626 // Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.
628 switch (NdisRequest->RequestType)
630 case NdisRequestQueryInformation:
633 // We never pass OID_PNP_QUERY_POWER down.
635 ASSERT(Oid != OID_PNP_QUERY_POWER);
637 if ((Oid == OID_PNP_CAPABILITIES) && (Status == NDIS_STATUS_SUCCESS))
639 MPQueryPNPCapabilities(pAdapt, &Status);
641 *pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
642 *pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
644 if (((Oid == OID_GEN_MAC_OPTIONS)
645 && (Status == NDIS_STATUS_SUCCESS))
646 && (NdisDotSysVersion >= NDIS_SYS_VERSION_51))
649 // Only do this on Windows XP or greater (NDIS.SYS v 5.1);
650 // do not do in Windows 2000 (NDIS.SYS v 5.0))
654 // Remove the no-loopback bit from mac-options. In essence we are
655 // telling NDIS that we can handle loopback. We don't, but the
656 // interface below us does. If we do not do this, then loopback
657 // processing happens both below us and above us. This is wasteful
658 // at best and if Netmon is running, it will see multiple copies
659 // of loopback packets when sniffing above us.
661 // Only the lowest miniport is a stack of layered miniports should
662 // ever report this bit set to NDIS.
664 *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer &= ~NDIS_MAC_OPTION_NO_LOOPBACK;
667 NdisMQueryInformationComplete(pAdapt->MiniportHandle,
671 case NdisRequestSetInformation:
673 ASSERT( Oid != OID_PNP_SET_POWER);
675 *pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;
676 *pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
677 NdisMSetInformationComplete(pAdapt->MiniportHandle,
691 IN NDIS_HANDLE ProtocolBindingContext,
692 IN NDIS_STATUS GeneralStatus,
693 IN PVOID StatusBuffer,
694 IN UINT StatusBufferSize
700 Status handler for the lower-edge(protocol).
704 ProtocolBindingContext Pointer to the adapter structure
705 GeneralStatus Status code
706 StatusBuffer Status buffer
707 StatusBufferSize Size of the status buffer
715 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
718 // Pass up this indication only if the upper edge miniport is initialized
719 // and powered on. Also ignore indications that might be sent by the lower
720 // miniport when it isn't at D0.
722 if ((pAdapt->MiniportHandle != NULL) &&
723 (pAdapt->MPDeviceState == NdisDeviceStateD0) &&
724 (pAdapt->PTDeviceState == NdisDeviceStateD0))
726 if ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) ||
727 (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT))
730 pAdapt->LastIndicatedStatus = GeneralStatus;
732 NdisMIndicateStatus(pAdapt->MiniportHandle,
738 // Save the last indicated media status
742 if ((pAdapt->MiniportHandle != NULL) &&
743 ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) ||
744 (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT)))
746 pAdapt->LatestUnIndicateStatus = GeneralStatus;
755 IN NDIS_HANDLE ProtocolBindingContext
770 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
773 // Pass up this indication only if the upper edge miniport is initialized
774 // and powered on. Also ignore indications that might be sent by the lower
775 // miniport when it isn't at D0.
777 if ((pAdapt->MiniportHandle != NULL) &&
778 (pAdapt->MPDeviceState == NdisDeviceStateD0) &&
779 (pAdapt->PTDeviceState == NdisDeviceStateD0))
781 NdisMIndicateStatusComplete(pAdapt->MiniportHandle);
788 IN NDIS_HANDLE ProtocolBindingContext,
789 IN PNDIS_PACKET Packet,
790 IN NDIS_STATUS Status
796 Called by NDIS when the miniport below had completed a send. We should
797 complete the corresponding upper-edge send this represents.
801 ProtocolBindingContext - Points to ADAPT structure
802 Packet - Low level packet being completed
803 Status - status of send
811 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
813 NDIS_HANDLE PoolHandle;
819 // Determine if the packet we are completing is the one we allocated. If so, then
820 // get the original packet from the reserved area and completed it and free the
821 // allocated packet. If this is the packet that was sent down to us, then just
824 PoolHandle = NdisGetPoolFromPacket(Packet);
825 if (PoolHandle != pAdapt->SendPacketPoolHandle)
828 // We had passed down a packet belonging to the protocol above us.
830 // DBGPRINT(("PtSendComp: Adapt %p, Stacked Packet %p\n", pAdapt, Packet));
832 NdisMSendComplete(pAdapt->MiniportHandle,
841 SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
842 Pkt = SendRsvd->OriginalPkt;
844 #if 1 // IPFW - new code
845 //DbgPrint("SendComplete: packet %p pkt %p\n", Packet, Pkt);
846 if (Pkt == NULL) { //this is a reinjected packet, with no 'father'
847 CleanupReinjected(Packet, SendRsvd->pMbuf, pAdapt);
853 NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
856 NdisDprFreePacket(Packet);
858 NdisMSendComplete(pAdapt->MiniportHandle,
863 // Decrease the outstanding send count
865 ADAPT_DECR_PENDING_SENDS(pAdapt);
870 PtTransferDataComplete(
871 IN NDIS_HANDLE ProtocolBindingContext,
872 IN PNDIS_PACKET Packet,
873 IN NDIS_STATUS Status,
874 IN UINT BytesTransferred
880 Entry point called by NDIS to indicate completion of a call by us
883 See notes under SendComplete.
891 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
893 if(pAdapt->MiniportHandle)
895 NdisMTransferDataComplete(pAdapt->MiniportHandle,
905 IN NDIS_HANDLE ProtocolBindingContext,
906 IN NDIS_HANDLE MacReceiveContext,
907 IN PVOID HeaderBuffer,
908 IN UINT HeaderBufferSize,
909 IN PVOID LookAheadBuffer,
910 IN UINT LookAheadBufferSize,
917 Handle receive data indicated up by the miniport below. We pass
918 it along to the protocol above us.
920 If the miniport below indicates packets, NDIS would more
921 likely call us at our ReceivePacket handler. However we
922 might be called here in certain situations even though
923 the miniport below has indicated a receive packet, e.g.
924 if the miniport had set packet status to NDIS_STATUS_RESOURCES.
928 <see DDK ref page for ProtocolReceive>
932 NDIS_STATUS_SUCCESS if we processed the receive successfully,
933 NDIS_STATUS_XXX error code if we discarded it.
937 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
938 PNDIS_PACKET MyPacket, Packet = NULL;
939 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
940 ULONG Proc = KeGetCurrentProcessorNumber();
942 if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))
944 Status = NDIS_STATUS_FAILURE;
949 // Get at the packet, if any, indicated up by the miniport below.
951 Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
955 // The miniport below did indicate up a packet. Use information
956 // from that packet to construct a new packet to indicate up.
961 // NDIS 5.1 NOTE: Do not reuse the original packet in indicating
962 // up a receive, even if there is sufficient packet stack space.
963 // If we had to do so, we would have had to overwrite the
964 // status field in the original packet to NDIS_STATUS_RESOURCES,
965 // and it is not allowed for protocols to overwrite this field
966 // in received packets.
971 // Get a packet off the pool and indicate that up
973 NdisDprAllocatePacket(&Status,
975 pAdapt->RecvPacketPoolHandle);
977 if (Status == NDIS_STATUS_SUCCESS)
980 // Make our packet point to data from the original
981 // packet. NOTE: this works only because we are
982 // indicating a receive directly from the context of
983 // our receive indication. If we need to queue this
984 // packet and indicate it from another thread context,
985 // we will also have to allocate a new buffer and copy
986 // over the packet contents, OOB data and per-packet
987 // information. This is because the packet data
988 // is available only for the duration of this
989 // receive indication call.
991 NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
992 NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
995 // Get the original packet (it could be the same packet as the
996 // one received or a different one based on the number of layered
997 // miniports below) and set it on the indicated packet so the OOB
998 // data is visible correctly at protocols above. If the IM driver
999 // modifies the packet in any way it should not set the new packet's
1000 // original packet equal to the original packet of the packet that
1001 // was indicated to it from the underlying driver, in this case, the
1002 // IM driver should also ensure that the related per packet info should
1003 // be copied to the new packet.
1004 // we can set the original packet to the original packet of the packet
1005 // indicated from the underlying driver because the driver doesn't modify
1006 // the data content in the packet.
1008 NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
1009 NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
1012 // Copy packet flags.
1014 NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
1017 // Force protocols above to make a copy if they want to hang
1018 // on to data in this packet. This is because we are in our
1019 // Receive handler (not ReceivePacket) and we can't return a
1020 // ref count from here.
1022 NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
1025 // By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim
1026 // this packet as soon as the call to NdisMIndicateReceivePacket
1030 if (pAdapt->MiniportHandle != NULL)
1032 #if 1 /* IPFW: query the firewall */
1034 ret = ipfw2_qhandler_w32(MyPacket, INCOMING,
1035 ProtocolBindingContext);
1037 return 0; //otherwise simply continue
1038 #endif /* end of IPFW code */
1039 NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
1043 // Reclaim the indicated packet. Since we had set its status
1044 // to NDIS_STATUS_RESOURCES, we are guaranteed that protocols
1045 // above are done with it.
1047 NdisDprFreePacket(MyPacket);
1055 // The miniport below us uses the old-style (not packet)
1056 // receive indication. Fall through.
1061 // Fall through if the miniport below us has either not
1062 // indicated a packet or we could not allocate one
1064 pAdapt->ReceivedIndicationFlags[Proc] = TRUE;
1065 if (pAdapt->MiniportHandle == NULL)
1069 switch (pAdapt->Medium)
1071 case NdisMedium802_3:
1073 //DbgPrint("EthIndicateReceive context %p, header at %p len %u, lookahead at %p len %u, packetsize %u\n",ProtocolBindingContext,HeaderBuffer,HeaderBufferSize,LookAheadBuffer,LookAheadBufferSize,PacketSize);
1074 //hexdump(HeaderBuffer,HeaderBufferSize+LookAheadBufferSize,"EthIndicateReceive");
1076 int ret = ipfw2_qhandler_w32_oldstyle(INCOMING, ProtocolBindingContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize);
1078 return NDIS_STATUS_SUCCESS;
1080 NdisMEthIndicateReceive(pAdapt->MiniportHandle,
1085 LookAheadBufferSize,
1089 case NdisMedium802_5:
1090 NdisMTrIndicateReceive(pAdapt->MiniportHandle,
1095 LookAheadBufferSize,
1100 case NdisMediumFddi:
1101 NdisMFddiIndicateReceive(pAdapt->MiniportHandle,
1106 LookAheadBufferSize,
1123 IN NDIS_HANDLE ProtocolBindingContext
1127 Routine Description:
1129 Called by the adapter below us when it is done indicating a batch of
1134 ProtocolBindingContext Pointer to our adapter structure.
1142 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
1143 ULONG Proc = KeGetCurrentProcessorNumber();
1145 /* Warning: this is a poor implementation of the PtReceiveComplete
1146 * made by MS, and it's a well known (but never fixed) issue.
1147 * Since the ProcessorNumber here can be different from the one
1148 * that processed the PtReceive, sometimes NdisMEthIndicateReceiveComplete
1149 * will not be called, causing poor performance in the incoming traffic.
1150 * In our driver, PtReceive is called for IP packets ONLY by particulary
1151 * old NIC drivers, and the poor performance can be seen even
1152 * in traffic not handled by ipfw or dummynet.
1153 * Fortunately, this is quite rare, all the incoming IP packets
1154 * will arrive through PtReceivePacket, and this callback will never
1155 * be called. For reinjected traffic, a workaround is done
1156 * commuting the ReceivedIndicationFlag and calling
1157 * NdisMEthIndicateReceiveComplete manually for each packet.
1160 if (((pAdapt->MiniportHandle != NULL)
1161 && (pAdapt->MPDeviceState == NdisDeviceStateD0))
1162 && (pAdapt->ReceivedIndicationFlags[Proc]))
1164 switch (pAdapt->Medium)
1166 case NdisMedium802_3:
1168 NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);
1171 case NdisMedium802_5:
1172 NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);
1175 case NdisMediumFddi:
1176 NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);
1185 pAdapt->ReceivedIndicationFlags[Proc] = FALSE;
1191 IN NDIS_HANDLE ProtocolBindingContext,
1192 IN PNDIS_PACKET Packet
1196 Routine Description:
1198 ReceivePacket handler. Called by NDIS if the miniport below supports
1199 NDIS 4.0 style receives. Re-package the buffer chain in a new packet
1200 and indicate the new packet to protocols above us. Any context for
1201 packets indicated up must be kept in the MiniportReserved field.
1203 NDIS 5.1 - packet stacking - if there is sufficient "stack space" in
1204 the packet passed to us, we can use the same packet in a receive
1209 ProtocolBindingContext - Pointer to our adapter structure.
1210 Packet - Pointer to the packet
1214 == 0 -> We are done with the packet
1215 != 0 -> We will keep the packet and call NdisReturnPackets() this
1216 many times when done.
1219 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
1221 PNDIS_PACKET MyPacket;
1225 // Drop the packet silently if the upper miniport edge isn't initialized or
1226 // the miniport edge is in low power state
1228 if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))
1235 // Check if we can reuse the same packet for indicating up.
1236 // See also: PtReceive().
1238 (VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);
1242 // We can reuse "Packet". Indicate it up and be done with it.
1244 Status = NDIS_GET_PACKET_STATUS(Packet);
1245 NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1);
1246 return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
1251 // Get a packet off the pool and indicate that up
1253 NdisDprAllocatePacket(&Status,
1255 pAdapt->RecvPacketPoolHandle);
1257 if (Status == NDIS_STATUS_SUCCESS)
1259 PRECV_RSVD RecvRsvd;
1261 RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);
1262 RecvRsvd->OriginalPkt = Packet;
1264 NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
1265 NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
1268 // Get the original packet (it could be the same packet as the one
1269 // received or a different one based on the number of layered miniports
1270 // below) and set it on the indicated packet so the OOB data is visible
1271 // correctly to protocols above us.
1273 NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
1278 NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
1280 Status = NDIS_GET_PACKET_STATUS(Packet);
1282 NDIS_SET_PACKET_STATUS(MyPacket, Status);
1283 NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));
1285 if (pAdapt->MiniportHandle != NULL)
1287 #if 1 /* IPFW: query the firewall */
1289 ret = ipfw2_qhandler_w32(MyPacket, INCOMING,
1290 ProtocolBindingContext);
1292 return 0; //otherwise simply continue
1293 #endif /* end of IPFW code */
1294 NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
1298 // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES
1299 // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since
1300 // it might have changed! Use the value saved in the local variable.
1302 if (Status == NDIS_STATUS_RESOURCES)
1305 // Our ReturnPackets handler will not be called for this packet.
1306 // We should reclaim it right here.
1308 NdisDprFreePacket(MyPacket);
1311 return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
1316 // We are out of packets. Silently drop it.
1325 IN NDIS_HANDLE ProtocolBindingContext,
1326 IN PNET_PNP_EVENT pNetPnPEvent
1330 Routine Description:
1332 This is called by NDIS to notify us of a PNP event related to a lower
1333 binding. Based on the event, this dispatches to other helper routines.
1335 NDIS 5.1: forward this event to the upper protocol(s) by calling
1336 NdisIMNotifyPnPEvent.
1340 ProtocolBindingContext - Pointer to our adapter structure. Can be NULL
1341 for "global" notifications
1343 pNetPnPEvent - Pointer to the PNP event to be processed.
1347 NDIS_STATUS code indicating status of event processing.
1351 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
1352 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1354 DBGPRINT(("PtPnPHandler: Adapt %p, Event %d\n", pAdapt, pNetPnPEvent->NetEvent));
1356 switch (pNetPnPEvent->NetEvent)
1358 case NetEventSetPower:
1359 Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);
1362 case NetEventReconfigure:
1363 Status = PtPnPNetEventReconfigure(pAdapt, pNetPnPEvent);
1369 // Pass on this notification to protocol(s) above, before
1370 // doing anything else with it.
1372 if (pAdapt && pAdapt->MiniportHandle)
1374 Status = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
1377 Status = NDIS_STATUS_SUCCESS;
1389 PtPnPNetEventReconfigure(
1391 IN PNET_PNP_EVENT pNetPnPEvent
1394 Routine Description:
1396 This routine is called from NDIS to notify our protocol edge of a
1397 reconfiguration of parameters for either a specific binding (pAdapt
1398 is not NULL), or global parameters if any (pAdapt is NULL).
1402 pAdapt - Pointer to our adapter structure.
1403 pNetPnPEvent - the reconfigure event
1411 NDIS_STATUS ReconfigStatus = NDIS_STATUS_SUCCESS;
1412 NDIS_STATUS ReturnStatus = NDIS_STATUS_SUCCESS;
1417 // Is this is a global reconfiguration notification ?
1422 // An important event that causes this notification to us is if
1423 // one of our upper-edge miniport instances was enabled after being
1424 // disabled earlier, e.g. from Device Manager in Win2000. Note that
1425 // NDIS calls this because we had set up an association between our
1426 // miniport and protocol entities by calling NdisIMAssociateMiniport.
1428 // Since we would have torn down the lower binding for that miniport,
1429 // we need NDIS' assistance to re-bind to the lower miniport. The
1430 // call to NdisReEnumerateProtocolBindings does exactly that.
1432 NdisReEnumerateProtocolBindings (ProtHandle);
1439 // Pass on this notification to protocol(s) above before doing anything
1442 if (pAdapt->MiniportHandle)
1444 ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
1448 ReconfigStatus = NDIS_STATUS_SUCCESS;
1452 DBGPRINT(("<==PtPNPNetEventReconfigure: pAdapt %p\n", pAdapt));
1456 // Overwrite status with what upper-layer protocol(s) returned.
1458 ReconfigStatus = ReturnStatus;
1461 return ReconfigStatus;
1466 PtPnPNetEventSetPower(
1468 IN PNET_PNP_EVENT pNetPnPEvent
1471 Routine Description:
1473 This is a notification to our protocol edge of the power state
1474 of the lower miniport. If it is going to a low-power state, we must
1475 wait here for all outstanding sends and requests to complete.
1477 NDIS 5.1: Since we use packet stacking, it is not sufficient to
1478 check usage of our local send packet pool to detect whether or not
1479 all outstanding sends have completed. For this, use the new API
1480 NdisQueryPendingIOCount.
1482 NDIS 5.1: Use the 5.1 API NdisIMNotifyPnPEvent to pass on PnP
1483 notifications to upper protocol(s).
1487 pAdapt - Pointer to the adpater structure
1488 pNetPnPEvent - The Net Pnp Event. this contains the new device state
1492 NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols.
1496 PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);
1497 NDIS_DEVICE_POWER_STATE PrevDeviceState = pAdapt->PTDeviceState;
1499 NDIS_STATUS ReturnStatus;
1501 ReturnStatus = NDIS_STATUS_SUCCESS;
1504 // Set the Internal Device State, this blocks all new sends or receives
1506 NdisAcquireSpinLock(&pAdapt->Lock);
1507 pAdapt->PTDeviceState = *pDeviceState;
1510 // Check if the miniport below is going to a low power state.
1512 if (pAdapt->PTDeviceState > NdisDeviceStateD0)
1515 // If the miniport below is going to standby, fail all incoming requests
1517 if (PrevDeviceState == NdisDeviceStateD0)
1519 pAdapt->StandingBy = TRUE;
1522 NdisReleaseSpinLock(&pAdapt->Lock);
1526 // Notify upper layer protocol(s) first.
1528 if (pAdapt->MiniportHandle != NULL)
1530 ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
1535 // Wait for outstanding sends and requests to complete.
1537 while (pAdapt->OutstandingSends != 0)
1542 while (pAdapt->OutstandingRequests == TRUE)
1545 // sleep till outstanding requests complete
1551 // If the below miniport is going to low power state, complete the queued request
1553 NdisAcquireSpinLock(&pAdapt->Lock);
1554 if (pAdapt->QueuedRequest)
1556 pAdapt->QueuedRequest = FALSE;
1557 NdisReleaseSpinLock(&pAdapt->Lock);
1558 PtRequestComplete(pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE);
1562 NdisReleaseSpinLock(&pAdapt->Lock);
1566 ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);
1567 ASSERT(pAdapt->OutstandingRequests == FALSE);
1572 // If the physical miniport is powering up (from Low power state to D0),
1575 if (PrevDeviceState > NdisDeviceStateD0)
1577 pAdapt->StandingBy = FALSE;
1580 // The device below is being turned on. If we had a request
1581 // pending, send it down now.
1583 if (pAdapt->QueuedRequest == TRUE)
1585 pAdapt->QueuedRequest = FALSE;
1587 pAdapt->OutstandingRequests = TRUE;
1588 NdisReleaseSpinLock(&pAdapt->Lock);
1590 NdisRequest(&Status,
1591 pAdapt->BindingHandle,
1594 if (Status != NDIS_STATUS_PENDING)
1596 PtRequestComplete(pAdapt,
1604 NdisReleaseSpinLock(&pAdapt->Lock);
1610 // Pass on this notification to protocol(s) above
1612 if (pAdapt->MiniportHandle)
1614 ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
1620 return ReturnStatus;
1628 NdisAcquireSpinLock(&pAdapt->Lock);
1630 ASSERT(pAdapt->RefCount >= 0);
1632 pAdapt->RefCount ++;
1633 NdisReleaseSpinLock(&pAdapt->Lock);
1642 NdisAcquireSpinLock(&pAdapt->Lock);
1644 ASSERT(pAdapt->RefCount > 0);
1648 if (pAdapt->RefCount == 0)
1650 NdisReleaseSpinLock(&pAdapt->Lock);
1653 // Free all resources on this adapter structure.
1655 MPFreeAllPacketPools (pAdapt);;
1656 NdisFreeSpinLock(&pAdapt->Lock);
1657 NdisFreeMemory(pAdapt, 0 , 0);
1664 NdisReleaseSpinLock(&pAdapt->Lock);