[bus] Use new bus creation strategy
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Fri, 21 May 2010 19:33:32 +0000 (15:33 -0400)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Fri, 21 May 2010 19:33:32 +0000 (15:33 -0400)
When creating the boot bus or when a user manually installs
a bus device, the bus module will use the new device creation
scheme.

When the bus module initializes, it creates the boot bus,
which is a root-enumerated device via IoReportDetectedDevice().
Using this kernel function means that the PnpManager owns the
PDO.  If a user manually installs a bus device, PnpManager also
owns the PDO.  So the create_pdo() routine for a bus doesn't
make a lot of sense, except for indirectly for the case of the
boot bus only.

Also, when the IoReportDetectedDevice() is used, we must
manually call our attach_fdo() function to create the
DEVICE_OBJECT which we own and which we will associate with
the driver-internal bus & device details.

There is a really big nasty TODO left over in this commit
which should be removed as soon as possible.  In shifting to
the new device classing scheme, we are part-way through,
where some devices use a DEVICE_OBJECT's DeviceExtension as
a device__type_ptr, and the bus uses it as a device__type_ptr*.
So for now, we have the mini IRP handling system sense if it
should compensate for this.

The next steps will be to move all of the various disk types
to use counterpart strategies for device classing.  But hey,
it still boots.

src/aoe/driver.c
src/include/bus.h
src/include/device.h
src/winvblock/bus/bus.c
src/winvblock/bus/dev_ctl.c
src/winvblock/bus/pnp.c
src/winvblock/disk/pnp.c
src/winvblock/irp.c

index c3125b0..17356b8 100644 (file)
@@ -813,7 +813,7 @@ DriverEntry (
       }
     else
       {
-       irp__reg_table ( &bus_ptr->device.irp_handler_chain, handling_table );
+       irp__reg_table ( &bus_ptr->device->irp_handler_chain, handling_table );
       }
   }
   DriverObject->DriverUnload = unload;
@@ -947,7 +947,7 @@ unload (
       }
     else
       {
-       irp__unreg_table ( &bus_ptr->device.irp_handler_chain,
+       irp__unreg_table ( &bus_ptr->device->irp_handler_chain,
                           handling_table );
       }
   }
@@ -2271,7 +2271,7 @@ irp__handler_decl (
 
   DBG ( "Got IOCTL_AOE_SHOW...\n" );
 
-  bus_ptr = get_bus_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( DeviceExtension );
   disk_walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
   count = 0;
   while ( disk_walker != NULL )
index 0d9281d..6e587ea 100644 (file)
@@ -30,7 +30,7 @@
 
 winvblock__def_struct ( bus__type )
 {
-  device__type device;
+  device__type_ptr device;
   PDEVICE_OBJECT LowerDeviceObject;
   PDEVICE_OBJECT PhysicalDeviceObject;
   winvblock__uint32 Children;
@@ -39,6 +39,9 @@ winvblock__def_struct ( bus__type )
   LIST_ENTRY tracking;
   winvblock__any_ptr ext;
   device__free_routine prev_free;
+  UNICODE_STRING dev_name;
+  UNICODE_STRING dos_dev_name;
+  winvblock__bool named;
 };
 
 extern NTSTATUS STDCALL Bus_GetDeviceCapabilities (
@@ -99,11 +102,10 @@ extern winvblock__lib_func bus__type_ptr bus__boot (
  );
 
 /*
- * Establish a pointer to the bus.
- * Since the device extension is the first member of a bus
- * structure, a simple cast will suffice
+ * Yield a pointer to the bus.  Whoa
  */
-#  define get_bus_ptr( dev_ptr ) \
-  ( ( bus__type_ptr ) dev_ptr )
+#  define bus__get_ptr( dev_ext )                                       \
+  ( ( bus__type_ptr )                                                   \
+    ( ( ( device__type_ptr* ) dev_ext )[0]->TODO_temp_measure->ext ) )
 
 #endif                         /* _bus_h */
index b76fc3e..7e22126 100644 (file)
@@ -172,6 +172,7 @@ winvblock__def_struct ( device__ops )
 /* Details common to all devices this driver works with */
 struct _device__type
 {
+  device__type_ptr TODO_temp_measure;
   size_t size;
   winvblock__bool IsBus;       /* For debugging */
   PDEVICE_OBJECT Self;
index 5699840..59aca04 100644 (file)
 static PDEVICE_OBJECT boot_bus_fdo = NULL;
 static LIST_ENTRY bus_list;
 static KSPIN_LOCK bus_list_lock;
-/* Forward declaration */
+/* Forward declarations */
 static device__free_decl (
   free_bus
  );
+static device__create_pdo_decl (
+  create_pdo
+ );
 
 /**
  * Tear down the global, bus-common environment
@@ -107,7 +110,7 @@ bus__add_child (
    * extension space.  We don't need the original details anymore
    */
   dev_ptr = dev_obj_ptr->DeviceExtension;
-  dev_ptr->Parent = bus_ptr->device.Self;
+  dev_ptr->Parent = bus_ptr->device->Self;
   dev_ptr->next_sibling_ptr = NULL;
   /*
    * Initialize the device.  For disks, this routine is responsible for
@@ -144,7 +147,7 @@ irp__handler_decl (
   sys_ctl
  )
 {
-  bus__type_ptr bus_ptr = get_bus_ptr ( DeviceExtension );
+  bus__type_ptr bus_ptr = bus__get_ptr ( DeviceExtension );
   DBG ( "...\n" );
   IoSkipCurrentIrpStackLocation ( Irp );
   *completion_ptr = TRUE;
@@ -156,7 +159,7 @@ irp__handler_decl (
   power
  )
 {
-  bus__type_ptr bus_ptr = get_bus_ptr ( DeviceExtension );
+  bus__type_ptr bus_ptr = bus__get_ptr ( DeviceExtension );
   PoStartNextPowerIrp ( Irp );
   IoSkipCurrentIrpStackLocation ( Irp );
   *completion_ptr = TRUE;
@@ -238,81 +241,90 @@ attach_fdo (
   IN PDEVICE_OBJECT PhysicalDeviceObject
  )
 {
-  NTSTATUS Status;
-  UNICODE_STRING DeviceName,
-   DosDeviceName;
-  device__type_ptr bus_dev_ptr;
+  PLIST_ENTRY walker;
   bus__type_ptr bus_ptr;
+  NTSTATUS status;
+  PUNICODE_STRING dev_name = NULL;
+  PDEVICE_OBJECT fdo = NULL;
+  device__type_ptr dev_ptr;
 
   DBG ( "Entry\n" );
-  if ( boot_bus_fdo )
-    return STATUS_SUCCESS;
-  RtlInitUnicodeString ( &DeviceName, L"\\Device\\" winvblock__literal_w );
-  RtlInitUnicodeString ( &DosDeviceName,
-                        L"\\DosDevices\\" winvblock__literal_w );
-  Status =
-    IoCreateDevice ( DriverObject, sizeof ( bus__type ), &DeviceName,
-                    FILE_DEVICE_CONTROLLER, FILE_DEVICE_SECURE_OPEN, FALSE,
-                    &boot_bus_fdo );
-  if ( !NT_SUCCESS ( Status ) )
-    {
-      return Error ( "IoCreateDevice", Status );
-    }
-  Status = IoCreateSymbolicLink ( &DosDeviceName, &DeviceName );
-  if ( !NT_SUCCESS ( Status ) )
+  /*
+   * Search for the associated bus
+   */
+  walker = bus_list.Flink;
+  while ( walker != &bus_list )
     {
-      IoDeleteDevice ( boot_bus_fdo );
-      return Error ( "IoCreateSymbolicLink", Status );
+      bus_ptr = CONTAINING_RECORD ( walker, bus__type, tracking );
+      if ( bus_ptr->PhysicalDeviceObject == PhysicalDeviceObject )
+       break;
+      walker = walker->Flink;
     }
-
   /*
-   * Set some default parameters for a bus
+   * If we get back to the list head, we need to create a bus
    */
-  bus_dev_ptr = ( device__type_ptr ) boot_bus_fdo->DeviceExtension;
-  RtlZeroMemory ( bus_dev_ptr, sizeof ( bus__type ) );
-  bus_dev_ptr->IsBus = TRUE;
-  bus_dev_ptr->size = sizeof ( bus__type );
-  bus_dev_ptr->DriverObject = DriverObject;
-  bus_dev_ptr->Self = boot_bus_fdo;
-  bus_dev_ptr->State = NotStarted;
-  bus_dev_ptr->OldState = NotStarted;
+  if ( walker == &bus_list )
+    {
+      DBG ( "No bus->PDO association.  Creating a new bus\n" );
+      bus_ptr = bus__create (  );
+      if ( bus_ptr == NULL )
+       return Error ( "Could not create a bus!\n",
+                      STATUS_INSUFFICIENT_RESOURCES );
+    }
   /*
-   * Register the default driver IRP handling table
+   * This bus might have an associated name
    */
-  irp__reg_table_s ( &bus_dev_ptr->irp_handler_chain, driver__handling_table,
-                    driver__handling_table_size );
+  if ( bus_ptr->named )
+    dev_name = &bus_ptr->dev_name;
+
+  status =
+    IoCreateDevice ( DriverObject, sizeof ( device__type_ptr ), dev_name,
+                    FILE_DEVICE_CONTROLLER, FILE_DEVICE_SECURE_OPEN, FALSE,
+                    &fdo );
+  if ( !NT_SUCCESS ( status ) )
+    {
+      return Error ( "IoCreateDevice", status );
+    }
   /*
-   * Register the default bus IRP handling table
+   * DosDevice symlink
    */
-  irp__reg_table ( &bus_dev_ptr->irp_handler_chain, handling_table );
+  if ( bus_ptr->named )
+    status =
+      IoCreateSymbolicLink ( &bus_ptr->dos_dev_name, &bus_ptr->dev_name );
+  if ( !NT_SUCCESS ( status ) )
+    {
+      IoDeleteDevice ( fdo );
+      return Error ( "IoCreateSymbolicLink", status );
+    }
+
   /*
-   * Establish a pointer to the bus
+   * Set associations for the bus, device, FDO, PDO
    */
-  bus_ptr = get_bus_ptr ( bus_dev_ptr );
+  dev_ptr = bus_ptr->device;
+  *( ( device__type_ptr * ) fdo->DeviceExtension ) = dev_ptr;  /* Careful */
+  dev_ptr->DriverObject = DriverObject;
+  dev_ptr->Self = fdo;
+
   bus_ptr->PhysicalDeviceObject = PhysicalDeviceObject;
-  bus_ptr->Children = 0;
-  bus_ptr->first_child_ptr = NULL;
-  KeInitializeSpinLock ( &bus_ptr->SpinLock );
-  boot_bus_fdo->Flags |= DO_DIRECT_IO; /* FIXME? */
-  boot_bus_fdo->Flags |= DO_POWER_INRUSH;      /* FIXME? */
+  fdo->Flags |= DO_DIRECT_IO;  /* FIXME? */
+  fdo->Flags |= DO_POWER_INRUSH;       /* FIXME? */
   /*
    * Add the bus to the device tree
    */
   if ( PhysicalDeviceObject != NULL )
     {
       bus_ptr->LowerDeviceObject =
-       IoAttachDeviceToDeviceStack ( boot_bus_fdo, PhysicalDeviceObject );
+       IoAttachDeviceToDeviceStack ( fdo, PhysicalDeviceObject );
       if ( bus_ptr->LowerDeviceObject == NULL )
        {
-         IoDeleteDevice ( boot_bus_fdo );
-         boot_bus_fdo = NULL;
+         IoDeleteDevice ( fdo );
          return Error ( "IoAttachDeviceToDeviceStack",
                         STATUS_NO_SUCH_DEVICE );
        }
     }
-  boot_bus_fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+  fdo->Flags &= ~DO_DEVICE_INITIALIZING;
 #ifdef RIS
-  bus_dev_ptr->State = Started;
+  dev_ptr->State = Started;
 #endif
   DBG ( "Exit\n" );
   return STATUS_SUCCESS;
@@ -355,9 +367,18 @@ bus__create (
   /*
    * Populate non-zero device defaults
    */
+  bus_ptr->device = dev_ptr;
   bus_ptr->prev_free = dev_ptr->ops.free;
+  dev_ptr->TODO_temp_measure = dev_ptr;
+  dev_ptr->ops.create_pdo = create_pdo;
   dev_ptr->ops.free = free_bus;
   dev_ptr->ext = bus_ptr;
+  dev_ptr->IsBus = TRUE;
+  dev_ptr->State = NotStarted;
+  dev_ptr->OldState = NotStarted;
+  bus_ptr->Children = 0;
+  bus_ptr->first_child_ptr = NULL;
+  KeInitializeSpinLock ( &bus_ptr->SpinLock );
   /*
    * Register the default bus IRP handling table
    */
@@ -387,8 +408,18 @@ device__create_pdo_decl (
  )
 {
   PDEVICE_OBJECT pdo_ptr = NULL;
+  bus__type_ptr bus_ptr;
   NTSTATUS status;
 
+  /*
+   * Note the bus device needing a PDO
+   */
+  if ( dev_ptr == NULL )
+    {
+      DBG ( "No device passed\n" );
+      return NULL;
+    }
+  bus_ptr = ( bus__type_ptr ) dev_ptr->ext;
   /*
    * Always create the root-enumerated bus device 
    */
@@ -400,7 +431,16 @@ device__create_pdo_decl (
       return NULL;
     }
   /*
-   * Attach FDO to PDO *sigh*
+   * We have a PDO.  Note it in the bus
+   */
+  bus_ptr->PhysicalDeviceObject = pdo_ptr;
+  /*
+   * Attach FDO to PDO. *sigh*  Note that we do not own the PDO,
+   * so we must associate the bus structure with the FDO, instead.
+   * Consider that the AddDevice()/attach_fdo() routine takes two parameters,
+   * neither of which are guaranteed to be owned by a caller in this driver.
+   * Since attach_fdo() associates a bus device, it is forced to walk our
+   * global list of bus devices.  Otherwise, it would be easy to pass it here
    */
   status = attach_fdo ( driver__obj_ptr, pdo_ptr );
   if ( !NT_SUCCESS ( status ) )
@@ -426,6 +466,8 @@ bus__init (
   void
  )
 {
+  bus__type_ptr boot_bus_ptr;
+
   /*
    * Initialize the global list of devices
    */
@@ -438,8 +480,22 @@ bus__init (
   /*
    * Establish the boot bus (required for booting from a WinVBlock disk)
    */
-  if ( create_pdo ( NULL ) == NULL )   /* TODO: Pass a bus */
+  boot_bus_ptr = bus__create (  );
+  if ( boot_bus_ptr == NULL )
     return STATUS_UNSUCCESSFUL;
+  RtlInitUnicodeString ( &boot_bus_ptr->dev_name,
+                        L"\\Device\\" winvblock__literal_w );
+  RtlInitUnicodeString ( &boot_bus_ptr->dos_dev_name,
+                        L"\\DosDevices\\" winvblock__literal_w );
+  /*
+   * Create the PDO, which also attaches the FDO *sigh*
+   */
+  if ( create_pdo ( boot_bus_ptr->device ) == NULL )
+    {
+      free_bus ( boot_bus_ptr->device );
+      return STATUS_UNSUCCESSFUL;
+    }
+  boot_bus_fdo = boot_bus_ptr->device->Self;
 
   return STATUS_SUCCESS;
 }
@@ -474,9 +530,9 @@ device__free_decl (
 }
 
 /**
- * Get a pointer to the bus device's extension space
+ * Get a pointer to the boot bus device
  *
- * @ret         A pointer to the bus device's extension space, or NULL
+ * @ret         A pointer to the boot bus, or NULL
  */
 winvblock__lib_func bus__type_ptr
 bus__boot (
@@ -488,5 +544,5 @@ bus__boot (
       DBG ( "No boot bus device!\n" );
       return NULL;
     }
-  return get_bus_ptr ( boot_bus_fdo->DeviceExtension );
+  return bus__get_ptr ( boot_bus_fdo->DeviceExtension );
 }
index 9e25af6..003ca5d 100644 (file)
@@ -50,7 +50,7 @@ irp__handler_decl (
   bus__type_ptr bus_ptr;
 
   DBG ( "Request to detach disk: %d\n", *( winvblock__uint32_ptr ) buffer );
-  bus_ptr = get_bus_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( DeviceExtension );
   disk_walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
   prev_disk_walker = disk_walker;
   while ( ( disk_walker != NULL )
index 72f6471..d6e22aa 100644 (file)
@@ -55,7 +55,7 @@ irp__handler_decl ( bus_pnp__start_dev )
   KEVENT event;
   bus__type_ptr bus_ptr;
 
-  bus_ptr = get_bus_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( DeviceExtension );
   KeInitializeEvent ( &event, NotificationEvent, FALSE );
   IoCopyCurrentIrpStackLocationToNext ( Irp );
   IoSetCompletionRoutine ( Irp,
@@ -91,7 +91,7 @@ irp__handler_decl ( bus_pnp__remove_dev )
   Irp->IoStatus.Information = 0;
   Irp->IoStatus.Status = STATUS_SUCCESS;
   IoSkipCurrentIrpStackLocation ( Irp );
-  bus_ptr = get_bus_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( DeviceExtension );
   status = IoCallDriver ( bus_ptr->LowerDeviceObject, Irp );
   walker = ( device__type_ptr ) bus_ptr->first_child_ptr;
   while ( walker != NULL )
@@ -117,7 +117,7 @@ irp__handler_decl ( bus_pnp__query_dev_relations )
   disk__type_ptr walker;
   PDEVICE_RELATIONS dev_relations;
 
-  bus_ptr = get_bus_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( DeviceExtension );
   if ( Stack->Parameters.QueryDeviceRelations.Type != BusRelations
        || Irp->IoStatus.Information )
     {
@@ -175,7 +175,7 @@ irp__handler_decl ( bus_pnp__simple )
   NTSTATUS status;
   bus__type_ptr bus_ptr;
 
-  bus_ptr = get_bus_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( DeviceExtension );
   switch ( Stack->MinorFunction )
     {
       case IRP_MN_QUERY_PNP_DEVICE_STATE:
index 1e67acb..2105f8b 100644 (file)
@@ -256,7 +256,7 @@ irp__handler_decl ( disk_pnp__query_capabilities )
       goto ret_path;
     }
   disk_ptr = get_disk_ptr ( DeviceExtension );
-  bus_ptr = get_bus_ptr ( DeviceExtension->Parent->DeviceExtension );
+  bus_ptr = bus__get_ptr ( DeviceExtension->Parent->DeviceExtension );
   status =
     Bus_GetDeviceCapabilities ( bus_ptr->LowerDeviceObject,
                                &ParentDeviceCapabilities );
index 283e98f..2bdc222 100644 (file)
@@ -157,8 +157,17 @@ irp__unreg_table (
 irp__handler_decl ( irp__process )
 {
   NTSTATUS status = STATUS_NOT_SUPPORTED;
-  handler_chain_ptr link =
-    ( handler_chain_ptr ) DeviceExtension->irp_handler_chain;
+  handler_chain_ptr link;
+
+  /*
+   * Temporary work-around while a bus FDO's DeviceExtension is actually
+   * a pointer to a bus pointer, but other devices' PDO's DeviceExtensions
+   * are pointers to the device structures.  Ugh
+   */
+  if ( DeviceExtension->TODO_temp_measure )
+    DeviceExtension = DeviceExtension->TODO_temp_measure;
+
+  link = ( handler_chain_ptr ) DeviceExtension->irp_handler_chain;
 
   while ( link != NULL )
     {