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