[project] Don't use mini IRP handling for IRP_MJ_POWER
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Mon, 13 Dec 2010 05:13:41 +0000 (00:13 -0500)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Mon, 13 Dec 2010 05:17:18 +0000 (00:17 -0500)
Instead of using the mini IRP handling logic, we will
handle IRP_MJ_POWER differently.  This might be a trend...

Also introduced are:

driver__complete_irp() for common IRP completion logic.

device__dispatch_func typedef for IRP dispatch routines.

device::irp_mj is an pointer to an IRP handling table based
on major function code.

src/include/device.h
src/include/driver.h
src/winvblock/bus/bus.c
src/winvblock/device.c
src/winvblock/disk/disk.c
src/winvblock/driver.c

index 1d01073..21f0848 100644 (file)
@@ -106,6 +106,23 @@ winvblock__def_struct(device__ops) {
 
 typedef void STDCALL device__thread_func(IN void *);
 
+/**
+ * The prototype for a device IRP dispatch.
+ *
+ * @v dev               Points to the device.
+ * @v irp               Points to the IRP.
+ * @ret NTSTATUS        The status of processing the IRP for the device.
+ */
+typedef NTSTATUS STDCALL device__dispatch_func(
+    IN struct device__type *,
+    IN PIRP
+  );
+
+/* IRP major function handler table. */
+struct device__irp_mj {
+    device__dispatch_func * power;
+  };
+
 /* Details common to all devices this driver works with */
 struct device__type {
     /* For debugging */
@@ -142,6 +159,8 @@ struct device__type {
     LIST_ENTRY tracking;
     /* Points to further extensions. */
     winvblock__any_ptr ext;
+    /* How to handle IRPs based on major function code. */
+    struct device__irp_mj * irp_mj;
   };
 
 extern winvblock__lib_func struct device__type * device__get(PDEVICE_OBJECT);
index 2a976a0..c11fd5e 100644 (file)
@@ -65,5 +65,10 @@ typedef NTSTATUS STDCALL driver__dispatch_func(
 extern winvblock__lib_func driver__dispatch_func driver__default_dispatch;
 extern winvblock__lib_func irp__handler driver__not_supported;
 extern winvblock__lib_func irp__handler driver__create_close;
+extern winvblock__lib_func NTSTATUS STDCALL driver__complete_irp(
+    IN PIRP,
+    IN ULONG_PTR,
+    IN NTSTATUS
+  );
 
 #endif /* _DRIVER_H */
index 51e9ef9..c80d254 100644 (file)
 /* Forward declarations. */
 static device__free_func bus__free_;
 static device__create_pdo_func bus__create_pdo_;
+static device__dispatch_func bus__power_;
+
+/* Globals. */
+struct device__irp_mj bus__irp_mj_ = {
+    bus__power_,
+  };
 
 /**
  * Add a child node to the bus.
@@ -139,19 +145,18 @@ static NTSTATUS STDCALL bus__sys_ctl_(
   }
 
 static NTSTATUS STDCALL bus__power_(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp,
-    IN PIO_STACK_LOCATION Stack,
-    IN struct device__type * dev_ptr,
-    OUT winvblock__bool_ptr completion_ptr
+    IN struct device__type * dev,
+    IN PIRP irp
   ) {
-    struct bus__type * bus_ptr = bus__get(dev_ptr);
-    PDEVICE_OBJECT lower = bus_ptr->LowerDeviceObject;
+    struct bus__type * bus = bus__get(dev);
+    PDEVICE_OBJECT lower = bus->LowerDeviceObject;
 
-    PoStartNextPowerIrp(Irp);
-    IoSkipCurrentIrpStackLocation(Irp);
-    *completion_ptr = TRUE;
-    return lower ? PoCallDriver(lower, Irp) : STATUS_SUCCESS;
+    PoStartNextPowerIrp(irp);
+    if (lower) {
+        IoSkipCurrentIrpStackLocation(irp);
+        return PoCallDriver(lower, irp);
+      }
+    return driver__complete_irp(irp, 0, STATUS_SUCCESS);
   }
 
 NTSTATUS STDCALL bus__get_dev_capabilities(
@@ -226,7 +231,6 @@ static NTSTATUS STDCALL bus_dispatch(
         {          IRP_MJ_CLOSE, 0, FALSE, TRUE,  driver__create_close },
         {         IRP_MJ_CREATE, 0, FALSE, TRUE,  driver__create_close },
         { IRP_MJ_SYSTEM_CONTROL, 0, FALSE, TRUE,         bus__sys_ctl_ },
-        {          IRP_MJ_POWER, 0, FALSE, TRUE,           bus__power_ },
         { IRP_MJ_DEVICE_CONTROL, 0, FALSE, TRUE, bus_dev_ctl__dispatch },
         {            IRP_MJ_PNP, 0, FALSE, TRUE,       bus_pnp__simple },
         {            IRP_MJ_PNP,
@@ -303,6 +307,7 @@ winvblock__lib_func struct bus__type * bus__create(void) {
     dev_ptr->ops.init = bus__init_;
     dev_ptr->ops.free = bus__free_;
     dev_ptr->ext = bus_ptr;
+    dev_ptr->irp_mj = &bus__irp_mj_;
     dev_ptr->IsBus = TRUE;
     KeInitializeSpinLock(&bus_ptr->SpinLock);
 
index f2f280a..38d9946 100644 (file)
@@ -207,7 +207,11 @@ static void STDCALL device__free_dev_(IN struct device__type * dev) {
  * @ret                 Returns a pointer to the device on success, else NULL.
  */
 winvblock__lib_func struct device__type * device__get(PDEVICE_OBJECT dev_obj) {
-    driver__dev_ext_ptr dev_ext = dev_obj->DeviceExtension;
+    driver__dev_ext_ptr dev_ext;
+
+    if (!dev_obj)
+      return NULL;
+    dev_ext = dev_obj->DeviceExtension;
     return dev_ext->device;
   }
 
index fdac4b6..615cd19 100644 (file)
@@ -50,15 +50,19 @@ __divdi3 (
 }
 #endif
 
+/* Forward declarations. */
+static device__free_func free_disk;
+static device__dispatch_func disk__power_;
+
 /* Globals. */
 static LIST_ENTRY disk_list;
 static KSPIN_LOCK disk_list_lock;
 winvblock__bool disk__removable[disk__media_count] = { TRUE, FALSE, TRUE };
 PWCHAR disk__compat_ids[disk__media_count] =
   { L"GenSFloppy", L"GenDisk", L"GenCdRom" };
-
-/* Forward declarations. */
-static device__free_func free_disk;
+struct device__irp_mj disk__irp_mj_ = {
+    disk__power_,
+  };
 
 static
 disk__max_xfer_len_decl (
@@ -90,19 +94,12 @@ disk__close_decl ( default_close )
   return;
 }
 
-static NTSTATUS STDCALL power(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp,
-    IN PIO_STACK_LOCATION Stack,
-    IN struct device__type * dev_ptr,
-    OUT winvblock__bool_ptr completion_ptr
-  )
-  {
-    PoStartNextPowerIrp ( Irp );
-    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-    IoCompleteRequest ( Irp, IO_NO_INCREMENT );
-    *completion_ptr = TRUE;
-    return STATUS_NOT_SUPPORTED;
+static NTSTATUS STDCALL disk__power_(
+    IN struct device__type * dev,
+    IN PIRP irp
+  ) {
+    PoStartNextPowerIrp(irp);
+    return driver__complete_irp(irp, 0, STATUS_NOT_SUPPORTED);
   }
 
 static NTSTATUS STDCALL sys_ctl(
@@ -366,7 +363,6 @@ static NTSTATUS STDCALL (disk_dispatch)(
         {         IRP_MJ_CREATE, 0, FALSE,  TRUE,   driver__create_close },
         { IRP_MJ_DEVICE_CONTROL, 0, FALSE,  TRUE, disk_dev_ctl__dispatch },
         { IRP_MJ_SYSTEM_CONTROL, 0, FALSE,  TRUE,                sys_ctl },
-        {          IRP_MJ_POWER, 0, FALSE,  TRUE,                  power },
         {           IRP_MJ_SCSI, 0, FALSE,  TRUE,    disk_scsi__dispatch },
         {            IRP_MJ_PNP, 0, FALSE,  TRUE,       disk_pnp__simple },
         {            IRP_MJ_PNP,
@@ -447,6 +443,7 @@ disk__create (
   dev_ptr->ops.free = free_disk;
   dev_ptr->ops.init = disk__init_;
   dev_ptr->ext = disk_ptr;
+  dev_ptr->irp_mj = &disk__irp_mj_;
   KeInitializeSpinLock ( &disk_ptr->SpinLock );
 
   return disk_ptr;
index 352d28c..95e5225 100644 (file)
@@ -56,6 +56,7 @@ static LPWSTR driver__os_load_opts_ = NULL;
 
 /* Forward declarations. */
 static driver__dispatch_func driver__dispatch_not_supported_;
+static driver__dispatch_func driver__dispatch_power_;
 static driver__dispatch_func driver__dispatch_;
 static void STDCALL driver__unload_(IN PDRIVER_OBJECT);
 
@@ -304,7 +305,7 @@ NTSTATUS STDCALL DriverEntry(
     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
       DriverObject->MajorFunction[i] = driver__dispatch_not_supported_;
     DriverObject->MajorFunction[IRP_MJ_PNP] = driver__dispatch_;
-    DriverObject->MajorFunction[IRP_MJ_POWER] = driver__dispatch_;
+    DriverObject->MajorFunction[IRP_MJ_POWER] = driver__dispatch_power_;
     DriverObject->MajorFunction[IRP_MJ_CREATE] = driver__dispatch_;
     DriverObject->MajorFunction[IRP_MJ_CLOSE] = driver__dispatch_;
     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = driver__dispatch_;
@@ -379,6 +380,52 @@ extern winvblock__lib_func NTSTATUS STDCALL driver__not_supported(
     return status;
   }
 
+/**
+ * Common IRP completion routine.
+ *
+ * @v irp               Points to the IRP to complete.
+ * @v info              Number of bytes returned for the IRP, or 0.
+ * @v status            Status for the IRP to complete.
+ * @ret NTSTATUS        Returns the status value, as passed.
+ */
+winvblock__lib_func NTSTATUS STDCALL driver__complete_irp(
+    IN PIRP irp,
+    IN ULONG_PTR info,
+    IN NTSTATUS status
+  ) {
+    irp->IoStatus.Information = info;
+    irp->IoStatus.Status = status;
+    IoCompleteRequest(irp, IO_NO_INCREMENT);
+    #ifdef DEBUGIRPS
+    Debug_IrpEnd(irp, status);
+    #endif
+    return status;
+  }
+
+/* Handle a power IRP. */
+static NTSTATUS driver__dispatch_power_(
+    IN PDEVICE_OBJECT dev_obj,
+    IN PIRP irp
+  ) {
+    /* device__get() checks for a NULL dev_obj */
+    struct device__type * dev = device__get(dev_obj);
+
+    #ifdef DEBUGIRPS
+    Debug_IrpStart(dev_obj, irp);
+    #endif
+    /* Check that the device exists. */
+    if (!dev || dev->state == device__state_deleted) {
+        /* Even if it doesn't, a power IRP is important! */
+        PoStartNextPowerIrp(irp);
+        return driver__complete_irp(irp, 0, STATUS_NO_SUCH_DEVICE);
+      }
+    /* Call the particular device's power handler. */
+    if (dev->irp_mj && dev->irp_mj->power)            
+      return dev->irp_mj->power(dev, irp);
+    /* Otherwise, we don't support the IRP. */
+    return driver__complete_irp(irp, 0, STATUS_NOT_SUPPORTED);
+  }
+
 static NTSTATUS STDCALL driver__dispatch_(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp
@@ -391,10 +438,8 @@ static NTSTATUS STDCALL driver__dispatch_(
     #endif
     dev_ptr = device__get(DeviceObject);
 
-    /* We handle IRP_MJ_POWER as an exception. */
+    /* Check for a deleted device. */
     if (dev_ptr->state == device__state_deleted) {
-        if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_POWER)
-          PoStartNextPowerIrp(Irp);
         Irp->IoStatus.Information = 0;
         Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);