Amd64/misc 64bit fixes (#236)
[reactos.git] / drivers / network / ndis / ndis / miniport.c
index 130b929..904158d 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "ndissys.h"
 
+#include <ndisguid.h>
+
 /*
  * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
  * for each new miniport starting up
@@ -127,7 +129,7 @@ MiniGetFirstWorkItem(
 
     while (CurrentEntry)
     {
-      if (CurrentEntry->WorkItemType == Type)
+      if (CurrentEntry->WorkItemType == Type || Type == NdisMaxWorkItems)
           return CurrentEntry;
 
       CurrentEntry = (PNDIS_MINIPORT_WORK_ITEM)CurrentEntry->Link.Next;
@@ -146,18 +148,20 @@ MiniIsBusy(
 
     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
 
-    if (Type == NdisWorkItemRequest &&
-        (Adapter->NdisMiniportBlock.PendingRequest || MiniGetFirstWorkItem(Adapter, NdisWorkItemRequest)))
+    if (MiniGetFirstWorkItem(Adapter, Type))
+    {
+        Busy = TRUE;
+    }
+    else if (Type == NdisWorkItemRequest && Adapter->NdisMiniportBlock.PendingRequest)
     {
        Busy = TRUE;
     }
-    else if (Type == NdisWorkItemSend &&
-             (Adapter->NdisMiniportBlock.FirstPendingPacket || MiniGetFirstWorkItem(Adapter, NdisWorkItemSend)))
+    else if (Type == NdisWorkItemSend && Adapter->NdisMiniportBlock.FirstPendingPacket)
     {
        Busy = TRUE;
     }
     else if (Type == NdisWorkItemResetRequested &&
-             (Adapter->NdisMiniportBlock.ResetStatus == NDIS_STATUS_PENDING || MiniGetFirstWorkItem(Adapter, NdisWorkItemResetRequested)))
+             Adapter->NdisMiniportBlock.ResetStatus == NDIS_STATUS_PENDING)
     {
        Busy = TRUE;
     }
@@ -336,7 +340,7 @@ MiniIndicateReceivePacket(
                                              &NdisBufferVA,
                                              &FirstBufferLength,
                                              &TotalBufferLength);
-                
+
                 HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
 
                 LookAheadSize = TotalBufferLength - HeaderSize;
@@ -348,12 +352,12 @@ MiniIndicateReceivePacket(
                     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
                     return;
                 }
-                
+
                 CopyBufferChainToBuffer(LookAheadBuffer,
                                         NdisBuffer,
                                         HeaderSize,
                                         LookAheadSize);
-                
+
                 NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's legacy Receive handler\n"));
                 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
                      AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
@@ -363,7 +367,7 @@ MiniIndicateReceivePacket(
                      LookAheadBuffer,
                      LookAheadSize,
                      TotalBufferLength - HeaderSize);
-                
+
                 ExFreePool(LookAheadBuffer);
             }
         }
@@ -491,18 +495,33 @@ MiniRequestComplete(
 
     MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
 
-    if( MacBlock->Binding->RequestCompleteHandler ) {
-        (*MacBlock->Binding->RequestCompleteHandler)(
-            MacBlock->Binding->ProtocolBindingContext,
-            Request,
-            Status);
+    /* We may or may not be doing this request on behalf of an adapter binding */
+    if (MacBlock->Binding != NULL)
+    {
+        /* We are, so invoke its request complete handler */
+        if (MacBlock->Binding->RequestCompleteHandler != NULL)
+        {
+            (*MacBlock->Binding->RequestCompleteHandler)(
+                MacBlock->Binding->ProtocolBindingContext,
+                Request,
+                Status);
+        }
+    }
+    else
+    {
+        /* We are doing this internally, so we'll signal this event we've stashed in the MacBlock */
+        ASSERT(MacBlock->Unknown1 != NULL);
+        ASSERT(MacBlock->Unknown3 == NULL);
+        MacBlock->Unknown3 = (PVOID)Status;
+        KeSetEvent(MacBlock->Unknown1, IO_NO_INCREMENT, FALSE);
     }
 
     KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
     Adapter->NdisMiniportBlock.PendingRequest = NULL;
     KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-
     KeLowerIrql(OldIrql);
+
+    MiniWorkItemComplete(Adapter, NdisWorkItemRequest);
 }
 
 VOID NTAPI
@@ -553,6 +572,8 @@ MiniSendComplete(
         Status);
 
     KeLowerIrql(OldIrql);
+
+    MiniWorkItemComplete(Adapter, NdisWorkItemSend);
 }
 
 
@@ -560,9 +581,8 @@ VOID NTAPI
 MiniSendResourcesAvailable(
     IN  NDIS_HANDLE MiniportAdapterHandle)
 {
-/*
-    UNIMPLEMENTED
-*/
+    /* Run the work if anything is waiting */
+    MiniWorkItemComplete((PLOGICAL_ADAPTER)MiniportAdapterHandle, NdisWorkItemSend);
 }
 
 
@@ -696,7 +716,7 @@ MiniLocateDevice(
     KeAcquireSpinLock(&AdapterListLock, &OldIrql);
     {
         CurrentEntry = AdapterListHead.Flink;
-        
+
         while (CurrentEntry != &AdapterListHead)
         {
             Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
@@ -740,6 +760,8 @@ MiniSetInformation(
 {
   NDIS_STATUS NdisStatus;
   PNDIS_REQUEST NdisRequest;
+  KEVENT Event;
+  PNDIS_REQUEST_MAC_BLOCK MacBlock;
 
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
@@ -756,11 +778,19 @@ MiniSetInformation(
   NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
   NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
 
-  NdisStatus = MiniDoRequest(Adapter, NdisRequest);
+  /* We'll need to give the completion routine some way of letting us know
+   * when it's finished. We'll stash a pointer to an event in the MacBlock */
+  KeInitializeEvent(&Event, NotificationEvent, FALSE);
+  MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
+  MacBlock->Unknown1 = &Event;
 
-  /* FIXME: Wait in pending case! */
+  NdisStatus = MiniDoRequest(Adapter, NdisRequest);
 
-  ASSERT(NdisStatus != NDIS_STATUS_PENDING);
+  if (NdisStatus == NDIS_STATUS_PENDING)
+  {
+      KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+      NdisStatus = (NDIS_STATUS)MacBlock->Unknown3;
+  }
 
   *BytesRead = NdisRequest->DATA.SET_INFORMATION.BytesRead;
 
@@ -790,6 +820,8 @@ MiniQueryInformation(
 {
   NDIS_STATUS NdisStatus;
   PNDIS_REQUEST NdisRequest;
+  KEVENT Event;
+  PNDIS_REQUEST_MAC_BLOCK MacBlock;
 
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
@@ -806,11 +838,19 @@ MiniQueryInformation(
   NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
   NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
 
-  NdisStatus = MiniDoRequest(Adapter, NdisRequest);
+  /* We'll need to give the completion routine some way of letting us know
+   * when it's finished. We'll stash a pointer to an event in the MacBlock */
+  KeInitializeEvent(&Event, NotificationEvent, FALSE);
+  MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
+  MacBlock->Unknown1 = &Event;
 
-  /* FIXME: Wait in pending case! */
+  NdisStatus = MiniDoRequest(Adapter, NdisRequest);
 
-  ASSERT(NdisStatus != NDIS_STATUS_PENDING);
+  if (NdisStatus == NDIS_STATUS_PENDING)
+  {
+      KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+      NdisStatus = (NDIS_STATUS)MacBlock->Unknown3;
+  }
 
   *BytesWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
 
@@ -896,6 +936,8 @@ MiniReset(
 
        NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
        NdisMIndicateStatusComplete(Adapter);
+
+       MiniWorkItemComplete(Adapter, NdisWorkItemResetRequested);
    }
 
    return Status;
@@ -916,6 +958,23 @@ MiniportHangDpc(
   }
 }
 
+VOID
+MiniWorkItemComplete(
+    PLOGICAL_ADAPTER     Adapter,
+    NDIS_WORK_ITEM_TYPE  WorkItemType)
+{
+    PIO_WORKITEM IoWorkItem;
+
+    /* Check if there's anything queued to run after this work item */
+    if (!MiniIsBusy(Adapter, WorkItemType))
+        return;
+
+    /* There is, so fire the worker */
+    IoWorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
+    if (IoWorkItem)
+        IoQueueWorkItem(IoWorkItem, MiniportWorker, DelayedWorkQueue, IoWorkItem);
+}
+
 VOID
 FASTCALL
 MiniQueueWorkItem(
@@ -934,7 +993,6 @@ MiniQueueWorkItem(
  */
 {
     PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
-    PIO_WORKITEM IoWorkItem;
     KIRQL OldIrql;
 
     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
@@ -982,10 +1040,6 @@ MiniQueueWorkItem(
         }
     }
 
-    IoWorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
-    if (IoWorkItem)
-        IoQueueWorkItem(IoWorkItem, MiniportWorker, DelayedWorkQueue, IoWorkItem);
-
     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 }
 
@@ -1114,6 +1168,11 @@ MiniDoRequest(
     }
 
     KeLowerIrql(OldIrql);
+
+    if (Status != NDIS_STATUS_PENDING) {
+        MiniWorkItemComplete(Adapter, NdisWorkItemRequest);
+    }
+
     return Status;
 }
 
@@ -1292,10 +1351,11 @@ MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
             if (NdisStatus == NDIS_STATUS_PENDING)
               break;
 
+            Adapter->NdisMiniportBlock.PendingRequest = (PNDIS_REQUEST)WorkItemContext;
             switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
               {
                 case NdisRequestQueryInformation:
-                 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
+                  NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
                   break;
 
                 case NdisRequestSetInformation:
@@ -1306,6 +1366,7 @@ MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
                   NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
                   break;
               }
+            Adapter->NdisMiniportBlock.PendingRequest = NULL;
             break;
 
           default:
@@ -1647,6 +1708,12 @@ NdisMRegisterAdapterShutdownHandler(
 
   NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
+  if (Adapter->BugcheckContext != NULL)
+  {
+      NDIS_DbgPrint(MIN_TRACE, ("Attempted to register again for a shutdown callback\n"));
+      return;
+  }
+
   BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
   if(!BugcheckContext)
     {
@@ -1819,7 +1886,7 @@ NdisIPnPStartDevice(
 /*
  * FUNCTION: Handle the PnP start device event
  * ARGUMENTS:
- *     DeviceObejct = Functional Device Object
+ *     DeviceObject = Functional Device Object
  *     Irp          = IRP_MN_START_DEVICE I/O request packet
  * RETURNS:
  *     Status of operation
@@ -2033,7 +2100,7 @@ NdisIPnPStartDevice(
 
   if (NdisStatus != NDIS_STATUS_SUCCESS)
     {
-      NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
+      NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter (%lx).\n", NdisStatus));
       ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
       if (Adapter->NdisMiniportBlock.Interrupt)
       {
@@ -2145,7 +2212,7 @@ NdisIPnPStopDevice(
 /*
  * FUNCTION: Handle the PnP stop device event
  * ARGUMENTS:
- *     DeviceObejct = Functional Device Object
+ *     DeviceObject = Functional Device Object
  *     Irp          = IRP_MN_STOP_DEVICE I/O request packet
  * RETURNS:
  *     Status of operation
@@ -2226,13 +2293,15 @@ NdisIDeviceIoControl(
   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
   NDIS_STATUS Status = STATUS_NOT_SUPPORTED;
+  ULONG ControlCode;
   ULONG Written;
 
   Irp->IoStatus.Information = 0;
 
   ASSERT(Adapter);
 
-  switch (Stack->Parameters.DeviceIoControl.IoControlCode)
+  ControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
+  switch (ControlCode)
   {
     case IOCTL_NDIS_QUERY_GLOBAL_STATS:
       Status = MiniQueryInformation(Adapter,
@@ -2244,7 +2313,7 @@ NdisIDeviceIoControl(
       break;
 
     default:
-      ASSERT(FALSE);
+      NDIS_DbgPrint(MIN_TRACE, ("NdisIDeviceIoControl: unsupported control code 0x%lx\n", ControlCode));
       break;
   }
 
@@ -2331,6 +2400,19 @@ NdisIDispatchPnp(
   return IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
 }
 
+NTSTATUS
+NTAPI
+NdisIPower(
+    _In_ PDEVICE_OBJECT DeviceObject,
+    _In_ PIRP Irp)
+{
+  PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
+
+  PoStartNextPowerIrp(Irp);
+  IoSkipCurrentIrpStackLocation(Irp);
+  return PoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
+}
+
 NTSTATUS
 NTAPI
 NdisIAddDevice(
@@ -2371,7 +2453,7 @@ NdisIAddDevice(
    * Get name of the Linkage registry key for our adapter. It's located under
    * the driver key for our driver and so we have basicly two ways to do it.
    * Either we can use IoOpenDriverRegistryKey or compose it using information
-   * gathered by IoGetDeviceProperty. I choosed the second because
+   * gathered by IoGetDeviceProperty. I chose the second because
    * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
    */
 
@@ -2497,7 +2579,8 @@ NdisGenericIrpHandler(
     if (DeviceObject->DeviceType == FILE_DEVICE_PHYSICAL_NETCARD)
     {
         if ((IrpSp->MajorFunction == IRP_MJ_CREATE) ||
-            (IrpSp->MajorFunction == IRP_MJ_CLOSE))
+            (IrpSp->MajorFunction == IRP_MJ_CLOSE) ||
+            (IrpSp->MajorFunction == IRP_MJ_CLEANUP))
         {
             return NdisICreateClose(DeviceObject, Irp);
         }
@@ -2513,6 +2596,12 @@ NdisGenericIrpHandler(
         {
             return NdisIDeviceIoControl(DeviceObject, Irp);
         }
+        else if (IrpSp->MajorFunction == IRP_MJ_POWER)
+        {
+            return NdisIPower(DeviceObject, Irp);
+        }
+        NDIS_DbgPrint(MIN_TRACE, ("Unexpected IRP MajorFunction 0x%x\n", IrpSp->MajorFunction));
+        ASSERT(FALSE);
     }
     else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK)
     {
@@ -2581,11 +2670,11 @@ NdisMRegisterMiniport(
             case 0x00:
                 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
                 break;
-                
+
             case 0x01:
                 MinSize = sizeof(NDIS51_MINIPORT_CHARACTERISTICS);
                 break;
-                
+
             default:
                 NDIS_DbgPrint(MIN_TRACE, ("Bad 5.x minor characteristics version.\n"));
                 return NDIS_STATUS_BAD_VERSION;
@@ -2597,7 +2686,7 @@ NdisMRegisterMiniport(
         return NDIS_STATUS_BAD_VERSION;
     }
 
-   NDIS_DbgPrint(MIN_TRACE, ("Initializing an NDIS %u.%u miniport\n", 
+   NDIS_DbgPrint(MID_TRACE, ("Initializing an NDIS %u.%u miniport\n",
                               MiniportCharacteristics->MajorNdisVersion,
                               MiniportCharacteristics->MinorNdisVersion));
 
@@ -2818,7 +2907,7 @@ NdisMSetAttributesEx(
   if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
     NDIS_DbgPrint(MIN_TRACE, ("Intermediate drivers not supported yet.\n"));
 
-  NDIS_DbgPrint(MIN_TRACE, ("Miniport attribute flags: 0x%x\n", AttributeFlags));
+  NDIS_DbgPrint(MID_TRACE, ("Miniport attribute flags: 0x%x\n", AttributeFlags));
 
   if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler)
   {
@@ -3114,7 +3203,7 @@ NdisMRegisterDevice(
         NDIS_DbgPrint(MIN_TRACE, ("IoCreateDevice failed (%x)\n", Status));
         return Status;
     }
-    
+
     Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
 
     if (!NT_SUCCESS(Status))
@@ -3322,4 +3411,3 @@ NdisIMGetDeviceContext(
 }
 
 /* EOF */
-