--- /dev/null
+/*++\r
+\r
+Copyright(c) 1992-2000 Microsoft Corporation\r
+\r
+Module Name:\r
+\r
+ protocol.c\r
+\r
+Abstract:\r
+\r
+ Ndis Intermediate Miniport driver sample. This is a passthru driver.\r
+\r
+Author:\r
+\r
+Environment:\r
+\r
+\r
+Revision History:\r
+\r
+\r
+--*/\r
+\r
+\r
+#include "precomp.h"\r
+#pragma hdrstop\r
+\r
+#define MAX_PACKET_POOL_SIZE 0x0000FFFF\r
+#define MIN_PACKET_POOL_SIZE 0x000000FF\r
+\r
+//\r
+// NDIS version as 0xMMMMmmmm, where M=Major/m=minor (0x00050001 = 5.1); \r
+// initially unknown (0)\r
+// \r
+ULONG NdisDotSysVersion = 0x0;\r
+\r
+\r
+#define NDIS_SYS_VERSION_51 0x00050001\r
+\r
+\r
+VOID\r
+PtBindAdapter(\r
+ OUT PNDIS_STATUS Status,\r
+ IN NDIS_HANDLE BindContext,\r
+ IN PNDIS_STRING DeviceName,\r
+ IN PVOID SystemSpecific1,\r
+ IN PVOID SystemSpecific2\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Called by NDIS to bind to a miniport below.\r
+\r
+Arguments:\r
+\r
+ Status - Return status of bind here.\r
+ BindContext - Can be passed to NdisCompleteBindAdapter if this call is pended.\r
+ DeviceName - Device name to bind to. This is passed to NdisOpenAdapter.\r
+ SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to read per-binding information\r
+ SystemSpecific2 - Unused\r
+\r
+Return Value:\r
+\r
+ NDIS_STATUS_PENDING if this call is pended. In this case call NdisCompleteBindAdapter\r
+ to complete.\r
+ Anything else Completes this call synchronously\r
+\r
+--*/\r
+{\r
+ NDIS_HANDLE ConfigHandle = NULL;\r
+ PNDIS_CONFIGURATION_PARAMETER Param;\r
+ NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings");\r
+ NDIS_STRING NdisVersionStr = NDIS_STRING_CONST("NdisVersion");\r
+ PADAPT pAdapt = NULL;\r
+ NDIS_STATUS Sts;\r
+ UINT MediumIndex;\r
+ ULONG TotalSize;\r
+ BOOLEAN NoCleanUpNeeded = FALSE;\r
+\r
+\r
+ UNREFERENCED_PARAMETER(BindContext);\r
+ UNREFERENCED_PARAMETER(SystemSpecific2);\r
+ \r
+ DBGPRINT(("==> Protocol BindAdapter\n"));\r
+\r
+ do\r
+ {\r
+ //\r
+ // Access the configuration section for our binding-specific\r
+ // parameters.\r
+ //\r
+ NdisOpenProtocolConfiguration(Status,\r
+ &ConfigHandle,\r
+ SystemSpecific1);\r
+\r
+ if (*Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+ if (NdisDotSysVersion == 0)\r
+ {\r
+ NdisReadConfiguration(Status,\r
+ &Param,\r
+ ConfigHandle,\r
+ &NdisVersionStr, // "NdisVersion"\r
+ NdisParameterInteger);\r
+ if (*Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+ \r
+ NdisDotSysVersion = Param->ParameterData.IntegerData;\r
+ }\r
+ \r
+\r
+ //\r
+ // Read the "UpperBindings" reserved key that contains a list\r
+ // of device names representing our miniport instances corresponding\r
+ // to this lower binding. Since this is a 1:1 IM driver, this key\r
+ // contains exactly one name.\r
+ //\r
+ // If we want to implement a N:1 mux driver (N adapter instances\r
+ // over a single lower binding), then UpperBindings will be a\r
+ // MULTI_SZ containing a list of device names - we would loop through\r
+ // this list, calling NdisIMInitializeDeviceInstanceEx once for\r
+ // each name in it.\r
+ //\r
+ NdisReadConfiguration(Status,\r
+ &Param,\r
+ ConfigHandle,\r
+ &DeviceStr,\r
+ NdisParameterString);\r
+ if (*Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Allocate memory for the Adapter structure. This represents both the\r
+ // protocol context as well as the adapter structure when the miniport\r
+ // is initialized.\r
+ //\r
+ // In addition to the base structure, allocate space for the device\r
+ // instance string.\r
+ //\r
+ TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength;\r
+\r
+ NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG);\r
+\r
+ if (pAdapt == NULL)\r
+ {\r
+ *Status = NDIS_STATUS_RESOURCES;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Initialize the adapter structure. We copy in the IM device\r
+ // name as well, because we may need to use it in a call to\r
+ // NdisIMCancelInitializeDeviceInstance. The string returned\r
+ // by NdisReadConfiguration is active (i.e. available) only\r
+ // for the duration of this call to our BindAdapter handler.\r
+ //\r
+ NdisZeroMemory(pAdapt, TotalSize);\r
+ pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength;\r
+ pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length;\r
+ pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT));\r
+ NdisMoveMemory(pAdapt->DeviceName.Buffer,\r
+ Param->ParameterData.StringData.Buffer,\r
+ Param->ParameterData.StringData.MaximumLength);\r
+\r
+\r
+\r
+ NdisInitializeEvent(&pAdapt->Event);\r
+ NdisAllocateSpinLock(&pAdapt->Lock);\r
+\r
+ //\r
+ // Allocate a packet pool for sends. We need this to pass sends down.\r
+ // We cannot use the same packet descriptor that came down to our send\r
+ // handler (see also NDIS 5.1 packet stacking).\r
+ //\r
+ NdisAllocatePacketPoolEx(Status,\r
+ &pAdapt->SendPacketPoolHandle,\r
+ MIN_PACKET_POOL_SIZE,\r
+ MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,\r
+ sizeof(SEND_RSVD));\r
+\r
+ if (*Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Allocate a packet pool for receives. We need this to indicate receives.\r
+ // Same consideration as sends (see also NDIS 5.1 packet stacking).\r
+ //\r
+ NdisAllocatePacketPoolEx(Status,\r
+ &pAdapt->RecvPacketPoolHandle,\r
+ MIN_PACKET_POOL_SIZE,\r
+ MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,\r
+ PROTOCOL_RESERVED_SIZE_IN_PACKET);\r
+\r
+ if (*Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Now open the adapter below and complete the initialization\r
+ //\r
+ NdisOpenAdapter(Status,\r
+ &Sts,\r
+ &pAdapt->BindingHandle,\r
+ &MediumIndex,\r
+ MediumArray,\r
+ sizeof(MediumArray)/sizeof(NDIS_MEDIUM),\r
+ ProtHandle,\r
+ pAdapt,\r
+ DeviceName,\r
+ 0,\r
+ NULL);\r
+\r
+ if (*Status == NDIS_STATUS_PENDING)\r
+ {\r
+ NdisWaitEvent(&pAdapt->Event, 0);\r
+ *Status = pAdapt->Status;\r
+ }\r
+\r
+ if (*Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ break;\r
+ }\r
+ PtReferenceAdapt(pAdapt);\r
+\r
+#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW, "Ndis guarantees MediumIndex to be within bounds");\r
+ pAdapt->Medium = MediumArray[MediumIndex];\r
+\r
+ //\r
+ // Now ask NDIS to initialize our miniport (upper) edge.\r
+ // Set the flag below to synchronize with a possible call\r
+ // to our protocol Unbind handler that may come in before\r
+ // our miniport initialization happens.\r
+ //\r
+ pAdapt->MiniportInitPending = TRUE;\r
+ NdisInitializeEvent(&pAdapt->MiniportInitEvent);\r
+\r
+ PtReferenceAdapt(pAdapt);\r
+\r
+ *Status = NdisIMInitializeDeviceInstanceEx(DriverHandle,\r
+ &pAdapt->DeviceName,\r
+ pAdapt);\r
+\r
+ if (*Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ if (pAdapt->MiniportIsHalted == TRUE)\r
+ {\r
+ NoCleanUpNeeded = TRUE;\r
+ }\r
+ \r
+ DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n",\r
+ pAdapt, *Status));\r
+ \r
+ if (PtDereferenceAdapt(pAdapt))\r
+ {\r
+ pAdapt = NULL;\r
+ }\r
+ \r
+ break;\r
+ }\r
+ \r
+ PtDereferenceAdapt(pAdapt);\r
+\r
+ } while(FALSE);\r
+\r
+ //\r
+ // Close the configuration handle now - see comments above with\r
+ // the call to NdisIMInitializeDeviceInstanceEx.\r
+ //\r
+ if (ConfigHandle != NULL)\r
+ {\r
+ NdisCloseConfiguration(ConfigHandle);\r
+ }\r
+\r
+ if ((*Status != NDIS_STATUS_SUCCESS) && (NoCleanUpNeeded == FALSE))\r
+ {\r
+ if (pAdapt != NULL)\r
+ {\r
+ if (pAdapt->BindingHandle != NULL)\r
+ {\r
+ NDIS_STATUS LocalStatus;\r
+\r
+ //\r
+ // Close the binding we opened above.\r
+ //\r
+\r
+ NdisResetEvent(&pAdapt->Event);\r
+ \r
+ NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle);\r
+ pAdapt->BindingHandle = NULL;\r
+\r
+ if (LocalStatus == NDIS_STATUS_PENDING)\r
+ {\r
+ NdisWaitEvent(&pAdapt->Event, 0);\r
+ LocalStatus = pAdapt->Status;\r
+\r
+ \r
+ }\r
+ if (PtDereferenceAdapt(pAdapt))\r
+ {\r
+ pAdapt = NULL;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ DBGPRINT(("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status));\r
+}\r
+\r
+\r
+VOID\r
+PtOpenAdapterComplete(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN NDIS_STATUS Status,\r
+ IN NDIS_STATUS OpenErrorStatus\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Completion routine for NdisOpenAdapter issued from within the PtBindAdapter. Simply\r
+ unblock the caller.\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext Pointer to the adapter\r
+ Status Status of the NdisOpenAdapter call\r
+ OpenErrorStatus Secondary status(ignored by us).\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt =(PADAPT)ProtocolBindingContext;\r
+ \r
+ UNREFERENCED_PARAMETER(OpenErrorStatus);\r
+ \r
+ DBGPRINT(("==> PtOpenAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));\r
+ pAdapt->Status = Status;\r
+ NdisSetEvent(&pAdapt->Event);\r
+}\r
+\r
+\r
+VOID\r
+PtUnbindAdapter(\r
+ OUT PNDIS_STATUS Status,\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN NDIS_HANDLE UnbindContext\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Called by NDIS when we are required to unbind to the adapter below.\r
+ This functions shares functionality with the miniport's HaltHandler.\r
+ The code should ensure that NdisCloseAdapter and NdisFreeMemory is called\r
+ only once between the two functions\r
+\r
+Arguments:\r
+\r
+ Status Placeholder for return status\r
+ ProtocolBindingContext Pointer to the adapter structure\r
+ UnbindContext Context for NdisUnbindComplete() if this pends\r
+\r
+Return Value:\r
+\r
+ Status for NdisIMDeinitializeDeviceContext\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt =(PADAPT)ProtocolBindingContext;\r
+ NDIS_STATUS LocalStatus;\r
+\r
+ UNREFERENCED_PARAMETER(UnbindContext);\r
+ \r
+ DBGPRINT(("==> PtUnbindAdapter: Adapt %p\n", pAdapt));\r
+\r
+ //\r
+ // Set the flag that the miniport below is unbinding, so the request handlers will\r
+ // fail any request comming later\r
+ // \r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ pAdapt->UnbindingInProcess = TRUE;\r
+ if (pAdapt->QueuedRequest == TRUE)\r
+ {\r
+ pAdapt->QueuedRequest = FALSE;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+ PtRequestComplete(pAdapt,\r
+ &pAdapt->Request,\r
+ NDIS_STATUS_FAILURE );\r
+\r
+ }\r
+ else\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ }\r
+#ifndef WIN9X\r
+ //\r
+ // Check if we had called NdisIMInitializeDeviceInstanceEx and\r
+ // we are awaiting a call to MiniportInitialize.\r
+ //\r
+ if (pAdapt->MiniportInitPending == TRUE)\r
+ {\r
+ //\r
+ // Try to cancel the pending IMInit process.\r
+ //\r
+ LocalStatus = NdisIMCancelInitializeDeviceInstance(\r
+ DriverHandle,\r
+ &pAdapt->DeviceName);\r
+\r
+ if (LocalStatus == NDIS_STATUS_SUCCESS)\r
+ {\r
+ //\r
+ // Successfully cancelled IM Initialization; our\r
+ // Miniport Initialize routine will not be called\r
+ // for this device.\r
+ //\r
+ pAdapt->MiniportInitPending = FALSE;\r
+ ASSERT(pAdapt->MiniportHandle == NULL);\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // Our Miniport Initialize routine will be called\r
+ // (may be running on another thread at this time).\r
+ // Wait for it to finish.\r
+ //\r
+ NdisWaitEvent(&pAdapt->MiniportInitEvent, 0);\r
+ ASSERT(pAdapt->MiniportInitPending == FALSE);\r
+ }\r
+\r
+ }\r
+#endif // !WIN9X\r
+\r
+ //\r
+ // Call NDIS to remove our device-instance. We do most of the work\r
+ // inside the HaltHandler.\r
+ //\r
+ // The Handle will be NULL if our miniport Halt Handler has been called or\r
+ // if the IM device was never initialized\r
+ //\r
+ \r
+ if (pAdapt->MiniportHandle != NULL)\r
+ {\r
+ *Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);\r
+\r
+ if (*Status != NDIS_STATUS_SUCCESS)\r
+ {\r
+ *Status = NDIS_STATUS_FAILURE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // We need to do some work here. \r
+ // Close the binding below us \r
+ // and release the memory allocated.\r
+ //\r
+ \r
+ if(pAdapt->BindingHandle != NULL)\r
+ {\r
+ NdisResetEvent(&pAdapt->Event);\r
+\r
+ NdisCloseAdapter(Status, pAdapt->BindingHandle);\r
+\r
+ //\r
+ // Wait for it to complete\r
+ //\r
+ if(*Status == NDIS_STATUS_PENDING)\r
+ {\r
+ NdisWaitEvent(&pAdapt->Event, 0);\r
+ *Status = pAdapt->Status;\r
+ }\r
+ pAdapt->BindingHandle = NULL;\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // Both Our MiniportHandle and Binding Handle should not be NULL.\r
+ //\r
+ *Status = NDIS_STATUS_FAILURE;\r
+ ASSERT(0);\r
+ }\r
+\r
+ //\r
+ // Free the memory here, if was not released earlier(by calling the HaltHandler)\r
+ //\r
+ MPFreeAllPacketPools(pAdapt);\r
+ NdisFreeSpinLock(&pAdapt->Lock);\r
+ NdisFreeMemory(pAdapt, 0, 0);\r
+ }\r
+\r
+ DBGPRINT(("<== PtUnbindAdapter: Adapt %p\n", pAdapt));\r
+}\r
+\r
+VOID\r
+PtUnloadProtocol(\r
+ VOID\r
+)\r
+{\r
+ NDIS_STATUS Status;\r
+\r
+ if (ProtHandle != NULL)\r
+ {\r
+ NdisDeregisterProtocol(&Status, ProtHandle);\r
+ ProtHandle = NULL;\r
+ }\r
+\r
+ DBGPRINT(("PtUnloadProtocol: done!\n"));\r
+}\r
+\r
+\r
+\r
+VOID\r
+PtCloseAdapterComplete(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN NDIS_STATUS Status\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Completion for the CloseAdapter call.\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext Pointer to the adapter structure\r
+ Status Completion status\r
+\r
+Return Value:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt =(PADAPT)ProtocolBindingContext;\r
+\r
+ DBGPRINT(("CloseAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));\r
+ pAdapt->Status = Status;\r
+ NdisSetEvent(&pAdapt->Event);\r
+}\r
+\r
+\r
+VOID\r
+PtResetComplete(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN NDIS_STATUS Status\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Completion for the reset.\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext Pointer to the adapter structure\r
+ Status Completion status\r
+\r
+Return Value:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+\r
+ UNREFERENCED_PARAMETER(ProtocolBindingContext);\r
+ UNREFERENCED_PARAMETER(Status);\r
+ //\r
+ // We never issue a reset, so we should not be here.\r
+ //\r
+ ASSERT(0);\r
+}\r
+\r
+\r
+VOID\r
+PtRequestComplete(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN PNDIS_REQUEST NdisRequest,\r
+ IN NDIS_STATUS Status\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Completion handler for the previously posted request. All OIDS\r
+ are completed by and sent to the same miniport that they were requested for.\r
+ If Oid == OID_PNP_QUERY_POWER then the data structure needs to returned with all entries =\r
+ NdisDeviceStateUnspecified\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext Pointer to the adapter structure\r
+ NdisRequest The posted request\r
+ Status Completion status\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)ProtocolBindingContext;\r
+ NDIS_OID Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;\r
+\r
+ //\r
+ // Since our request is not outstanding anymore\r
+ //\r
+ ASSERT(pAdapt->OutstandingRequests == TRUE);\r
+\r
+ pAdapt->OutstandingRequests = FALSE;\r
+\r
+ //\r
+ // Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.\r
+ //\r
+ switch (NdisRequest->RequestType)\r
+ {\r
+ case NdisRequestQueryInformation:\r
+\r
+ //\r
+ // We never pass OID_PNP_QUERY_POWER down.\r
+ //\r
+ ASSERT(Oid != OID_PNP_QUERY_POWER);\r
+\r
+ if ((Oid == OID_PNP_CAPABILITIES) && (Status == NDIS_STATUS_SUCCESS))\r
+ {\r
+ MPQueryPNPCapabilities(pAdapt, &Status);\r
+ }\r
+ *pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;\r
+ *pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;\r
+\r
+ if (((Oid == OID_GEN_MAC_OPTIONS) \r
+ && (Status == NDIS_STATUS_SUCCESS))\r
+ && (NdisDotSysVersion >= NDIS_SYS_VERSION_51))\r
+ {\r
+ //\r
+ // Only do this on Windows XP or greater (NDIS.SYS v 5.1); \r
+ // do not do in Windows 2000 (NDIS.SYS v 5.0))\r
+ //\r
+ \r
+ //\r
+ // Remove the no-loopback bit from mac-options. In essence we are\r
+ // telling NDIS that we can handle loopback. We don't, but the\r
+ // interface below us does. If we do not do this, then loopback\r
+ // processing happens both below us and above us. This is wasteful\r
+ // at best and if Netmon is running, it will see multiple copies\r
+ // of loopback packets when sniffing above us.\r
+ //\r
+ // Only the lowest miniport is a stack of layered miniports should\r
+ // ever report this bit set to NDIS.\r
+ //\r
+ *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer &= ~NDIS_MAC_OPTION_NO_LOOPBACK;\r
+ }\r
+\r
+ NdisMQueryInformationComplete(pAdapt->MiniportHandle,\r
+ Status);\r
+ break;\r
+\r
+ case NdisRequestSetInformation:\r
+\r
+ ASSERT( Oid != OID_PNP_SET_POWER);\r
+\r
+ *pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;\r
+ *pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;\r
+ NdisMSetInformationComplete(pAdapt->MiniportHandle,\r
+ Status);\r
+ break;\r
+\r
+ default:\r
+ ASSERT(0);\r
+ break;\r
+ }\r
+ \r
+}\r
+\r
+\r
+VOID\r
+PtStatus(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN NDIS_STATUS GeneralStatus,\r
+ IN PVOID StatusBuffer,\r
+ IN UINT StatusBufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Status handler for the lower-edge(protocol).\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext Pointer to the adapter structure\r
+ GeneralStatus Status code\r
+ StatusBuffer Status buffer\r
+ StatusBufferSize Size of the status buffer\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)ProtocolBindingContext;\r
+\r
+ //\r
+ // Pass up this indication only if the upper edge miniport is initialized\r
+ // and powered on. Also ignore indications that might be sent by the lower\r
+ // miniport when it isn't at D0.\r
+ //\r
+ if ((pAdapt->MiniportHandle != NULL) &&\r
+ (pAdapt->MPDeviceState == NdisDeviceStateD0) &&\r
+ (pAdapt->PTDeviceState == NdisDeviceStateD0)) \r
+ {\r
+ if ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) || \r
+ (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT))\r
+ {\r
+ \r
+ pAdapt->LastIndicatedStatus = GeneralStatus;\r
+ }\r
+ NdisMIndicateStatus(pAdapt->MiniportHandle,\r
+ GeneralStatus,\r
+ StatusBuffer,\r
+ StatusBufferSize);\r
+ }\r
+ //\r
+ // Save the last indicated media status \r
+ //\r
+ else\r
+ {\r
+ if ((pAdapt->MiniportHandle != NULL) && \r
+ ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) || \r
+ (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT)))\r
+ {\r
+ pAdapt->LatestUnIndicateStatus = GeneralStatus;\r
+ }\r
+ }\r
+ \r
+}\r
+\r
+\r
+VOID\r
+PtStatusComplete(\r
+ IN NDIS_HANDLE ProtocolBindingContext\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+\r
+Return Value:\r
+\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)ProtocolBindingContext;\r
+\r
+ //\r
+ // Pass up this indication only if the upper edge miniport is initialized\r
+ // and powered on. Also ignore indications that might be sent by the lower\r
+ // miniport when it isn't at D0.\r
+ //\r
+ if ((pAdapt->MiniportHandle != NULL) &&\r
+ (pAdapt->MPDeviceState == NdisDeviceStateD0) &&\r
+ (pAdapt->PTDeviceState == NdisDeviceStateD0)) \r
+ {\r
+ NdisMIndicateStatusComplete(pAdapt->MiniportHandle);\r
+ }\r
+}\r
+\r
+\r
+VOID\r
+PtSendComplete(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN PNDIS_PACKET Packet,\r
+ IN NDIS_STATUS Status\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Called by NDIS when the miniport below had completed a send. We should\r
+ complete the corresponding upper-edge send this represents.\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext - Points to ADAPT structure\r
+ Packet - Low level packet being completed\r
+ Status - status of send\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)ProtocolBindingContext;\r
+ PNDIS_PACKET Pkt; \r
+ NDIS_HANDLE PoolHandle;\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // Packet stacking:\r
+ //\r
+ // Determine if the packet we are completing is the one we allocated. If so, then\r
+ // get the original packet from the reserved area and completed it and free the\r
+ // allocated packet. If this is the packet that was sent down to us, then just\r
+ // complete it\r
+ //\r
+ PoolHandle = NdisGetPoolFromPacket(Packet);\r
+ if (PoolHandle != pAdapt->SendPacketPoolHandle)\r
+ {\r
+ //\r
+ // We had passed down a packet belonging to the protocol above us.\r
+ //\r
+ // DBGPRINT(("PtSendComp: Adapt %p, Stacked Packet %p\n", pAdapt, Packet));\r
+\r
+ NdisMSendComplete(pAdapt->MiniportHandle,\r
+ Packet,\r
+ Status);\r
+ }\r
+ else\r
+#endif // NDIS51\r
+ {\r
+ PSEND_RSVD SendRsvd;\r
+\r
+ SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);\r
+ Pkt = SendRsvd->OriginalPkt;\r
+ \r
+#ifndef WIN9X\r
+ NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);\r
+#endif\r
+ \r
+ NdisDprFreePacket(Packet);\r
+\r
+ NdisMSendComplete(pAdapt->MiniportHandle,\r
+ Pkt,\r
+ Status);\r
+ }\r
+ //\r
+ // Decrease the outstanding send count\r
+ //\r
+ ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+} \r
+\r
+\r
+VOID\r
+PtTransferDataComplete(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN PNDIS_PACKET Packet,\r
+ IN NDIS_STATUS Status,\r
+ IN UINT BytesTransferred\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Entry point called by NDIS to indicate completion of a call by us\r
+ to NdisTransferData.\r
+\r
+ See notes under SendComplete.\r
+\r
+Arguments:\r
+\r
+Return Value:\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt =(PADAPT)ProtocolBindingContext;\r
+\r
+ if(pAdapt->MiniportHandle)\r
+ {\r
+ NdisMTransferDataComplete(pAdapt->MiniportHandle,\r
+ Packet,\r
+ Status,\r
+ BytesTransferred);\r
+ }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+PtReceive(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN NDIS_HANDLE MacReceiveContext,\r
+ IN PVOID HeaderBuffer,\r
+ IN UINT HeaderBufferSize,\r
+ IN PVOID LookAheadBuffer,\r
+ IN UINT LookAheadBufferSize,\r
+ IN UINT PacketSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Handle receive data indicated up by the miniport below. We pass\r
+ it along to the protocol above us.\r
+\r
+ If the miniport below indicates packets, NDIS would more\r
+ likely call us at our ReceivePacket handler. However we\r
+ might be called here in certain situations even though\r
+ the miniport below has indicated a receive packet, e.g.\r
+ if the miniport had set packet status to NDIS_STATUS_RESOURCES.\r
+ \r
+Arguments:\r
+\r
+ <see DDK ref page for ProtocolReceive>\r
+\r
+Return Value:\r
+\r
+ NDIS_STATUS_SUCCESS if we processed the receive successfully,\r
+ NDIS_STATUS_XXX error code if we discarded it.\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt = (PADAPT)ProtocolBindingContext;\r
+ PNDIS_PACKET MyPacket, Packet = NULL;\r
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
+ ULONG Proc = KeGetCurrentProcessorNumber(); \r
+ \r
+ if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))\r
+ {\r
+ Status = NDIS_STATUS_FAILURE;\r
+ }\r
+ else do\r
+ {\r
+ //\r
+ // Get at the packet, if any, indicated up by the miniport below.\r
+ //\r
+ Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);\r
+ if (Packet != NULL)\r
+ {\r
+ //\r
+ // The miniport below did indicate up a packet. Use information\r
+ // from that packet to construct a new packet to indicate up.\r
+ //\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // NDIS 5.1 NOTE: Do not reuse the original packet in indicating\r
+ // up a receive, even if there is sufficient packet stack space.\r
+ // If we had to do so, we would have had to overwrite the\r
+ // status field in the original packet to NDIS_STATUS_RESOURCES,\r
+ // and it is not allowed for protocols to overwrite this field\r
+ // in received packets.\r
+ //\r
+#endif // NDIS51\r
+\r
+ //\r
+ // Get a packet off the pool and indicate that up\r
+ //\r
+ NdisDprAllocatePacket(&Status,\r
+ &MyPacket,\r
+ pAdapt->RecvPacketPoolHandle);\r
+\r
+ if (Status == NDIS_STATUS_SUCCESS)\r
+ {\r
+ //\r
+ // Make our packet point to data from the original\r
+ // packet. NOTE: this works only because we are\r
+ // indicating a receive directly from the context of\r
+ // our receive indication. If we need to queue this\r
+ // packet and indicate it from another thread context,\r
+ // we will also have to allocate a new buffer and copy\r
+ // over the packet contents, OOB data and per-packet\r
+ // information. This is because the packet data\r
+ // is available only for the duration of this\r
+ // receive indication call.\r
+ //\r
+ NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);\r
+ NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);\r
+\r
+ //\r
+ // Get the original packet (it could be the same packet as the\r
+ // one received or a different one based on the number of layered\r
+ // miniports below) and set it on the indicated packet so the OOB\r
+ // data is visible correctly at protocols above. If the IM driver \r
+ // modifies the packet in any way it should not set the new packet's\r
+ // original packet equal to the original packet of the packet that \r
+ // was indicated to it from the underlying driver, in this case, the \r
+ // IM driver should also ensure that the related per packet info should\r
+ // be copied to the new packet.\r
+ // we can set the original packet to the original packet of the packet\r
+ // indicated from the underlying driver because the driver doesn't modify\r
+ // the data content in the packet.\r
+ //\r
+ NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));\r
+ NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);\r
+\r
+ //\r
+ // Copy packet flags.\r
+ //\r
+ NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);\r
+\r
+ //\r
+ // Force protocols above to make a copy if they want to hang\r
+ // on to data in this packet. This is because we are in our\r
+ // Receive handler (not ReceivePacket) and we can't return a\r
+ // ref count from here.\r
+ //\r
+ NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);\r
+\r
+ //\r
+ // By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim\r
+ // this packet as soon as the call to NdisMIndicateReceivePacket\r
+ // returns.\r
+ //\r
+\r
+ if (pAdapt->MiniportHandle != NULL)\r
+ {\r
+ NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);\r
+ }\r
+\r
+ //\r
+ // Reclaim the indicated packet. Since we had set its status\r
+ // to NDIS_STATUS_RESOURCES, we are guaranteed that protocols\r
+ // above are done with it.\r
+ //\r
+ NdisDprFreePacket(MyPacket);\r
+\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // The miniport below us uses the old-style (not packet)\r
+ // receive indication. Fall through.\r
+ //\r
+ }\r
+\r
+ //\r
+ // Fall through if the miniport below us has either not\r
+ // indicated a packet or we could not allocate one\r
+ //\r
+ pAdapt->ReceivedIndicationFlags[Proc] = TRUE;\r
+ if (pAdapt->MiniportHandle == NULL)\r
+ {\r
+ break;\r
+ }\r
+ switch (pAdapt->Medium)\r
+ {\r
+ case NdisMedium802_3:\r
+ case NdisMediumWan:\r
+ NdisMEthIndicateReceive(pAdapt->MiniportHandle,\r
+ MacReceiveContext,\r
+ HeaderBuffer,\r
+ HeaderBufferSize,\r
+ LookAheadBuffer,\r
+ LookAheadBufferSize,\r
+ PacketSize);\r
+ break;\r
+\r
+ case NdisMedium802_5:\r
+ NdisMTrIndicateReceive(pAdapt->MiniportHandle,\r
+ MacReceiveContext,\r
+ HeaderBuffer,\r
+ HeaderBufferSize,\r
+ LookAheadBuffer,\r
+ LookAheadBufferSize,\r
+ PacketSize);\r
+ break;\r
+\r
+#if FDDI\r
+ case NdisMediumFddi:\r
+ NdisMFddiIndicateReceive(pAdapt->MiniportHandle,\r
+ MacReceiveContext,\r
+ HeaderBuffer,\r
+ HeaderBufferSize,\r
+ LookAheadBuffer,\r
+ LookAheadBufferSize,\r
+ PacketSize);\r
+ break;\r
+#endif\r
+ default:\r
+ ASSERT(FALSE);\r
+ break;\r
+ }\r
+\r
+ } while(FALSE);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+VOID\r
+PtReceiveComplete(\r
+ IN NDIS_HANDLE ProtocolBindingContext\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Called by the adapter below us when it is done indicating a batch of\r
+ received packets.\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext Pointer to our adapter structure.\r
+\r
+Return Value:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt =(PADAPT)ProtocolBindingContext;\r
+ ULONG Proc = KeGetCurrentProcessorNumber(); \r
+\r
+ if (((pAdapt->MiniportHandle != NULL)\r
+ && (pAdapt->MPDeviceState == NdisDeviceStateD0))\r
+ && (pAdapt->ReceivedIndicationFlags[Proc]))\r
+ {\r
+ switch (pAdapt->Medium)\r
+ {\r
+ case NdisMedium802_3:\r
+ case NdisMediumWan:\r
+ NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);\r
+ break;\r
+\r
+ case NdisMedium802_5:\r
+ NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);\r
+ break;\r
+#if FDDI\r
+ case NdisMediumFddi:\r
+ NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);\r
+ break;\r
+#endif\r
+ default:\r
+ ASSERT(FALSE);\r
+ break;\r
+ }\r
+ }\r
+\r
+ pAdapt->ReceivedIndicationFlags[Proc] = FALSE;\r
+}\r
+\r
+\r
+INT\r
+PtReceivePacket(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN PNDIS_PACKET Packet\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ ReceivePacket handler. Called by NDIS if the miniport below supports\r
+ NDIS 4.0 style receives. Re-package the buffer chain in a new packet\r
+ and indicate the new packet to protocols above us. Any context for\r
+ packets indicated up must be kept in the MiniportReserved field.\r
+\r
+ NDIS 5.1 - packet stacking - if there is sufficient "stack space" in\r
+ the packet passed to us, we can use the same packet in a receive\r
+ indication.\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext - Pointer to our adapter structure.\r
+ Packet - Pointer to the packet\r
+\r
+Return Value:\r
+\r
+ == 0 -> We are done with the packet\r
+ != 0 -> We will keep the packet and call NdisReturnPackets() this\r
+ many times when done.\r
+--*/\r
+{\r
+ PADAPT pAdapt =(PADAPT)ProtocolBindingContext;\r
+ NDIS_STATUS Status;\r
+ PNDIS_PACKET MyPacket;\r
+ BOOLEAN Remaining;\r
+\r
+ //\r
+ // Drop the packet silently if the upper miniport edge isn't initialized or\r
+ // the miniport edge is in low power state\r
+ //\r
+ if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // Check if we can reuse the same packet for indicating up.\r
+ // See also: PtReceive(). \r
+ //\r
+ (VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);\r
+ if (Remaining)\r
+ {\r
+ //\r
+ // We can reuse "Packet". Indicate it up and be done with it.\r
+ //\r
+ Status = NDIS_GET_PACKET_STATUS(Packet);\r
+ NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1);\r
+ return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);\r
+ }\r
+#endif // NDIS51\r
+\r
+ //\r
+ // Get a packet off the pool and indicate that up\r
+ //\r
+ NdisDprAllocatePacket(&Status,\r
+ &MyPacket,\r
+ pAdapt->RecvPacketPoolHandle);\r
+\r
+ if (Status == NDIS_STATUS_SUCCESS)\r
+ {\r
+ PRECV_RSVD RecvRsvd;\r
+\r
+ RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);\r
+ RecvRsvd->OriginalPkt = Packet;\r
+\r
+ NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);\r
+ NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);\r
+\r
+ //\r
+ // Get the original packet (it could be the same packet as the one\r
+ // received or a different one based on the number of layered miniports\r
+ // below) and set it on the indicated packet so the OOB data is visible\r
+ // correctly to protocols above us.\r
+ //\r
+ NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));\r
+\r
+ //\r
+ // Set Packet Flags\r
+ //\r
+ NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);\r
+\r
+ Status = NDIS_GET_PACKET_STATUS(Packet);\r
+\r
+ NDIS_SET_PACKET_STATUS(MyPacket, Status);\r
+ NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));\r
+\r
+ if (pAdapt->MiniportHandle != NULL)\r
+ {\r
+ NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);\r
+ }\r
+\r
+ //\r
+ // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES\r
+ // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since\r
+ // it might have changed! Use the value saved in the local variable.\r
+ //\r
+ if (Status == NDIS_STATUS_RESOURCES)\r
+ {\r
+ //\r
+ // Our ReturnPackets handler will not be called for this packet.\r
+ // We should reclaim it right here.\r
+ //\r
+ NdisDprFreePacket(MyPacket);\r
+ }\r
+\r
+ return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // We are out of packets. Silently drop it.\r
+ //\r
+ return(0);\r
+ }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+PtPNPHandler(\r
+ IN NDIS_HANDLE ProtocolBindingContext,\r
+ IN PNET_PNP_EVENT pNetPnPEvent\r
+ )\r
+\r
+/*++\r
+Routine Description:\r
+\r
+ This is called by NDIS to notify us of a PNP event related to a lower\r
+ binding. Based on the event, this dispatches to other helper routines.\r
+\r
+ NDIS 5.1: forward this event to the upper protocol(s) by calling\r
+ NdisIMNotifyPnPEvent.\r
+\r
+Arguments:\r
+\r
+ ProtocolBindingContext - Pointer to our adapter structure. Can be NULL\r
+ for "global" notifications\r
+\r
+ pNetPnPEvent - Pointer to the PNP event to be processed.\r
+\r
+Return Value:\r
+\r
+ NDIS_STATUS code indicating status of event processing.\r
+\r
+--*/\r
+{\r
+ PADAPT pAdapt =(PADAPT)ProtocolBindingContext;\r
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
+\r
+ DBGPRINT(("PtPnPHandler: Adapt %p, Event %d\n", pAdapt, pNetPnPEvent->NetEvent));\r
+\r
+ switch (pNetPnPEvent->NetEvent)\r
+ {\r
+ case NetEventSetPower:\r
+ Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);\r
+ break;\r
+\r
+ case NetEventReconfigure:\r
+ Status = PtPnPNetEventReconfigure(pAdapt, pNetPnPEvent);\r
+ break;\r
+\r
+ default:\r
+#ifdef NDIS51\r
+ //\r
+ // Pass on this notification to protocol(s) above, before\r
+ // doing anything else with it.\r
+ //\r
+ if (pAdapt && pAdapt->MiniportHandle)\r
+ {\r
+ Status = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
+ }\r
+#else\r
+ Status = NDIS_STATUS_SUCCESS;\r
+\r
+#endif // NDIS51\r
+\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+PtPnPNetEventReconfigure(\r
+ IN PADAPT pAdapt,\r
+ IN PNET_PNP_EVENT pNetPnPEvent\r
+ )\r
+/*++\r
+Routine Description:\r
+\r
+ This routine is called from NDIS to notify our protocol edge of a\r
+ reconfiguration of parameters for either a specific binding (pAdapt\r
+ is not NULL), or global parameters if any (pAdapt is NULL).\r
+\r
+Arguments:\r
+\r
+ pAdapt - Pointer to our adapter structure.\r
+ pNetPnPEvent - the reconfigure event\r
+\r
+Return Value:\r
+\r
+ NDIS_STATUS_SUCCESS\r
+\r
+--*/\r
+{\r
+ NDIS_STATUS ReconfigStatus = NDIS_STATUS_SUCCESS;\r
+ NDIS_STATUS ReturnStatus = NDIS_STATUS_SUCCESS;\r
+\r
+ do\r
+ {\r
+ //\r
+ // Is this is a global reconfiguration notification ?\r
+ //\r
+ if (pAdapt == NULL)\r
+ {\r
+ //\r
+ // An important event that causes this notification to us is if\r
+ // one of our upper-edge miniport instances was enabled after being\r
+ // disabled earlier, e.g. from Device Manager in Win2000. Note that\r
+ // NDIS calls this because we had set up an association between our\r
+ // miniport and protocol entities by calling NdisIMAssociateMiniport.\r
+ //\r
+ // Since we would have torn down the lower binding for that miniport,\r
+ // we need NDIS' assistance to re-bind to the lower miniport. The\r
+ // call to NdisReEnumerateProtocolBindings does exactly that.\r
+ //\r
+ NdisReEnumerateProtocolBindings (ProtHandle); \r
+ \r
+ break;\r
+ }\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // Pass on this notification to protocol(s) above before doing anything\r
+ // with it.\r
+ //\r
+ if (pAdapt->MiniportHandle)\r
+ {\r
+ ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
+ }\r
+#endif // NDIS51\r
+\r
+ ReconfigStatus = NDIS_STATUS_SUCCESS;\r
+\r
+ } while(FALSE);\r
+\r
+ DBGPRINT(("<==PtPNPNetEventReconfigure: pAdapt %p\n", pAdapt));\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // Overwrite status with what upper-layer protocol(s) returned.\r
+ //\r
+ ReconfigStatus = ReturnStatus;\r
+#endif\r
+\r
+ return ReconfigStatus;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+PtPnPNetEventSetPower(\r
+ IN PADAPT pAdapt,\r
+ IN PNET_PNP_EVENT pNetPnPEvent\r
+ )\r
+/*++\r
+Routine Description:\r
+\r
+ This is a notification to our protocol edge of the power state\r
+ of the lower miniport. If it is going to a low-power state, we must\r
+ wait here for all outstanding sends and requests to complete.\r
+\r
+ NDIS 5.1: Since we use packet stacking, it is not sufficient to\r
+ check usage of our local send packet pool to detect whether or not\r
+ all outstanding sends have completed. For this, use the new API\r
+ NdisQueryPendingIOCount.\r
+\r
+ NDIS 5.1: Use the 5.1 API NdisIMNotifyPnPEvent to pass on PnP\r
+ notifications to upper protocol(s).\r
+\r
+Arguments:\r
+\r
+ pAdapt - Pointer to the adpater structure\r
+ pNetPnPEvent - The Net Pnp Event. this contains the new device state\r
+\r
+Return Value:\r
+\r
+ NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols.\r
+\r
+--*/\r
+{\r
+ PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);\r
+ NDIS_DEVICE_POWER_STATE PrevDeviceState = pAdapt->PTDeviceState; \r
+ NDIS_STATUS Status;\r
+ NDIS_STATUS ReturnStatus;\r
+\r
+ ReturnStatus = NDIS_STATUS_SUCCESS;\r
+\r
+ //\r
+ // Set the Internal Device State, this blocks all new sends or receives\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ pAdapt->PTDeviceState = *pDeviceState;\r
+\r
+ //\r
+ // Check if the miniport below is going to a low power state.\r
+ //\r
+ if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+ {\r
+ //\r
+ // If the miniport below is going to standby, fail all incoming requests\r
+ //\r
+ if (PrevDeviceState == NdisDeviceStateD0)\r
+ {\r
+ pAdapt->StandingBy = TRUE;\r
+ }\r
+\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // Notify upper layer protocol(s) first.\r
+ //\r
+ if (pAdapt->MiniportHandle != NULL)\r
+ {\r
+ ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
+ }\r
+#endif // NDIS51\r
+\r
+ //\r
+ // Wait for outstanding sends and requests to complete.\r
+ //\r
+ while (pAdapt->OutstandingSends != 0)\r
+ {\r
+ NdisMSleep(2);\r
+ }\r
+\r
+ while (pAdapt->OutstandingRequests == TRUE)\r
+ {\r
+ //\r
+ // sleep till outstanding requests complete\r
+ //\r
+ NdisMSleep(2);\r
+ }\r
+\r
+ //\r
+ // If the below miniport is going to low power state, complete the queued request\r
+ //\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ if (pAdapt->QueuedRequest)\r
+ {\r
+ pAdapt->QueuedRequest = FALSE;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ PtRequestComplete(pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE);\r
+ }\r
+ else\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ }\r
+ \r
+\r
+ ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);\r
+ ASSERT(pAdapt->OutstandingRequests == FALSE);\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // If the physical miniport is powering up (from Low power state to D0), \r
+ // clear the flag\r
+ //\r
+ if (PrevDeviceState > NdisDeviceStateD0)\r
+ {\r
+ pAdapt->StandingBy = FALSE;\r
+ }\r
+ //\r
+ // The device below is being turned on. If we had a request\r
+ // pending, send it down now.\r
+ //\r
+ if (pAdapt->QueuedRequest == TRUE)\r
+ {\r
+ pAdapt->QueuedRequest = FALSE;\r
+ \r
+ pAdapt->OutstandingRequests = TRUE;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+ NdisRequest(&Status,\r
+ pAdapt->BindingHandle,\r
+ &pAdapt->Request);\r
+\r
+ if (Status != NDIS_STATUS_PENDING)\r
+ {\r
+ PtRequestComplete(pAdapt,\r
+ &pAdapt->Request,\r
+ Status);\r
+ \r
+ }\r
+ }\r
+ else\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ }\r
+\r
+\r
+#ifdef NDIS51\r
+ //\r
+ // Pass on this notification to protocol(s) above\r
+ //\r
+ if (pAdapt->MiniportHandle)\r
+ {\r
+ ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
+ }\r
+#endif // NDIS51\r
+\r
+ }\r
+\r
+ return ReturnStatus;\r
+}\r
+\r
+VOID\r
+PtReferenceAdapt(\r
+ IN PADAPT pAdapt\r
+ )\r
+{\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+ \r
+ ASSERT(pAdapt->RefCount >= 0);\r
+\r
+ pAdapt->RefCount ++;\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+}\r
+\r
+\r
+BOOLEAN\r
+PtDereferenceAdapt(\r
+ IN PADAPT pAdapt\r
+ )\r
+{\r
+ NdisAcquireSpinLock(&pAdapt->Lock);\r
+\r
+ ASSERT(pAdapt->RefCount > 0);\r
+\r
+ pAdapt->RefCount--;\r
+\r
+ if (pAdapt->RefCount == 0)\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+ \r
+ //\r
+ // Free all resources on this adapter structure.\r
+ //\r
+ MPFreeAllPacketPools (pAdapt);;\r
+ NdisFreeSpinLock(&pAdapt->Lock);\r
+ NdisFreeMemory(pAdapt, 0 , 0);\r
+ \r
+ return TRUE;\r
+ \r
+ }\r
+ else\r
+ {\r
+ NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+\r