[irp] Move mini IRP handling into its own module
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Fri, 7 May 2010 14:53:21 +0000 (10:53 -0400)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Fri, 7 May 2010 18:07:49 +0000 (14:07 -0400)
We introduce bus/irp.c for the miniature IRP handling logic.

We also introduce code for an IRP handling table chain.  The
goal of such a chain is to allow IRP handlings to be
dynamically added and removed for a device.  An example use
would be for the AoE system to register IOCTL handling with
the WinVBlock bus device, so that the bus processes the
IOCTLs.  If the AoE system is unloaded, it should be able to
un-register the handling of these IOCTLs.

Currently, the IRP handling table chain is not used, but
this will change in a future commit.

config.bat
src/bus/driver.c
src/bus/irp.c [new file with mode: 0644]
src/include/irp.h

index 4c48715..d77f02a 100644 (file)
@@ -2,5 +2,5 @@ rem This is the root directory of the ddk.
 set ddkdir=c:\winddk\6001.18001\r
 \r
 rem Next two lines are duplicated in Makefile, edit both when adding files or changing pxe style.\r
-set c=driver.c registry.c bus.c bus_pnp.c bus_dev_ctl.c disk.c ramdisk.c filedisk.c memdisk.c grub4dos.c disk_pnp.c disk_dev_ctl.c disk_scsi.c aoe.c protocol.c debug.c probe.c winvblock.rc\r
+set c=driver.c registry.c bus.c bus_pnp.c bus_dev_ctl.c disk.c ramdisk.c filedisk.c memdisk.c grub4dos.c disk_pnp.c disk_dev_ctl.c disk_scsi.c aoe.c protocol.c debug.c probe.c winvblock.rc irp.c\r
 set pxestyle=asm\r
index 82f59f5..b17c7d0 100644 (file)
@@ -294,44 +294,8 @@ Driver_Dispatch (
       return STATUS_NO_SUCH_DEVICE;
     }
 
-  /*
-   * Mini IRP handling strategy
-   * ~~~~~~~~~~~~~~~~~~~~~~~~~~
-   */
-
-  /*
-   * Determine the device's IRP handler stack size 
-   */
-  irp_handler_index = DeviceExtension->irp_handler_stack_size;
-
-  /*
-   * For each entry in the stack, in top-down order 
-   */
-  while ( irp_handler_index-- )
-    {
-      irp__handling handling;
-      winvblock__bool handles_major,
-       handles_minor;
-
-      /*
-       * Get the handling entry 
-       */
-      handling = DeviceExtension->irp_handler_stack_ptr[irp_handler_index];
-
-      handles_major = ( Stack->MajorFunction == handling.irp_major_func )
-       || handling.any_major;
-      handles_minor = ( Stack->MinorFunction == handling.irp_minor_func )
-       || handling.any_minor;
-      if ( handles_major && handles_minor )
-       status =
-         handling.handler ( DeviceObject, Irp, Stack, DeviceExtension,
-                            &completion );
-      /*
-       * Do not process the IRP any further down the stack 
-       */
-      if ( completion )
-       break;
-    }
+  status =
+    irp__process ( DeviceObject, Irp, Stack, DeviceExtension, &completion );
 
 #ifdef DEBUGIRPS
   if ( status != STATUS_PENDING )
diff --git a/src/bus/irp.c b/src/bus/irp.c
new file mode 100644 (file)
index 0000000..541c3b3
--- /dev/null
@@ -0,0 +1,196 @@
+/**
+ * Copyright (C) 2010, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
+ *
+ * This file is part of WinVBlock, derived from WinAoE.
+ * For WinAoE contact information, see http://winaoe.org/
+ *
+ * WinVBlock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WinVBlock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file
+ *
+ * Handling IRPs
+ *
+ */
+
+#include <ntddk.h>
+
+#include "winvblock.h"
+#include "portable.h"
+#include "irp.h"
+#include "driver.h"
+#include "debug.h"
+
+/*
+ * An internal type.  A device extension will have a
+ * pointer to this structure, but its type will be a void pointer
+ */
+winvblock__def_struct ( handler_chain )
+{
+  /*
+   * Points to an array of irp__handlings 
+   */
+  irp__handling *table;
+  /*
+   * Total table size, in bytes 
+   */
+  size_t size;
+  /*
+   * Points to the next table in the chain or NULL
+   */
+  handler_chain_ptr next;
+};
+
+/**
+ * Register an IRP handling table with a chain (with table size)
+ *
+ * @v chain_ptr Pointer to IRP handler chain to attach a table to
+ * @v table     Table to add
+ * @v size      Size of the table to add, in bytes
+ * @ret         FALSE for failure, TRUE for success
+ */
+winvblock__lib_func winvblock__bool
+irp__reg_table_s (
+  IN OUT irp__handler_chain_ptr chain_ptr,
+  IN irp__handling_ptr table,
+  IN size_t size
+ )
+{
+  /*
+   * The type used by a device extension is opaque
+   */
+  handler_chain_ptr *link = ( handler_chain_ptr * ) chain_ptr,
+    new_link;
+
+  if ( link == NULL )
+    /*
+     * Nothing to attach to
+     */
+    return FALSE;
+  /*
+   * Allocate and attach a new link in the chain.
+   * Maybe we should use a spin-lock for this
+   */
+  new_link = ExAllocatePool ( NonPagedPool, sizeof ( handler_chain ) );
+  if ( new_link == NULL )
+    {
+      /*
+       * Really too bad
+       */
+      DBG ( "Could not allocate IRP handler chain!\n" );
+
+      return FALSE;
+    }
+  new_link->table = table;
+  /*
+   * Could sanity-check the size to be a multiple of sizeof(irp__handling)
+   */
+  new_link->size = size;
+  new_link->next = *link;
+  *link = new_link;
+  return TRUE;
+}
+
+/**
+ * Un-register an IRP handling table from a chain
+ *
+ * @v chain_ptr Pointer to IRP handler chain to remove table from
+ * @v table     Table to remove
+ * @ret         FALSE for failure, TRUE for success
+ */
+winvblock__lib_func winvblock__bool
+irp__new_chain (
+  IN OUT irp__handler_chain_ptr chain_ptr,
+  IN irp__handling_ptr table
+ )
+{
+  winvblock__bool done = FALSE;
+  /*
+   * The type used by a device extension is opaque
+   */
+  handler_chain_ptr *link = ( handler_chain_ptr * ) chain_ptr;
+
+  if ( link == NULL )
+    /*
+     * No chain given
+     */
+    return FALSE;
+  /*
+   * Walk the chain, looking for the given table
+   */
+  while ( *link != NULL )
+    {
+      if ( link[0]->table == table )
+       {
+         /*
+          * Remove this link in the chain
+          */
+         handler_chain_ptr next = link[0]->next;
+         ExFreePool ( *link );
+         *link = next;
+         return TRUE;
+       }
+      link = &link[0]->next;
+    }
+
+  DBG ( "Table not found\n" );
+  return FALSE;
+}
+
+/**
+ * Mini IRP handling strategy
+ *
+ */
+irp__handler_decl ( irp__process )
+{
+  NTSTATUS status = STATUS_NOT_SUPPORTED;
+  size_t irp_handler_index;
+
+  /*
+   * Determine the device's IRP handler stack size
+   */
+  irp_handler_index = DeviceExtension->irp_handler_stack_size;
+
+  /*
+   * For each entry in the stack, in top-down order
+   */
+  while ( irp_handler_index-- )
+    {
+      irp__handling handling;
+      winvblock__bool handles_major,
+       handles_minor;
+
+      /*
+       * Get the handling entry
+       */
+      handling = DeviceExtension->irp_handler_stack_ptr[irp_handler_index];
+
+      handles_major = ( Stack->MajorFunction == handling.irp_major_func )
+       || handling.any_major;
+      handles_minor = ( Stack->MinorFunction == handling.irp_minor_func )
+       || handling.any_minor;
+      if ( handles_major && handles_minor )
+       status =
+         handling.handler ( DeviceObject, Irp, Stack, DeviceExtension,
+                            completion_ptr );
+      /*
+       * Do not process the IRP any further down the stack
+       */
+      if ( *completion_ptr )
+       break;
+    }
+
+  return status;
+}
index f6b3962..fa288df 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2009, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
+ * Copyright (C) 2009-2010, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
  *
  * This file is part of WinVBlock, derived from WinAoE.
  * For WinAoE contact information, see http://winaoe.org/
@@ -58,4 +58,46 @@ winvblock__def_struct ( irp__handling )
   irp__handler handler;
 };
 
+winvblock__def_type ( winvblock__any_ptr, irp__handler_chain );
+
+/**
+ * Register an IRP handling table with a chain (with table size)
+ *
+ * @v chain_ptr Pointer to IRP handler chain to attach a table to
+ * @v table     Table to add
+ * @v size      Size of the table to add, in bytes
+ * @ret         FALSE for failure, TRUE for success
+ */
+extern winvblock__lib_func winvblock__bool irp__reg_table_s (
+  IN OUT irp__handler_chain_ptr chain_ptr,
+  IN irp__handling_ptr table,
+  IN size_t size
+ );
+
+/**
+ * Register an IRP handling table with a chain
+ *
+ * @v chain_ptr Pointer to IRP handler chain to attach a table to
+ * @v table     Table to add
+ * @ret         FALSE for failure, TRUE for success
+ */
+#  define irp__reg_table( chain_ptr, table ) \
+  irp__reg_table_s ( chain_ptr, table, sizeof ( table ) )
+
+/**
+ * Un-register an IRP handling table from a chain
+ *
+ * @v chain_ptr Pointer to IRP handler chain to remove table from
+ * @v table     Table to remove
+ * @ret         FALSE for failure, TRUE for success
+ */
+winvblock__lib_func winvblock__bool irp__new_chain (
+  IN OUT irp__handler_chain_ptr chain_ptr,
+  IN irp__handling_ptr table
+ );
+
+extern irp__handler_decl (
+  irp__process
+ );
+
 #endif                         /* _irp_h */