[major] Re-work device structures and creation
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Sun, 23 May 2010 09:18:22 +0000 (05:18 -0400)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Sun, 23 May 2010 09:18:22 +0000 (05:18 -0400)
This rather large commit affects a majority of the AoE and
WinVBlock modules.  It is unfortunately large in order to
ensure that after the series of changes were made, that a
system was still bootable from a WinVBlock disk.

What was involved:

A DEVICE_OBJECT's DeviceExtension member no longer points to
one of our device types.  All of our device types were
previously structures which included the structures they
derived functionality from as their first members.  So you
had something like a RAM disk with a disk as its first
member, a disk having a device as its first member.  So to
access any one of the structures, you could quite simply
cast a pointer.

Now a DeviceExtension points to a pointer to a device__type.
A device__type has an ext member which is a pointer to the
instance of the next-higher structure type, such as a
disk__type.  A disk__type also has an ext member, so that
AoE, RAM, and file-backed disks can extend it.

Each device class provides a global creation routine, which
tracks the device instance in a list of created devices for
that type.  The device class' creation routine should set
default parameters.  The creation routine can override the
device routines used by callers calling the routines of the
"base class" (the device type).  As an example, when you
create a RAM disk, you:
  - create a disk
    - which creates a device
    - which hook's a device routine for the device
  - hook some of the disk's routines
  - add the RAM disk to the global list

When deleting the RAM disk, you:
  - call the deletion routine you hooked for the disk
    - which calls the deletion rout. it hooked for the dev.
  - remove the RAM disk from the global list

Some copy'n'pasted comments were corrected.

Some code expecting the base-class-as-first-member-of-
derived-class was exposed and modified appropriately.

get_ptr() macros were changed.

DEVICE_OBJECT deletion paths were tied to device__free()
calls.

Some TODOs are left: More error-checking when calling
module initialization functions, watching NULL pointer
dereferences when walking sibling pointers.

23 files changed:
src/aoe/driver.c
src/include/bus.h
src/include/device.h
src/include/disk.h
src/include/driver.h
src/include/filedisk.h
src/include/irp.h
src/include/ramdisk.h
src/winvblock/bus/bus.c
src/winvblock/bus/dev_ctl.c
src/winvblock/bus/pnp.c
src/winvblock/debug.c
src/winvblock/device.c
src/winvblock/disk/dev_ctl.c
src/winvblock/disk/disk.c
src/winvblock/disk/pnp.c
src/winvblock/disk/scsi.c
src/winvblock/driver.c
src/winvblock/filedisk.c
src/winvblock/irp.c
src/winvblock/ramdisk/grub4dos.c
src/winvblock/ramdisk/memdisk.c
src/winvblock/ramdisk/ramdisk.c

index 17356b8..da79cf3 100644 (file)
@@ -50,7 +50,8 @@ extern NTSTATUS STDCALL ZwWaitForSingleObject (
   IN PLARGE_INTEGER Timeout OPTIONAL
  );
 
-/* In this file */
+/* Forward declarations */
+winvblock__def_struct ( aoe_disk_type );
 static void STDCALL thread (
   IN void *StartContext
  );
@@ -61,6 +62,12 @@ static void process_abft (
 static void STDCALL unload (
   IN PDRIVER_OBJECT DriverObject
  );
+static aoe_disk_type_ptr create_aoe_disk (
+  void
+ );
+static device__free_decl (
+  free_aoe_disk
+ );
 
 /** Tag types */
 enum _tag_type
@@ -138,7 +145,7 @@ winvblock__def_struct ( io_req )
 winvblock__def_struct ( work_tag )
 {
   tag_type type;
-  device__type_ptr DeviceExtension;
+  device__type_ptr device;
   io_req_ptr request_ptr;
   winvblock__uint32 Id;
   packet_ptr packet_data;
@@ -154,7 +161,7 @@ winvblock__def_struct ( work_tag )
 /** A disk search */
 winvblock__def_struct ( disk_search )
 {
-  device__type_ptr DeviceExtension;
+  device__type_ptr device;
   work_tag_ptr tag;
   disk_search_ptr next;
 };
@@ -173,9 +180,9 @@ enum _search_state
 winvblock__def_enum ( search_state );
 
 /** The AoE disk type */
-winvblock__def_struct ( aoe_disk_type )
+struct _aoe_disk_type
 {
-  disk__type disk;
+  disk__type_ptr disk;
   winvblock__uint32 MTU;
   winvblock__uint8 ClientMac[6];
   winvblock__uint8 ServerMac[6];
@@ -184,6 +191,8 @@ winvblock__def_struct ( aoe_disk_type )
   winvblock__uint32 MaxSectorsPerPacket;
   winvblock__uint32 Timeout;
   search_state search_state;
+  device__free_routine prev_free;
+  LIST_ENTRY tracking;
 };
 
 winvblock__def_struct ( target_list )
@@ -205,6 +214,8 @@ static disk_search_ptr AoE_Globals_DiskSearchList = NULL;
 static LONG AoE_Globals_OutstandingTags = 0;
 static HANDLE AoE_Globals_ThreadHandle;
 static winvblock__bool AoE_Globals_Started = FALSE;
+static LIST_ENTRY aoe_disk_list;
+static KSPIN_LOCK aoe_disk_list_lock;
 
 static irp__handling handling_table[] = {
   /*
@@ -703,6 +714,11 @@ DriverEntry (
 
   if ( AoE_Globals_Started )
     return STATUS_SUCCESS;
+  /*
+   * Initialize the global list of AoE disks
+   */
+  InitializeListHead ( &aoe_disk_list );
+  KeInitializeSpinLock ( &aoe_disk_list_lock );
   /*
    * Setup the Registry
    */
@@ -892,9 +908,8 @@ unload (
   disk_searcher = AoE_Globals_DiskSearchList;
   while ( disk_searcher != NULL )
     {
-      KeSetEvent ( &
-                  ( get_disk_ptr ( disk_searcher->DeviceExtension )->
-                    SearchEvent ), 0, FALSE );
+      KeSetEvent ( &( disk__get_ptr ( disk_searcher->device )->SearchEvent ),
+                  0, FALSE );
       previous_disk_searcher = disk_searcher;
       disk_searcher = disk_searcher->next;
       ExFreePool ( previous_disk_searcher );
@@ -958,7 +973,7 @@ unload (
 /**
  * Search for disk parameters
  *
- * @v DeviceExtension          The device extension for the disk
+ * @v dev_ptr                   The device extension for the disk
  *
  * Returns TRUE if the disk could be matched, FALSE otherwise.
  */
@@ -996,7 +1011,7 @@ disk__init_decl (
   /*
    * Initialize the disk search 
    */
-  disk_searcher->DeviceExtension = &disk_ptr->device;
+  disk_searcher->device = disk_ptr->device;
   disk_searcher->next = NULL;
   aoe_disk_ptr->search_state = search_state_search_nic;
   KeResetEvent ( &disk_ptr->SearchEvent );
@@ -1176,8 +1191,7 @@ disk__init_decl (
               */
              disk_search_walker = AoE_Globals_DiskSearchList;
              while ( disk_search_walker
-                     && disk_search_walker->DeviceExtension !=
-                     &disk_ptr->device )
+                     && disk_search_walker->device != disk_ptr->device )
                {
                  previous_disk_searcher = disk_search_walker;
                  disk_search_walker = disk_search_walker->next;
@@ -1240,7 +1254,7 @@ disk__init_decl (
        }
       RtlZeroMemory ( tag, sizeof ( work_tag ) );
       tag->type = tag_type_search_drive;
-      tag->DeviceExtension = &disk_ptr->device;
+      tag->device = disk_ptr->device;
 
       /*
        * Establish our tag's AoE packet 
@@ -1354,7 +1368,7 @@ disk__io_decl (
   /*
    * Establish pointers to the disk and AoE disk
    */
-  disk_ptr = get_disk_ptr ( dev_ptr );
+  disk_ptr = disk__get_ptr ( dev_ptr );
   aoe_disk_ptr = get_aoe_disk_ptr ( dev_ptr );
 
   if ( AoE_Globals_Stop )
@@ -1442,7 +1456,7 @@ disk__io_decl (
       RtlZeroMemory ( tag, sizeof ( work_tag ) );
       tag->type = tag_type_io;
       tag->request_ptr = request_ptr;
-      tag->DeviceExtension = dev_ptr;
+      tag->device = dev_ptr;
       request_ptr->TagCount++;
       tag->Id = 0;
       tag->BufferOffset = i * disk_ptr->SectorSize;
@@ -1730,8 +1744,8 @@ aoe__reply (
   /*
    * Establish pointers to the disk device and AoE disk
    */
-  disk_ptr = get_disk_ptr ( tag->DeviceExtension );
-  aoe_disk_ptr = get_aoe_disk_ptr ( tag->DeviceExtension );
+  disk_ptr = disk__get_ptr ( tag->device );
+  aoe_disk_ptr = get_aoe_disk_ptr ( tag->device );
 
   /*
    * If our tag was a discovery request, note the server 
@@ -1960,8 +1974,8 @@ thread (
          /*
           * Establish pointers to the disk and AoE disk
           */
-         disk_ptr = get_disk_ptr ( tag->DeviceExtension );
-         aoe_disk_ptr = get_aoe_disk_ptr ( tag->DeviceExtension );
+         disk_ptr = disk__get_ptr ( tag->device );
+         aoe_disk_ptr = get_aoe_disk_ptr ( tag->device );
 
          RequestTimeout = aoe_disk_ptr->Timeout;
          if ( tag->Id == 0 )
@@ -2098,14 +2112,6 @@ disk__close_decl ( close )
   return;
 }
 
-static disk__ops default_ops = {
-  io,
-  max_xfer_len,
-  init,
-  query_id,
-  close
-};
-
 static void
 process_abft (
   void
@@ -2118,7 +2124,7 @@ process_abft (
    i;
   winvblock__bool FoundAbft = FALSE;
   abft AoEBootRecord;
-  aoe_disk_type aoe_disk;
+  aoe_disk_type_ptr aoe_disk_ptr;
 
   /*
    * Find aBFT
@@ -2170,24 +2176,27 @@ process_abft (
 
   if ( FoundAbft )
     {
+      aoe_disk_ptr = create_aoe_disk (  );
+      if ( aoe_disk_ptr == NULL )
+       {
+         DBG ( "Could not create AoE disk from aBFT!\n" );
+         return;
+       }
       DBG ( "Attaching AoE disk from client NIC "
            "%02x:%02x:%02x:%02x:%02x:%02x to major: %d minor: %d\n",
            AoEBootRecord.ClientMac[0], AoEBootRecord.ClientMac[1],
            AoEBootRecord.ClientMac[2], AoEBootRecord.ClientMac[3],
            AoEBootRecord.ClientMac[4], AoEBootRecord.ClientMac[5],
            AoEBootRecord.Major, AoEBootRecord.Minor );
-      RtlCopyMemory ( aoe_disk.ClientMac, AoEBootRecord.ClientMac, 6 );
-      RtlFillMemory ( aoe_disk.ServerMac, 6, 0xff );
-      aoe_disk.Major = AoEBootRecord.Major;
-      aoe_disk.Minor = AoEBootRecord.Minor;
-      aoe_disk.MaxSectorsPerPacket = 1;
-      aoe_disk.Timeout = 200000;       /* 20 ms. */
-      aoe_disk.disk.BootDrive = TRUE;
-      aoe_disk.disk.media = disk__media_hard;
-      aoe_disk.disk.ops = &default_ops;
-      disk__put_dev_ops ( &aoe_disk.disk.device );
-      aoe_disk.disk.device.size = sizeof ( aoe_disk_type );
-      bus__add_child ( bus__boot (  ), &aoe_disk.disk.device );
+      RtlCopyMemory ( aoe_disk_ptr->ClientMac, AoEBootRecord.ClientMac, 6 );
+      RtlFillMemory ( aoe_disk_ptr->ServerMac, 6, 0xff );
+      aoe_disk_ptr->Major = AoEBootRecord.Major;
+      aoe_disk_ptr->Minor = AoEBootRecord.Minor;
+      aoe_disk_ptr->MaxSectorsPerPacket = 1;
+      aoe_disk_ptr->Timeout = 200000;  /* 20 ms. */
+      aoe_disk_ptr->disk->BootDrive = TRUE;
+      aoe_disk_ptr->disk->media = disk__media_hard;
+      bus__add_child ( bus__boot (  ), aoe_disk_ptr->disk->device );
     }
   else
     {
@@ -2271,13 +2280,13 @@ irp__handler_decl (
 
   DBG ( "Got IOCTL_AOE_SHOW...\n" );
 
-  bus_ptr = bus__get_ptr ( DeviceExtension );
-  disk_walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
+  bus_ptr = bus__get_ptr ( dev_ptr );
+  disk_walker = disk__get_ptr ( bus_ptr->first_child_ptr );
   count = 0;
   while ( disk_walker != NULL )
     {
       count++;
-      disk_walker = ( disk__type_ptr ) disk_walker->device.next_sibling_ptr;
+      disk_walker = disk__get_ptr ( disk_walker->device->next_sibling_ptr );
     }
 
   if ( ( disks =
@@ -2298,7 +2307,7 @@ irp__handler_decl (
   disks->Count = count;
 
   count = 0;
-  disk_walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
+  disk_walker = disk__get_ptr ( bus_ptr->first_child_ptr );
   while ( disk_walker != NULL )
     {
       aoe_disk_type_ptr aoe_disk_ptr =
@@ -2313,7 +2322,7 @@ irp__handler_decl (
       disks->Disk[count].Minor = aoe_disk_ptr->Minor;
       disks->Disk[count].LBASize = disk_walker->LBADiskSize;
       count++;
-      disk_walker = ( disk__type_ptr ) disk_walker->device.next_sibling_ptr;
+      disk_walker = disk__get_ptr ( disk_walker->device->next_sibling_ptr );
     }
   RtlCopyMemory ( Irp->AssociatedIrp.SystemBuffer, disks,
                  ( Stack->Parameters.DeviceIoControl.OutputBufferLength <
@@ -2336,24 +2345,29 @@ irp__handler_decl (
  )
 {
   winvblock__uint8_ptr buffer = Irp->AssociatedIrp.SystemBuffer;
-  aoe_disk_type aoe_disk;
+  aoe_disk_type_ptr aoe_disk_ptr;
 
   DBG ( "Got IOCTL_AOE_MOUNT for client: %02x:%02x:%02x:%02x:%02x:%02x "
        "Major:%d Minor:%d\n", buffer[0], buffer[1], buffer[2], buffer[3],
        buffer[4], buffer[5], *( winvblock__uint16_ptr ) ( &buffer[6] ),
        ( winvblock__uint8 ) buffer[8] );
-  RtlCopyMemory ( aoe_disk.ClientMac, buffer, 6 );
-  RtlFillMemory ( aoe_disk.ServerMac, 6, 0xff );
-  aoe_disk.Major = *( winvblock__uint16_ptr ) ( &buffer[6] );
-  aoe_disk.Minor = ( winvblock__uint8 ) buffer[8];
-  aoe_disk.MaxSectorsPerPacket = 1;
-  aoe_disk.Timeout = 200000;   /* 20 ms. */
-  aoe_disk.disk.BootDrive = FALSE;
-  aoe_disk.disk.media = disk__media_hard;
-  aoe_disk.disk.ops = &default_ops;
-  disk__put_dev_ops ( &aoe_disk.disk.device );
-  aoe_disk.disk.device.size = sizeof ( aoe_disk_type );
-  bus__add_child ( bus__boot (  ), &aoe_disk.disk.device );
+  aoe_disk_ptr = create_aoe_disk (  );
+  if ( aoe_disk_ptr == NULL )
+    {
+      DBG ( "Could not create AoE disk!\n" );
+      Irp->IoStatus.Information = 0;
+      *completion_ptr = TRUE;
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
+  RtlCopyMemory ( aoe_disk_ptr->ClientMac, buffer, 6 );
+  RtlFillMemory ( aoe_disk_ptr->ServerMac, 6, 0xff );
+  aoe_disk_ptr->Major = *( winvblock__uint16_ptr ) ( &buffer[6] );
+  aoe_disk_ptr->Minor = ( winvblock__uint8 ) buffer[8];
+  aoe_disk_ptr->MaxSectorsPerPacket = 1;
+  aoe_disk_ptr->Timeout = 200000;      /* 20 ms. */
+  aoe_disk_ptr->disk->BootDrive = FALSE;
+  aoe_disk_ptr->disk->media = disk__media_hard;
+  bus__add_child ( bus__boot (  ), aoe_disk_ptr->disk->device );
   Irp->IoStatus.Information = 0;
   *completion_ptr = TRUE;
   return STATUS_SUCCESS;
@@ -2366,16 +2380,13 @@ irp__handler_decl ( aoe__bus_dev_ctl_dispatch )
   switch ( Stack->Parameters.DeviceIoControl.IoControlCode )
     {
       case IOCTL_AOE_SCAN:
-       status =
-         scan ( DeviceObject, Irp, Stack, DeviceExtension, completion_ptr );
+       status = scan ( DeviceObject, Irp, Stack, dev_ptr, completion_ptr );
        break;
       case IOCTL_AOE_SHOW:
-       status =
-         show ( DeviceObject, Irp, Stack, DeviceExtension, completion_ptr );
+       status = show ( DeviceObject, Irp, Stack, dev_ptr, completion_ptr );
        break;
       case IOCTL_AOE_MOUNT:
-       status =
-         mount ( DeviceObject, Irp, Stack, DeviceExtension, completion_ptr );
+       status = mount ( DeviceObject, Irp, Stack, dev_ptr, completion_ptr );
        break;
       case IOCTL_AOE_UMOUNT:
        Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_FILE_DETACH;
@@ -2385,3 +2396,90 @@ irp__handler_decl ( aoe__bus_dev_ctl_dispatch )
     IoCompleteRequest ( Irp, IO_NO_INCREMENT );
   return status;
 }
+
+/**
+ * Create a new AoE disk
+ *
+ * @ret aoe_disk_ptr    The address of a new AoE disk, or NULL for failure
+ *
+ * This function should not be confused with a PDO creation routine, which is
+ * actually implemented for each device type.  This routine will allocate a
+ * aoe_disk_type, track it in a global list, as well as populate the disk
+ * with default values.
+ */
+static aoe_disk_type_ptr
+create_aoe_disk (
+  void
+ )
+{
+  disk__type_ptr disk_ptr;
+  aoe_disk_type_ptr aoe_disk_ptr;
+
+  /*
+   * Try to create a disk
+   */
+  disk_ptr = disk__create (  );
+  if ( disk_ptr == NULL )
+    goto err_nodisk;
+  /*
+   * AoE disk devices might be used for booting and should
+   * not be allocated from a paged memory pool
+   */
+  aoe_disk_ptr = ExAllocatePool ( NonPagedPool, sizeof ( aoe_disk_type ) );
+  if ( aoe_disk_ptr == NULL )
+    goto err_noaoedisk;
+  RtlZeroMemory ( aoe_disk_ptr, sizeof ( aoe_disk_type ) );
+  /*
+   * Track the new AoE disk in our global list
+   */
+  ExInterlockedInsertTailList ( &aoe_disk_list, &aoe_disk_ptr->tracking,
+                               &aoe_disk_list_lock );
+  /*
+   * Populate non-zero device defaults
+   */
+  aoe_disk_ptr->disk = disk_ptr;
+  aoe_disk_ptr->prev_free = disk_ptr->device->ops.free;
+  disk_ptr->device->ops.free = free_aoe_disk;
+  disk_ptr->disk_ops.io = io;
+  disk_ptr->disk_ops.max_xfer_len = max_xfer_len;
+  disk_ptr->disk_ops.pnp_id = query_id;
+  disk_ptr->disk_ops.init = init;
+  disk_ptr->disk_ops.close = close;
+  disk_ptr->ext = aoe_disk_ptr;
+
+  return aoe_disk_ptr;
+
+err_noaoedisk:
+
+  device__free ( disk_ptr->device );
+err_nodisk:
+
+  return NULL;
+}
+
+/**
+ * Default AoE disk deletion operation
+ *
+ * @v dev_ptr           Points to the AoE disk device to delete
+ */
+static
+device__free_decl (
+  free_aoe_disk
+ )
+{
+  disk__type_ptr disk_ptr = disk__get_ptr ( dev_ptr );
+  aoe_disk_type_ptr aoe_disk_ptr = get_aoe_disk_ptr ( dev_ptr );
+  /*
+   * Free the "inherited class"
+   */
+  aoe_disk_ptr->prev_free ( dev_ptr );
+  /*
+   * Track the AoE disk deletion in our global list.  Unfortunately,
+   * for now we have faith that an AoE disk won't be deleted twice and
+   * result in a race condition.  Something to keep in mind...
+   */
+  ExInterlockedRemoveHeadList ( aoe_disk_ptr->tracking.Blink,
+                               &aoe_disk_list_lock );
+
+  ExFreePool ( aoe_disk_ptr );
+}
index 6e587ea..4249fee 100644 (file)
@@ -34,7 +34,7 @@ winvblock__def_struct ( bus__type )
   PDEVICE_OBJECT LowerDeviceObject;
   PDEVICE_OBJECT PhysicalDeviceObject;
   winvblock__uint32 Children;
-  winvblock__uint8_ptr first_child_ptr;
+  device__type_ptr first_child_ptr;
   KSPIN_LOCK SpinLock;
   LIST_ENTRY tracking;
   winvblock__any_ptr ext;
@@ -54,7 +54,7 @@ extern NTSTATUS STDCALL Bus_GetDeviceCapabilities (
  *
  * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure
  */
-extern STDCALL NTSTATUS bus__init (
+extern NTSTATUS bus__init (
   void
  );
 
@@ -102,10 +102,8 @@ extern winvblock__lib_func bus__type_ptr bus__boot (
  );
 
 /*
- * Yield a pointer to the bus.  Whoa
+ * Yield a pointer to the bus
  */
-#  define bus__get_ptr( dev_ext )                                       \
-  ( ( bus__type_ptr )                                                   \
-    ( ( ( device__type_ptr* ) dev_ext )[0]->TODO_temp_measure->ext ) )
+#  define bus__get_ptr( dev_ptr ) ( ( bus__type_ptr ) dev_ptr->ext )
 
 #endif                         /* _bus_h */
index 7e22126..d4bdae7 100644 (file)
@@ -110,6 +110,14 @@ x ( \
 typedef device__close_decl (
    ( *device__close_routine )
  );
+/**
+ * Close a device
+ *
+ * @v dev_ptr           Points to the device to close
+ */
+extern winvblock__lib_func device__close_decl (
+  device__close
+ );
 
 /**
  * Device deletion routine
@@ -134,8 +142,8 @@ typedef device__free_decl (
  *
  * @v dev_ptr           Points to the device to delete
  */
-extern winvblock__lib_func STDCALL void device__free (
-  device__type_ptr dev_ptr
+extern winvblock__lib_func device__free_decl (
+  device__free
  );
 
 /**
@@ -172,8 +180,6 @@ 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;
   PDEVICE_OBJECT Parent;
index 5148a84..3755fd0 100644 (file)
@@ -55,7 +55,7 @@ winvblock__def_struct ( disk__type );
 /**
  * I/O Request
  *
- * @v dev_ptr           The device extension space
+ * @v dev_ptr           Points to the disk's device structure
  * @v mode              Read / write mode
  * @v start_sector      First sector for request
  * @v sector_count      Number of sectors to work with
@@ -64,7 +64,7 @@ winvblock__def_struct ( disk__type );
  */
 #  define disk__io_decl( x ) \
 \
-NTSTATUS \
+NTSTATUS STDCALL \
 x ( \
   IN device__type_ptr dev_ptr, \
   IN disk__io_mode mode, \
@@ -100,10 +100,6 @@ typedef disk__max_xfer_len_decl (
    ( *disk__max_xfer_len_routine )
  );
 
-extern disk__max_xfer_len_decl (
-  disk__default_max_xfer_len
- );
-
 /**
  * Disk initialization routine
  *
@@ -123,10 +119,6 @@ typedef disk__init_decl (
    ( *disk__init_routine )
  );
 
-extern disk__init_decl (
-  disk__default_init
- );
-
 /**
  * Disk PnP ID reponse routine
  *
@@ -171,10 +163,6 @@ typedef disk__close_decl (
    ( *disk__close_routine )
  );
 
-extern disk__close_decl (
-  disk__default_close
- );
-
 winvblock__def_struct ( disk__ops )
 {
   disk__io_routine io;
@@ -186,68 +174,39 @@ winvblock__def_struct ( disk__ops )
 
 struct _disk__type
 {
-  device__type device;
+  device__type_ptr device;
   KEVENT SearchEvent;
   KSPIN_LOCK SpinLock;
   winvblock__bool BootDrive;
   winvblock__bool Unmount;
   winvblock__uint32 DiskNumber;
   disk__media media;
-  disk__ops_ptr ops;
+  disk__ops disk_ops;
   LONGLONG LBADiskSize;
   LONGLONG Cylinders;
   winvblock__uint32 Heads;
   winvblock__uint32 Sectors;
   winvblock__uint32 SectorSize;
   winvblock__uint32 SpecialFileCount;
+  device__free_routine prev_free;
+  LIST_ENTRY tracking;
+  winvblock__any_ptr ext;
 };
 
-/* Device operations for disks */
-extern device__ops disk__dev_ops;
-/* Copy default disk device operations into a device */
-winvblock__lib_func void disk__put_dev_ops (
-  device__type_ptr dev
- );
-
 /*
- * Establish a pointer to the child disk.
- * Since the device extension is the first member of a disk
- * structure, a simple cast will suffice
+ * Yield a pointer to the disk
  */
-#  define get_disk_ptr( dev_ptr ) \
-  ( ( disk__type_ptr ) dev_ptr )
+#  define disk__get_ptr( dev_ptr ) ( ( disk__type_ptr ) dev_ptr->ext )
 
-__inline
-disk__io_decl (
+extern disk__io_decl (
   disk__io
- )
-{
-  disk__type_ptr disk_ptr;
-
-  /*
-   * Establish a pointer to the disk
-   */
-  disk_ptr = get_disk_ptr ( dev_ptr );
-
-  return disk_ptr->ops->io ( dev_ptr, mode, start_sector, sector_count, buffer,
-                            irp );
-}
-
-__inline
-disk__max_xfer_len_decl (
+ );
+extern disk__max_xfer_len_decl (
   disk__max_xfer_len
- )
-{
-  return disk_ptr->ops->max_xfer_len ( disk_ptr );
-}
-
-__inline
-disk__pnp_id_decl (
+ );
+extern disk__pnp_id_decl (
   disk__query_id
- )
-{
-  return disk_ptr->ops->pnp_id ( disk_ptr, query_type, buf_512 );
-}
+ );
 
 /**
  * Attempt to guess a disk's geometry
@@ -260,4 +219,27 @@ extern winvblock__lib_func void disk__guess_geometry (
   IN OUT disk__type_ptr disk_ptr
  );
 
+/**
+ * Create a new disk
+ *
+ * @ret disk_ptr        The address of a new disk, or NULL for failure
+ *
+ * This function should not be confused with a PDO creation routine, which is
+ * actually implemented for each device type.  This routine will allocate a
+ * disk__type, track it in a global list, as well as populate the disk
+ * with default values.
+ */
+extern winvblock__lib_func disk__type_ptr disk__create (
+  void
+ );
+
+/**
+ * Initialize the global, disk-common environment
+ *
+ * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure
+ */
+extern NTSTATUS disk__init (
+  void
+ );
+
 #endif                         /* _disk_h */
index 5bec5f0..5fda5a6 100644 (file)
@@ -62,4 +62,13 @@ extern NTSTATUS STDCALL DriverEntry (
   IN PUNICODE_STRING RegistryPath
  );
 
+/* An unfortunate forward declaration.  Definition resolved in device.h */
+winvblock__def_struct ( device__type );
+
+/* The physical/function device object's (PDO's/FDO's) DeviceExtension */
+winvblock__def_struct ( driver__dev_ext )
+{
+  device__type_ptr device;
+};
+
 #endif                         /* _DRIVER_H */
index ed20456..5de36bb 100644 (file)
  *
  */
 
-winvblock__def_struct ( filedisk__type )
-{
-  disk__type disk;
-  HANDLE file;
-  winvblock__uint32 hash;
-};
-
-/*
- * Establish a pointer to the file-backed disk.
- * Since the device extension is the first member of the disk
- * member of a file-backed disk, and the disk structure is itself the
- * first member of a file-backed disk structure, a simple cast will suffice
- */
-#  define filedisk__get_ptr( dev_ptr ) \
-  ( ( filedisk__type_ptr ) dev_ptr )
-
 extern irp__handler_decl (
   filedisk__attach
  );
 
+/**
+ * Initialize the global, file-backed disk-common environment
+ *
+ * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure
+ */
+extern NTSTATUS filedisk__init (
+  void
+ );
+
 #endif                         /* _filedisk_h */
index 64a8deb..0341df8 100644 (file)
  */
 
 /* An unfortunate forward declaration.  Definition resolved in device.h */
-struct _device__type;
+winvblock__def_struct ( device__type );
 
 /* We have lots of these, so offer a convenience macro for declarations */
 #  define irp__handler_decl( x ) \
 \
-NTSTATUS STDCALL \
-x ( \
-  IN PDEVICE_OBJECT DeviceObject, \
-  IN PIRP Irp, \
-  IN PIO_STACK_LOCATION Stack, \
-  IN struct _device__type *DeviceExtension, \
-  OUT winvblock__bool_ptr completion_ptr \
+NTSTATUS STDCALL                                \
+x (                                             \
+  IN PDEVICE_OBJECT DeviceObject,               \
+  IN PIRP Irp,                                  \
+  IN PIO_STACK_LOCATION Stack,                  \
+  IN struct _device__type *dev_ptr,             \
+  OUT winvblock__bool_ptr completion_ptr        \
  )
 /*
  * Function pointer for an IRP handler.
index df64ca4..c68535e 100644 (file)
 
 winvblock__def_struct ( ramdisk__type )
 {
-  disk__type disk;
+  disk__type_ptr disk;
   winvblock__uint32 DiskBuf;
   winvblock__uint32 DiskSize;
+  device__free_routine prev_free;
+  LIST_ENTRY tracking;
 };
 
-extern disk__ops ramdisk__default_ops;
+/**
+ * Initialize the global, RAM disk-common environment
+ *
+ * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure
+ */
+extern NTSTATUS ramdisk__init (
+  void
+ );
 
-/*
- * Establish a pointer to the RAM disk.
- * Since the device extension is the first member of the disk
- * member of an AoE disk, and the disk structure is itself the
- * first member of an AoE disk structure, a simple cast will suffice
+/**
+ * Create a new RAM disk
+ *
+ * @ret ramdisk_ptr     The address of a new RAM disk, or NULL for failure
+ *
+ * This function should not be confused with a PDO creation routine, which is
+ * actually implemented for each device type.  This routine will allocate a
+ * ramdisk__type, track it in a global list, as well as populate the disk
+ * with default values.
  */
-#  define ramdisk__get_ptr( dev_ptr ) \
-  ( ( ramdisk__type_ptr ) dev_ptr )
+extern ramdisk__type_ptr ramdisk__create (
+  void
+ );
 
 #endif                         /* _ramdisk_h */
index 59aca04..4ae06de 100644 (file)
@@ -78,7 +78,7 @@ bus__finalize (
 winvblock__lib_func winvblock__bool STDCALL
 bus__add_child (
   IN OUT bus__type_ptr bus_ptr,
-  IN device__type_ptr dev_ptr
+  IN OUT device__type_ptr dev_ptr
  )
 {
   /**
@@ -102,16 +102,11 @@ bus__add_child (
   if ( dev_obj_ptr == NULL )
     {
       DBG ( "PDO creation failed!\n" );
+      device__free ( dev_ptr );
       return FALSE;
     }
 
-  /*
-   * Re-purpose dev_ptr to point into the PDO's device
-   * 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->next_sibling_ptr = NULL;
   /*
    * Initialize the device.  For disks, this routine is responsible for
    * determining the disk's geometry appropriately for AoE/RAM/file disks
@@ -123,11 +118,11 @@ bus__add_child (
    */
   if ( bus_ptr->first_child_ptr == NULL )
     {
-      bus_ptr->first_child_ptr = ( winvblock__uint8_ptr ) dev_ptr;
+      bus_ptr->first_child_ptr = dev_ptr;
     }
   else
     {
-      walker = ( device__type_ptr ) bus_ptr->first_child_ptr;
+      walker = bus_ptr->first_child_ptr;
       while ( walker->next_sibling_ptr != NULL )
        walker = walker->next_sibling_ptr;
       walker->next_sibling_ptr = dev_ptr;
@@ -147,7 +142,7 @@ irp__handler_decl (
   sys_ctl
  )
 {
-  bus__type_ptr bus_ptr = bus__get_ptr ( DeviceExtension );
+  bus__type_ptr bus_ptr = bus__get_ptr ( dev_ptr );
   DBG ( "...\n" );
   IoSkipCurrentIrpStackLocation ( Irp );
   *completion_ptr = TRUE;
@@ -159,7 +154,7 @@ irp__handler_decl (
   power
  )
 {
-  bus__type_ptr bus_ptr = bus__get_ptr ( DeviceExtension );
+  bus__type_ptr bus_ptr = bus__get_ptr ( dev_ptr );
   PoStartNextPowerIrp ( Irp );
   IoSkipCurrentIrpStackLocation ( Irp );
   *completion_ptr = TRUE;
@@ -276,13 +271,16 @@ attach_fdo (
    */
   if ( bus_ptr->named )
     dev_name = &bus_ptr->dev_name;
-
+  /*
+   * Create the bus FDO
+   */
   status =
-    IoCreateDevice ( DriverObject, sizeof ( device__type_ptr ), dev_name,
+    IoCreateDevice ( DriverObject, sizeof ( driver__dev_ext ), dev_name,
                     FILE_DEVICE_CONTROLLER, FILE_DEVICE_SECURE_OPEN, FALSE,
                     &fdo );
   if ( !NT_SUCCESS ( status ) )
     {
+      device__free ( bus_ptr->device );
       return Error ( "IoCreateDevice", status );
     }
   /*
@@ -294,6 +292,7 @@ attach_fdo (
   if ( !NT_SUCCESS ( status ) )
     {
       IoDeleteDevice ( fdo );
+      device__free ( bus_ptr->device );
       return Error ( "IoCreateSymbolicLink", status );
     }
 
@@ -301,8 +300,7 @@ attach_fdo (
    * Set associations for the bus, device, FDO, PDO
    */
   dev_ptr = bus_ptr->device;
-  *( ( device__type_ptr * ) fdo->DeviceExtension ) = dev_ptr;  /* Careful */
-  dev_ptr->DriverObject = DriverObject;
+  ( ( driver__dev_ext_ptr ) fdo->DeviceExtension )->device = dev_ptr;
   dev_ptr->Self = fdo;
 
   bus_ptr->PhysicalDeviceObject = PhysicalDeviceObject;
@@ -318,6 +316,7 @@ attach_fdo (
       if ( bus_ptr->LowerDeviceObject == NULL )
        {
          IoDeleteDevice ( fdo );
+         device__free ( bus_ptr->device );
          return Error ( "IoAttachDeviceToDeviceStack",
                         STATUS_NO_SUCH_DEVICE );
        }
@@ -360,7 +359,7 @@ bus__create (
     goto err_nobus;
   RtlZeroMemory ( bus_ptr, sizeof ( bus__type ) );
   /*
-   * Track the new device in our global list
+   * Track the new bus in our global list
    */
   ExInterlockedInsertTailList ( &bus_list, &bus_ptr->tracking,
                                &bus_list_lock );
@@ -369,15 +368,10 @@ bus__create (
    */
   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
@@ -461,7 +455,7 @@ err_add_dev:
  *
  * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure
  */
-extern STDCALL NTSTATUS
+NTSTATUS
 bus__init (
   void
  )
@@ -483,16 +477,19 @@ bus__init (
   boot_bus_ptr = bus__create (  );
   if ( boot_bus_ptr == NULL )
     return STATUS_UNSUCCESSFUL;
+  /*
+   * In booting, he has a name.  His name is WinVBlock
+   */
   RtlInitUnicodeString ( &boot_bus_ptr->dev_name,
                         L"\\Device\\" winvblock__literal_w );
   RtlInitUnicodeString ( &boot_bus_ptr->dos_dev_name,
                         L"\\DosDevices\\" winvblock__literal_w );
+  boot_bus_ptr->named = TRUE;
   /*
    * 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;
@@ -510,9 +507,9 @@ device__free_decl (
   free_bus
  )
 {
-  bus__type_ptr bus_ptr = ( bus__type_ptr ) dev_ptr->ext;
+  bus__type_ptr bus_ptr = bus__get_ptr ( dev_ptr );
   /*
-   * Un-register the default driver IRP handling table
+   * Un-register the default bus IRP handling table
    */
   irp__unreg_table ( &dev_ptr->irp_handler_chain, handling_table );
   /*
@@ -539,10 +536,13 @@ bus__boot (
   void
  )
 {
+  driver__dev_ext_ptr dev_ext_ptr;
+
   if ( !boot_bus_fdo )
     {
       DBG ( "No boot bus device!\n" );
       return NULL;
     }
-  return bus__get_ptr ( boot_bus_fdo->DeviceExtension );
+  dev_ext_ptr = ( driver__dev_ext_ptr ) boot_bus_fdo->DeviceExtension;
+  return bus__get_ptr ( dev_ext_ptr->device );
 }
index 003ca5d..ac0b931 100644 (file)
@@ -50,14 +50,14 @@ irp__handler_decl (
   bus__type_ptr bus_ptr;
 
   DBG ( "Request to detach disk: %d\n", *( winvblock__uint32_ptr ) buffer );
-  bus_ptr = bus__get_ptr ( DeviceExtension );
-  disk_walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
+  bus_ptr = bus__get_ptr ( dev_ptr );
+  disk_walker = disk__get_ptr ( bus_ptr->first_child_ptr );
   prev_disk_walker = disk_walker;
   while ( ( disk_walker != NULL )
          && ( disk_walker->DiskNumber != *( winvblock__uint32_ptr ) buffer ) )
     {
       prev_disk_walker = disk_walker;
-      disk_walker = ( disk__type_ptr ) disk_walker->device.next_sibling_ptr;
+      disk_walker = ( disk__type_ptr ) disk_walker->device->next_sibling_ptr;
     }
   if ( disk_walker != NULL )
     {
@@ -68,18 +68,17 @@ irp__handler_decl (
          return STATUS_INVALID_DEVICE_REQUEST;
        }
       DBG ( "Deleting disk %d\n", disk_walker->DiskNumber );
-      if ( disk_walker == ( disk__type_ptr ) bus_ptr->first_child_ptr )
+      if ( disk_walker == disk__get_ptr ( bus_ptr->first_child_ptr ) )
        {
-         bus_ptr->first_child_ptr =
-           ( winvblock__uint8_ptr ) disk_walker->device.next_sibling_ptr;
+         bus_ptr->first_child_ptr = disk_walker->device->next_sibling_ptr;
        }
       else
        {
-         prev_disk_walker->device.next_sibling_ptr =
-           disk_walker->device.next_sibling_ptr;
+         prev_disk_walker->device->next_sibling_ptr =
+           disk_walker->device->next_sibling_ptr;
        }
       disk_walker->Unmount = TRUE;
-      disk_walker->device.next_sibling_ptr = NULL;
+      disk_walker->device->next_sibling_ptr = NULL;
       if ( bus_ptr->PhysicalDeviceObject != NULL )
        IoInvalidateDeviceRelations ( bus_ptr->PhysicalDeviceObject,
                                      BusRelations );
@@ -96,13 +95,12 @@ irp__handler_decl ( bus_dev_ctl__dispatch )
     {
       case IOCTL_FILE_ATTACH:
        status =
-         filedisk__attach ( DeviceObject, Irp, Stack, DeviceExtension,
+         filedisk__attach ( DeviceObject, Irp, Stack, dev_ptr,
                             completion_ptr );
        break;
       case IOCTL_FILE_DETACH:
        status =
-         disk_detach ( DeviceObject, Irp, Stack, DeviceExtension,
-                       completion_ptr );
+         disk_detach ( DeviceObject, Irp, Stack, dev_ptr, completion_ptr );
        break;
       default:
        Irp->IoStatus.Information = 0;
index d6e22aa..45348c0 100644 (file)
@@ -55,7 +55,7 @@ irp__handler_decl ( bus_pnp__start_dev )
   KEVENT event;
   bus__type_ptr bus_ptr;
 
-  bus_ptr = bus__get_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( dev_ptr );
   KeInitializeEvent ( &event, NotificationEvent, FALSE );
   IoCopyCurrentIrpStackLocationToNext ( Irp );
   IoSetCompletionRoutine ( Irp,
@@ -69,8 +69,8 @@ irp__handler_decl ( bus_pnp__start_dev )
     }
   if ( NT_SUCCESS ( status = Irp->IoStatus.Status ) )
     {
-      DeviceExtension->OldState = DeviceExtension->State;
-      DeviceExtension->State = Started;
+      dev_ptr->OldState = dev_ptr->State;
+      dev_ptr->State = Started;
     }
   status = STATUS_SUCCESS;
   Irp->IoStatus.Status = status;
@@ -86,25 +86,27 @@ irp__handler_decl ( bus_pnp__remove_dev )
   device__type_ptr walker,
    next;
 
-  DeviceExtension->OldState = DeviceExtension->State;
-  DeviceExtension->State = Deleted;
+  dev_ptr->OldState = dev_ptr->State;
+  dev_ptr->State = Deleted;
   Irp->IoStatus.Information = 0;
   Irp->IoStatus.Status = STATUS_SUCCESS;
   IoSkipCurrentIrpStackLocation ( Irp );
-  bus_ptr = bus__get_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( dev_ptr );
   status = IoCallDriver ( bus_ptr->LowerDeviceObject, Irp );
-  walker = ( device__type_ptr ) bus_ptr->first_child_ptr;
+  walker = bus_ptr->first_child_ptr;
   while ( walker != NULL )
     {
-      next = ( device__type_ptr ) walker->next_sibling_ptr;
-      walker->ops.close ( walker );
+      next = walker->next_sibling_ptr;
+      device__close ( walker );
       IoDeleteDevice ( walker->Self );
+      device__free ( walker );
       walker = next;
     }
   bus_ptr->Children = 0;
   bus_ptr->first_child_ptr = NULL;
   IoDetachDevice ( bus_ptr->LowerDeviceObject );
-  IoDeleteDevice ( DeviceExtension->Self );
+  IoDeleteDevice ( dev_ptr->Self );
+  device__free ( dev_ptr );
   *completion_ptr = TRUE;
   return status;
 }
@@ -114,10 +116,10 @@ irp__handler_decl ( bus_pnp__query_dev_relations )
   NTSTATUS status;
   bus__type_ptr bus_ptr;
   winvblock__uint32 count;
-  disk__type_ptr walker;
+  device__type_ptr walker;
   PDEVICE_RELATIONS dev_relations;
 
-  bus_ptr = bus__get_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( dev_ptr );
   if ( Stack->Parameters.QueryDeviceRelations.Type != BusRelations
        || Irp->IoStatus.Information )
     {
@@ -129,11 +131,11 @@ irp__handler_decl ( bus_pnp__query_dev_relations )
     }
   probe__disks (  );
   count = 0;
-  walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
+  walker = bus_ptr->first_child_ptr;
   while ( walker != NULL )
     {
       count++;
-      walker = ( disk__type_ptr ) walker->device.next_sibling_ptr;
+      walker = walker->next_sibling_ptr;
     }
   dev_relations =
     ( PDEVICE_RELATIONS ) ExAllocatePool ( NonPagedPool,
@@ -153,13 +155,13 @@ irp__handler_decl ( bus_pnp__query_dev_relations )
   dev_relations->Count = count;
 
   count = 0;
-  walker = ( disk__type_ptr ) bus_ptr->first_child_ptr;
+  walker = bus_ptr->first_child_ptr;
   while ( walker != NULL )
     {
-      ObReferenceObject ( walker->device.Self );
-      dev_relations->Objects[count] = walker->device.Self;
+      ObReferenceObject ( walker->Self );
+      dev_relations->Objects[count] = walker->Self;
       count++;
-      walker = ( disk__type_ptr ) walker->device.next_sibling_ptr;
+      walker = walker->next_sibling_ptr;
     }
   Irp->IoStatus.Information = ( ULONG_PTR ) dev_relations;
   status = STATUS_SUCCESS;
@@ -175,7 +177,7 @@ irp__handler_decl ( bus_pnp__simple )
   NTSTATUS status;
   bus__type_ptr bus_ptr;
 
-  bus_ptr = bus__get_ptr ( DeviceExtension );
+  bus_ptr = bus__get_ptr ( dev_ptr );
   switch ( Stack->MinorFunction )
     {
       case IRP_MN_QUERY_PNP_DEVICE_STATE:
@@ -183,31 +185,31 @@ irp__handler_decl ( bus_pnp__simple )
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_QUERY_STOP_DEVICE:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = StopPending;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = StopPending;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_CANCEL_STOP_DEVICE:
-       DeviceExtension->State = DeviceExtension->OldState;
+       dev_ptr->State = dev_ptr->OldState;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_STOP_DEVICE:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = Stopped;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = Stopped;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_QUERY_REMOVE_DEVICE:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = RemovePending;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = RemovePending;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_CANCEL_REMOVE_DEVICE:
-       DeviceExtension->State = DeviceExtension->OldState;
+       dev_ptr->State = dev_ptr->OldState;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_SURPRISE_REMOVAL:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = SurpriseRemovePending;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = SurpriseRemovePending;
        status = STATUS_SUCCESS;
        break;
       default:
index 1d7aa0b..662de96 100644 (file)
@@ -234,8 +234,8 @@ Debug_DecodeIrp (
   IN PCHAR DebugMessage
  )
 {
-  device__type_ptr DeviceExtension =
-    ( device__type_ptr ) DeviceObject->DeviceExtension;
+  device__type_ptr dev_ptr =
+    ( ( driver__dev_ext_ptr ) DeviceObject->DeviceExtension )->device;
   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation ( Irp );
   PSCSI_REQUEST_BLOCK Srb;
   PCDB Cdb;
@@ -243,7 +243,7 @@ Debug_DecodeIrp (
    SectorCount;
   PSTORAGE_PROPERTY_QUERY StoragePropertyQuery;
 
-  sprintf ( DebugMessage, "%s %s", ( DeviceExtension->IsBus ? "Bus" : "Disk" ),
+  sprintf ( DebugMessage, "%s %s", ( dev_ptr->IsBus ? "Bus" : "Disk" ),
            Debug_MajorFunctionString ( Stack->MajorFunction ) );
   switch ( Stack->MajorFunction )
     {
@@ -279,7 +279,7 @@ Debug_DecodeIrp (
                  ( int )Stack->Parameters.DeviceIoControl.IoControlCode,
                  Debug_DeviceIoControlString ( Stack->Parameters.
                                                DeviceIoControl.IoControlCode ) );
-       if ( !DeviceExtension->IsBus
+       if ( !dev_ptr->IsBus
             && Stack->Parameters.DeviceIoControl.IoControlCode ==
             IOCTL_STORAGE_QUERY_PROPERTY )
          {
@@ -315,7 +315,7 @@ Debug_DecodeIrp (
          }
        break;
       case IRP_MJ_SCSI:
-       if ( !DeviceExtension->IsBus )
+       if ( !dev_ptr->IsBus )
          {
            Srb = Stack->Parameters.Scsi.Srb;
            Cdb = ( PCDB ) Srb->Cdb;
index ff9484b..f5df85b 100644 (file)
@@ -94,7 +94,6 @@ device__create (
   /*
    * Populate non-zero device defaults
    */
-  dev_ptr->size = sizeof ( device__type );
   dev_ptr->DriverObject = driver__obj_ptr;
   dev_ptr->ops.create_pdo = make_dev_pdo;
   dev_ptr->ops.free = free_dev;
@@ -137,14 +136,30 @@ device__create_pdo_decl (
   return NULL;
 }
 
+/**
+ * Close a device
+ *
+ * @v dev_ptr           Points to the device to close
+ */
+winvblock__lib_func
+device__close_decl (
+  device__close
+ )
+{
+  /*
+   * Call the device's close routine
+   */
+  dev_ptr->ops.close ( dev_ptr );
+}
+
 /**
  * Delete a device
  *
  * @v dev_ptr           Points to the device to delete
  */
-winvblock__lib_func STDCALL void
-device__free (
-  device__type_ptr dev_ptr
+winvblock__lib_func
+device__free_decl (
+  device__free
  )
 {
   /*
index eb6324b..9256727 100644 (file)
@@ -55,7 +55,7 @@ irp__handler_decl (
   STORAGE_ADAPTER_DESCRIPTOR storage_adapter_desc;
   STORAGE_DEVICE_DESCRIPTOR storage_dev_desc;
 
-  disk_ptr = get_disk_ptr ( DeviceExtension );
+  disk_ptr = disk__get_ptr ( dev_ptr );
   if ( storage_prop_query->PropertyId == StorageAdapterProperty
        && storage_prop_query->QueryType == PropertyStandardQuery )
     {
@@ -133,7 +133,7 @@ irp__handler_decl (
       sizeof ( DISK_GEOMETRY ) ? Stack->Parameters.DeviceIoControl.
       OutputBufferLength : sizeof ( DISK_GEOMETRY ) );
   disk_geom.MediaType = FixedMedia;
-  disk_ptr = get_disk_ptr ( DeviceExtension );
+  disk_ptr = disk__get_ptr ( dev_ptr );
   disk_geom.Cylinders.QuadPart = disk_ptr->Cylinders;
   disk_geom.TracksPerCylinder = disk_ptr->Heads;
   disk_geom.SectorsPerTrack = disk_ptr->Sectors;
@@ -159,7 +159,7 @@ irp__handler_decl (
   scsi_address.Length = sizeof ( SCSI_ADDRESS );
   scsi_address.PortNumber = 0;
   scsi_address.PathId = 0;
-  disk_ptr = get_disk_ptr ( DeviceExtension );
+  disk_ptr = disk__get_ptr ( dev_ptr );
   scsi_address.TargetId = ( winvblock__uint8 ) disk_ptr->DiskNumber;
   scsi_address.Lun = 0;
   RtlCopyMemory ( Irp->AssociatedIrp.SystemBuffer, &scsi_address, copy_size );
@@ -175,17 +175,17 @@ irp__handler_decl ( disk_dev_ctl__dispatch )
     {
       case IOCTL_STORAGE_QUERY_PROPERTY:
        status =
-         storage_query_prop ( DeviceObject, Irp, Stack, DeviceExtension,
+         storage_query_prop ( DeviceObject, Irp, Stack, dev_ptr,
                               completion_ptr );
        break;
       case IOCTL_DISK_GET_DRIVE_GEOMETRY:
        status =
-         disk_get_drive_geom ( DeviceObject, Irp, Stack, DeviceExtension,
+         disk_get_drive_geom ( DeviceObject, Irp, Stack, dev_ptr,
                                completion_ptr );
        break;
       case IOCTL_SCSI_GET_ADDRESS:
        status =
-         scsi_get_address ( DeviceObject, Irp, Stack, DeviceExtension,
+         scsi_get_address ( DeviceObject, Irp, Stack, dev_ptr,
                             completion_ptr );
        break;
        /*
index 07e01e3..e71febf 100644 (file)
@@ -51,11 +51,20 @@ __divdi3 (
 #endif
 
 static winvblock__uint32 next_disk = 0;
+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 declaration */
+static device__free_decl (
+  free_disk
+ );
 
-disk__max_xfer_len_decl ( disk__default_max_xfer_len )
+static
+disk__max_xfer_len_decl (
+  default_max_xfer_len
+ )
 {
   return 1024 * 1024;
 }
@@ -65,11 +74,11 @@ device__init_decl (
   init
  )
 {
-  disk__type_ptr disk_ptr = get_disk_ptr ( dev_ptr );
-  return disk_ptr->ops->init ( disk_ptr );
+  disk__type_ptr disk_ptr = disk__get_ptr ( dev_ptr );
+  return disk_ptr->disk_ops.init ( disk_ptr );
 }
 
-disk__init_decl ( disk__default_init )
+disk__init_decl ( default_init )
 {
   return TRUE;
 }
@@ -79,12 +88,12 @@ device__close_decl (
   close
  )
 {
-  disk__type_ptr disk_ptr = get_disk_ptr ( dev_ptr );
-  disk_ptr->ops->close ( disk_ptr );
+  disk__type_ptr disk_ptr = disk__get_ptr ( dev_ptr );
+  disk_ptr->disk_ops.close ( disk_ptr );
   return;
 }
 
-disk__close_decl ( disk__default_close )
+disk__close_decl ( default_close )
 {
   return;
 }
@@ -156,7 +165,7 @@ device__create_pdo_decl (
   /**
    * @v disk_ptr          Used for pointing to disk details
    * @v status            Status of last operation
-   * @v dev_obj_ptr       The new node's device object
+   * @v dev_obj_ptr       The new node's physical device object (PDO)
    * @v new_ext_size      The extension space size
    * @v disk_types[]      Floppy, hard disk, optical disc specifics
    * @v characteristics[] Floppy, hard disk, optical disc specifics
@@ -175,13 +184,12 @@ device__create_pdo_decl (
   /*
    * Point to the disk details provided
    */
-  disk_ptr = get_disk_ptr ( dev_ptr );
+  disk_ptr = disk__get_ptr ( dev_ptr );
   /*
-   * Create the disk device.  Whoever calls us should have set
-   * the device extension space size requirement appropriately
+   * Create the disk PDO
    */
   status =
-    IoCreateDevice ( driver__obj_ptr, disk_ptr->device.size, NULL,
+    IoCreateDevice ( driver__obj_ptr, sizeof ( driver__dev_ext ), NULL,
                     disk_types[disk_ptr->media],
                     FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN |
                     characteristics[disk_ptr->media], FALSE, &dev_obj_ptr );
@@ -191,43 +199,12 @@ device__create_pdo_decl (
       return NULL;
     }
   /*
-   * Re-purpose dev_ptr to point into the PDO's device
-   * extension space.  We have disk_ptr still for original details
-   */
-  dev_ptr = dev_obj_ptr->DeviceExtension;
-  /*
-   * Clear the extension space and establish parameters
-   */
-  RtlZeroMemory ( dev_ptr, disk_ptr->device.size );
-  /*
-   * Copy the provided disk parameters into the disk extension space
+   * Set associations for the PDO, device, disk
    */
-  RtlCopyMemory ( dev_ptr, &disk_ptr->device, disk_ptr->device.size );
-  /*
-   * Universal disk properties the caller needn't bother with
-   */
-  dev_ptr->IsBus = FALSE;
+  ( ( driver__dev_ext_ptr ) dev_obj_ptr->DeviceExtension )->device = dev_ptr;
   dev_ptr->Self = dev_obj_ptr;
-  dev_ptr->DriverObject = driver__obj_ptr;
-  dev_ptr->State = NotStarted;
-  dev_ptr->OldState = NotStarted;
-  dev_ptr->irp_handler_chain = NULL;
-  /*
-   * Register the default driver IRP handling table
-   */
-  irp__reg_table_s ( &dev_ptr->irp_handler_chain, driver__handling_table,
-                    driver__handling_table_size );
-  /*
-   * Register the default disk IRP handling table
-   */
-  irp__reg_table ( &dev_ptr->irp_handler_chain, handling_table );
-  /*
-   * Establish a pointer to the disk
-   */
-  disk_ptr = get_disk_ptr ( dev_ptr );
   KeInitializeEvent ( &disk_ptr->SearchEvent, SynchronizationEvent, FALSE );
   KeInitializeSpinLock ( &disk_ptr->SpinLock );
-  disk_ptr->Unmount = FALSE;
   disk_ptr->DiskNumber = InterlockedIncrement ( &next_disk ) - 1;
   /*
    * Some device parameters
@@ -238,22 +215,6 @@ device__create_pdo_decl (
   return dev_obj_ptr;
 }
 
-/* Device operations for disks */
-device__ops disk__dev_ops = {
-  create_pdo,
-  init,
-  close
-};
-
-/* Copy default disk device operations into a device */
-winvblock__lib_func void
-disk__put_dev_ops (
-  device__type_ptr dev
- )
-{
-  RtlCopyMemory ( &dev->ops, &disk__dev_ops, sizeof ( device__ops ) );
-}
-
 /* An MBR C/H/S address and ways to access its components */
 typedef winvblock__uint8 chs[3];
 
@@ -446,3 +407,140 @@ disk__guess_geometry (
   if ( !disk_ptr->Cylinders )
     disk_ptr->Cylinders = disk_ptr->LBADiskSize / ( heads * sects_per_track );
 }
+
+/**
+ * Create a new disk
+ *
+ * @ret disk_ptr        The address of a new disk, or NULL for failure
+ *
+ * See the header file for additional details
+ */
+winvblock__lib_func disk__type_ptr
+disk__create (
+  void
+ )
+{
+  device__type_ptr dev_ptr;
+  disk__type_ptr disk_ptr;
+
+  /*
+   * Try to create a device
+   */
+  dev_ptr = device__create (  );
+  if ( dev_ptr == NULL )
+    goto err_nodev;
+  /*
+   * Disk devices might be used for booting and should
+   * not be allocated from a paged memory pool
+   */
+  disk_ptr = ExAllocatePool ( NonPagedPool, sizeof ( disk__type ) );
+  if ( disk_ptr == NULL )
+    goto err_nodisk;
+  RtlZeroMemory ( disk_ptr, sizeof ( disk__type ) );
+  /*
+   * Track the new disk in our global list
+   */
+  ExInterlockedInsertTailList ( &disk_list, &disk_ptr->tracking,
+                               &disk_list_lock );
+  /*
+   * Populate non-zero device defaults
+   */
+  disk_ptr->device = dev_ptr;
+  disk_ptr->prev_free = dev_ptr->ops.free;
+  disk_ptr->disk_ops.max_xfer_len = default_max_xfer_len;
+  disk_ptr->disk_ops.init = default_init;
+  disk_ptr->disk_ops.close = default_close;
+  dev_ptr->ops.close = close;
+  dev_ptr->ops.create_pdo = create_pdo;
+  dev_ptr->ops.free = free_disk;
+  dev_ptr->ops.init = init;
+  dev_ptr->ext = disk_ptr;
+  KeInitializeSpinLock ( &disk_ptr->SpinLock );
+  /*
+   * Register the default disk IRP handling table
+   */
+  irp__reg_table ( &dev_ptr->irp_handler_chain, handling_table );
+
+  return disk_ptr;
+
+err_nodisk:
+
+  device__free ( dev_ptr );
+err_nodev:
+
+  return NULL;
+}
+
+/**
+ * Initialize the global, disk-common environment
+ *
+ * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure
+ */
+NTSTATUS
+disk__init (
+  void
+ )
+{
+  /*
+   * Initialize the global list of disks
+   */
+  InitializeListHead ( &disk_list );
+  KeInitializeSpinLock ( &disk_list_lock );
+
+  return STATUS_SUCCESS;
+}
+
+/**
+ * Default disk deletion operation
+ *
+ * @v dev_ptr           Points to the disk device to delete
+ */
+static
+device__free_decl (
+  free_disk
+ )
+{
+  disk__type_ptr disk_ptr = disk__get_ptr ( dev_ptr );
+  /*
+   * Un-register the default disk IRP handling table
+   */
+  irp__unreg_table ( &dev_ptr->irp_handler_chain, handling_table );
+  /*
+   * Free the "inherited class"
+   */
+  disk_ptr->prev_free ( dev_ptr );
+  /*
+   * Track the disk deletion in our global list.  Unfortunately,
+   * for now we have faith that a disk won't be deleted twice and
+   * result in a race condition.  Something to keep in mind...
+   */
+  ExInterlockedRemoveHeadList ( disk_ptr->tracking.Blink, &disk_list_lock );
+
+  ExFreePool ( disk_ptr );
+}
+
+/* See header for details */
+disk__io_decl ( disk__io )
+{
+  disk__type_ptr disk_ptr;
+
+  /*
+   * Establish a pointer to the disk
+   */
+  disk_ptr = disk__get_ptr ( dev_ptr );
+
+  return disk_ptr->disk_ops.io ( dev_ptr, mode, start_sector, sector_count,
+                                buffer, irp );
+}
+
+/* See header for details */
+disk__max_xfer_len_decl ( disk__max_xfer_len )
+{
+  return disk_ptr->disk_ops.max_xfer_len ( disk_ptr );
+}
+
+/* See header for details */
+disk__pnp_id_decl ( disk__query_id )
+{
+  return disk_ptr->disk_ops.pnp_id ( disk_ptr, query_type, buf_512 );
+}
index 2105f8b..c97c3d2 100644 (file)
@@ -46,7 +46,7 @@ irp__handler_decl ( disk_pnp__query_id )
   winvblock__uint32 string_length;
   disk__type_ptr disk_ptr;
 
-  disk_ptr = get_disk_ptr ( DeviceExtension );
+  disk_ptr = disk__get_ptr ( dev_ptr );
   string =
     ( PWCHAR ) ExAllocatePool ( NonPagedPool, ( 512 * sizeof ( WCHAR ) ) );
   if ( string == NULL )
@@ -105,7 +105,7 @@ irp__handler_decl ( disk_pnp__query_dev_text )
 
   string =
     ( PWCHAR ) ExAllocatePool ( NonPagedPool, ( 512 * sizeof ( WCHAR ) ) );
-  disk_ptr = get_disk_ptr ( DeviceExtension );
+  disk_ptr = disk__get_ptr ( dev_ptr );
 
   if ( string == NULL )
     {
@@ -188,9 +188,9 @@ irp__handler_decl ( disk_pnp__query_dev_relations )
       status = STATUS_INSUFFICIENT_RESOURCES;
       goto alloc_dev_relations;
     }
-  dev_relations->Objects[0] = DeviceExtension->Self;
+  dev_relations->Objects[0] = dev_ptr->Self;
   dev_relations->Count = 1;
-  ObReferenceObject ( DeviceExtension->Self );
+  ObReferenceObject ( dev_ptr->Self );
   Irp->IoStatus.Information = ( ULONG_PTR ) dev_relations;
   status = STATUS_SUCCESS;
 
@@ -246,6 +246,7 @@ irp__handler_decl ( disk_pnp__query_capabilities )
     Stack->Parameters.DeviceCapabilities.Capabilities;
   NTSTATUS status;
   disk__type_ptr disk_ptr;
+  driver__dev_ext_ptr bus_dev_ext_ptr;
   bus__type_ptr bus_ptr;
   DEVICE_CAPABILITIES ParentDeviceCapabilities;
 
@@ -255,8 +256,9 @@ irp__handler_decl ( disk_pnp__query_capabilities )
       status = STATUS_UNSUCCESSFUL;
       goto ret_path;
     }
-  disk_ptr = get_disk_ptr ( DeviceExtension );
-  bus_ptr = bus__get_ptr ( DeviceExtension->Parent->DeviceExtension );
+  disk_ptr = disk__get_ptr ( dev_ptr );
+  bus_dev_ext_ptr = ( driver__dev_ext_ptr ) dev_ptr->Parent->DeviceExtension;
+  bus_ptr = bus__get_ptr ( bus_dev_ext_ptr->device );
   status =
     Bus_GetDeviceCapabilities ( bus_ptr->LowerDeviceObject,
                                &ParentDeviceCapabilities );
@@ -310,7 +312,7 @@ irp__handler_decl ( disk_pnp__simple )
   NTSTATUS status;
   disk__type_ptr disk_ptr;
 
-  disk_ptr = get_disk_ptr ( DeviceExtension );
+  disk_ptr = disk__get_ptr ( dev_ptr );
   switch ( Stack->MinorFunction )
     {
       case IRP_MN_DEVICE_USAGE_NOTIFICATION:
@@ -330,36 +332,37 @@ irp__handler_decl ( disk_pnp__simple )
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_START_DEVICE:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = Started;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = Started;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_QUERY_STOP_DEVICE:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = StopPending;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = StopPending;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_CANCEL_STOP_DEVICE:
-       DeviceExtension->State = DeviceExtension->OldState;
+       dev_ptr->State = dev_ptr->OldState;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_STOP_DEVICE:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = Stopped;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = Stopped;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_QUERY_REMOVE_DEVICE:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = RemovePending;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = RemovePending;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_REMOVE_DEVICE:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = NotStarted;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = NotStarted;
        if ( disk_ptr->Unmount )
          {
-           DeviceExtension->ops.close ( DeviceExtension );
-           IoDeleteDevice ( DeviceExtension->Self );
+           device__close ( dev_ptr );
+           IoDeleteDevice ( dev_ptr->Self );
+           device__free ( dev_ptr );
            status = STATUS_NO_SUCH_DEVICE;
          }
        else
@@ -368,12 +371,12 @@ irp__handler_decl ( disk_pnp__simple )
          }
        break;
       case IRP_MN_CANCEL_REMOVE_DEVICE:
-       DeviceExtension->State = DeviceExtension->OldState;
+       dev_ptr->State = dev_ptr->OldState;
        status = STATUS_SUCCESS;
        break;
       case IRP_MN_SURPRISE_REMOVAL:
-       DeviceExtension->OldState = DeviceExtension->State;
-       DeviceExtension->State = SurpriseRemovePending;
+       dev_ptr->OldState = dev_ptr->State;
+       dev_ptr->State = SurpriseRemovePending;
        status = STATUS_SUCCESS;
        break;
       default:
index de8f4c7..d5d83b0 100644 (file)
@@ -116,14 +116,14 @@ typedef struct _DISK_CDB16
 
 #define scsi_op( x ) \
 \
-NTSTATUS STDCALL \
-x ( \
-  IN struct _device__type *DeviceExtension, \
-  IN PIRP Irp, \
-  IN disk__type_ptr disk_ptr, \
-  IN PSCSI_REQUEST_BLOCK Srb, \
-  IN PCDB Cdb, \
-  OUT winvblock__bool_ptr completion_ptr \
+NTSTATUS STDCALL                                \
+x (                                             \
+  IN struct _device__type *dev_ptr,             \
+  IN PIRP Irp,                                  \
+  IN disk__type_ptr disk_ptr,                   \
+  IN PSCSI_REQUEST_BLOCK Srb,                   \
+  IN PCDB Cdb,                                  \
+  OUT winvblock__bool_ptr completion_ptr        \
  )
 
 static
@@ -197,7 +197,7 @@ scsi_op (
   if ( Cdb->AsByte[0] == SCSIOP_READ || Cdb->AsByte[0] == SCSIOP_READ16 )
     {
       *completion_ptr = TRUE;
-      return disk__io ( DeviceExtension, disk__io_mode_read, start_sector,
+      return disk__io ( dev_ptr, disk__io_mode_read, start_sector,
                        sector_count,
                        ( ( winvblock__uint8_ptr ) Srb->DataBuffer -
                          ( winvblock__uint8_ptr )
@@ -210,7 +210,7 @@ scsi_op (
   else
     {
       *completion_ptr = TRUE;
-      return disk__io ( DeviceExtension, disk__io_mode_write, start_sector,
+      return disk__io ( dev_ptr, disk__io_mode_write, start_sector,
                        sector_count,
                        ( ( winvblock__uint8_ptr ) Srb->DataBuffer -
                          ( winvblock__uint8_ptr )
@@ -360,7 +360,7 @@ irp__handler_decl ( disk_scsi__dispatch )
   /*
    * Establish a pointer to the disk
    */
-  disk_ptr = get_disk_ptr ( DeviceExtension );
+  disk_ptr = disk__get_ptr ( dev_ptr );
 
   Srb = Stack->Parameters.Scsi.Srb;
   Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
@@ -387,29 +387,26 @@ irp__handler_decl ( disk_scsi__dispatch )
            case SCSIOP_WRITE:
            case SCSIOP_WRITE16:
              status =
-               read_write ( DeviceExtension, Irp, disk_ptr, Srb, Cdb,
-                            &completion );
+               read_write ( dev_ptr, Irp, disk_ptr, Srb, Cdb, &completion );
              break;
            case SCSIOP_VERIFY:
            case SCSIOP_VERIFY16:
              status =
-               verify ( DeviceExtension, Irp, disk_ptr, Srb, Cdb,
-                        &completion );
+               verify ( dev_ptr, Irp, disk_ptr, Srb, Cdb, &completion );
              break;
            case SCSIOP_READ_CAPACITY:
              status =
-               read_capacity ( DeviceExtension, Irp, disk_ptr, Srb, Cdb,
+               read_capacity ( dev_ptr, Irp, disk_ptr, Srb, Cdb,
                                &completion );
              break;
            case SCSIOP_READ_CAPACITY16:
              status =
-               read_capacity_16 ( DeviceExtension, Irp, disk_ptr, Srb, Cdb,
+               read_capacity_16 ( dev_ptr, Irp, disk_ptr, Srb, Cdb,
                                   &completion );
              break;
            case SCSIOP_MODE_SENSE:
              status =
-               mode_sense ( DeviceExtension, Irp, disk_ptr, Srb, Cdb,
-                            &completion );
+               mode_sense ( dev_ptr, Irp, disk_ptr, Srb, Cdb, &completion );
              break;
            case SCSIOP_MEDIUM_REMOVAL:
              Irp->IoStatus.Information = 0;
@@ -418,8 +415,7 @@ irp__handler_decl ( disk_scsi__dispatch )
              break;
            case SCSIOP_READ_TOC:
              status =
-               read_toc ( DeviceExtension, Irp, disk_ptr, Srb, Cdb,
-                          &completion );
+               read_toc ( dev_ptr, Irp, disk_ptr, Srb, Cdb, &completion );
              break;
            default:
              DBG ( "Invalid SCSIOP (%02x)!!\n", Cdb->AsByte[0] );
index b888e55..4d02a8c 100644 (file)
@@ -38,6 +38,8 @@
 #include "registry.h"
 #include "mount.h"
 #include "bus.h"
+#include "filedisk.h"
+#include "ramdisk.h"
 #include "debug.h"
 
 /* in this file */
@@ -193,6 +195,9 @@ DriverEntry (
    */
   device__init (  );           /* TODO: Check for error */
   bus__init (  );              /* TODO: Check for error */
+  disk__init (  );             /* TODO: Check for error */
+  filedisk__init (  );         /* TODO: Check for error */
+  ramdisk__init (  );          /* TODO: Check for error */
 
   Driver_Globals_Started = TRUE;
   DBG ( "Exit\n" );
@@ -259,7 +264,7 @@ Driver_Dispatch (
 {
   NTSTATUS status;
   PIO_STACK_LOCATION Stack;
-  device__type_ptr DeviceExtension;
+  device__type_ptr dev_ptr;
   size_t irp_handler_index;
   winvblock__bool completion = FALSE;
 
@@ -267,12 +272,12 @@ Driver_Dispatch (
   Debug_IrpStart ( DeviceObject, Irp );
 #endif
   Stack = IoGetCurrentIrpStackLocation ( Irp );
-  DeviceExtension = ( device__type_ptr ) DeviceObject->DeviceExtension;
+  dev_ptr = ( ( driver__dev_ext_ptr ) DeviceObject->DeviceExtension )->device;
 
   /*
    * We handle IRP_MJ_POWER as an exception 
    */
-  if ( DeviceExtension->State == Deleted )
+  if ( dev_ptr->State == Deleted )
     {
       if ( Stack->MajorFunction == IRP_MJ_POWER )
        PoStartNextPowerIrp ( Irp );
@@ -285,8 +290,7 @@ Driver_Dispatch (
       return STATUS_NO_SUCH_DEVICE;
     }
 
-  status =
-    irp__process ( DeviceObject, Irp, Stack, DeviceExtension, &completion );
+  status = irp__process ( DeviceObject, Irp, Stack, dev_ptr, &completion );
 
 #ifdef DEBUGIRPS
   if ( status != STATUS_PENDING )
index 9d4454a..af6f28d 100644 (file)
 #include "filedisk.h"
 #include "debug.h"
 
+winvblock__def_struct ( filedisk_type )
+{
+  disk__type_ptr disk;
+  HANDLE file;
+  winvblock__uint32 hash;
+  device__free_routine prev_free;
+  LIST_ENTRY tracking;
+};
+
+/*
+ * Yield a pointer to the file-backed disk
+ */
+#define filedisk_get_ptr( dev_ptr ) \
+  ( ( filedisk_type_ptr ) ( disk__get_ptr ( dev_ptr ) )->ext )
+
+static LIST_ENTRY filedisk_list;
+static KSPIN_LOCK filedisk_list_lock;
+/* Forward declarations */
+static filedisk_type_ptr create_filedisk (
+  void
+ );
+static device__free_decl (
+  free_filedisk
+ );
+
 static
 disk__io_decl (
   io
  )
 {
   disk__type_ptr disk_ptr;
-  filedisk__type_ptr filedisk_ptr;
+  filedisk_type_ptr filedisk_ptr;
   LARGE_INTEGER offset;
   NTSTATUS status;
   IO_STATUS_BLOCK io_status;
@@ -52,8 +77,8 @@ disk__io_decl (
   /*
    * Establish pointers to the disk and filedisk
    */
-  disk_ptr = get_disk_ptr ( dev_ptr );
-  filedisk_ptr = filedisk__get_ptr ( dev_ptr );
+  disk_ptr = disk__get_ptr ( dev_ptr );
+  filedisk_ptr = filedisk_get_ptr ( dev_ptr );
 
   if ( sector_count < 1 )
     {
@@ -89,7 +114,7 @@ disk__pnp_id_decl (
   query_id
  )
 {
-  filedisk__type_ptr filedisk_ptr = filedisk__get_ptr ( &disk_ptr->device );
+  filedisk_type_ptr filedisk_ptr = filedisk_get_ptr ( disk_ptr->device );
   static PWCHAR hw_ids[disk__media_count] =
     { winvblock__literal_w L"\\FileFloppyDisk",
     winvblock__literal_w L"\\FileHardDisk",
@@ -117,8 +142,6 @@ disk__pnp_id_decl (
     }
 }
 
-static disk__ops default_ops;
-
 irp__handler_decl ( filedisk__attach )
 {
   ANSI_STRING file_path1;
@@ -130,7 +153,14 @@ irp__handler_decl ( filedisk__attach )
   HANDLE file = NULL;
   IO_STATUS_BLOCK io_status;
   FILE_STANDARD_INFORMATION info;
-  filedisk__type filedisk = { 0 };
+  filedisk_type_ptr filedisk_ptr;
+
+  filedisk_ptr = create_filedisk (  );
+  if ( filedisk_ptr == NULL )
+    {
+      DBG ( "Could not create file-backed disk!\n" );
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
 
   RtlInitAnsiString ( &file_path1,
                      ( char * )&buf[sizeof ( mount__filedisk )] );
@@ -155,24 +185,24 @@ irp__handler_decl ( filedisk__attach )
   if ( !NT_SUCCESS ( status ) )
     return status;
 
-  filedisk.file = file;
+  filedisk_ptr->file = file;
 
   switch ( params->type )
     {
       case 'f':
-       filedisk.disk.media = disk__media_floppy;
-       filedisk.disk.SectorSize = 512;
+       filedisk_ptr->disk->media = disk__media_floppy;
+       filedisk_ptr->disk->SectorSize = 512;
        break;
       case 'c':
-       filedisk.disk.media = disk__media_optical;
-       filedisk.disk.SectorSize = 2048;
+       filedisk_ptr->disk->media = disk__media_optical;
+       filedisk_ptr->disk->SectorSize = 2048;
        break;
       default:
-       filedisk.disk.media = disk__media_hard;
-       filedisk.disk.SectorSize = 512;
+       filedisk_ptr->disk->media = disk__media_hard;
+       filedisk_ptr->disk->SectorSize = 512;
        break;
     }
-  DBG ( "File-backed disk is type: %d\n", filedisk.disk.media );
+  DBG ( "File-backed disk is type: %d\n", filedisk_ptr->disk->media );
   /*
    * Determine the disk's size
    */
@@ -182,28 +212,29 @@ irp__handler_decl ( filedisk__attach )
   if ( !NT_SUCCESS ( status ) )
     {
       ZwClose ( file );
+      free_filedisk ( filedisk_ptr->disk->device );
       return status;
     }
-  filedisk.disk.LBADiskSize =
-    info.EndOfFile.QuadPart / filedisk.disk.SectorSize;
-  filedisk.disk.Cylinders = params->cylinders;
-  filedisk.disk.Heads = params->heads;
-  filedisk.disk.Sectors = params->sectors;
+  filedisk_ptr->disk->LBADiskSize =
+    info.EndOfFile.QuadPart / filedisk_ptr->disk->SectorSize;
+  filedisk_ptr->disk->Cylinders = params->cylinders;
+  filedisk_ptr->disk->Heads = params->heads;
+  filedisk_ptr->disk->Sectors = params->sectors;
   /*
    * A really stupid "hash".  RtlHashUnicodeString() would have been
    * good, but is only available >= Windows XP
    */
-  filedisk.hash = ( winvblock__uint32 ) filedisk.disk.LBADiskSize;
+  filedisk_ptr->hash = ( winvblock__uint32 ) filedisk_ptr->disk->LBADiskSize;
   {
     char *path_iterator = file_path1.Buffer;
 
     while ( *path_iterator )
-      filedisk.hash += *path_iterator++;
+      filedisk_ptr->hash += *path_iterator++;
   }
-  filedisk.disk.ops = &default_ops;
-  disk__put_dev_ops ( &filedisk.disk.device );
-  filedisk.disk.device.size = sizeof ( filedisk__type );
-  bus__add_child ( bus__boot (  ), &filedisk.disk.device );
+  /*
+   * FIXME: Check for error below!
+   */
+  bus__add_child ( bus__boot (  ), filedisk_ptr->disk->device );
   return STATUS_SUCCESS;
 }
 
@@ -212,15 +243,111 @@ disk__close_decl (
   close
  )
 {
-  filedisk__type_ptr filedisk_ptr = filedisk__get_ptr ( &disk_ptr->device );
+  filedisk_type_ptr filedisk_ptr = filedisk_get_ptr ( disk_ptr->device );
   ZwClose ( filedisk_ptr->file );
   return;
 }
 
-static disk__ops default_ops = {
-  io,
-  disk__default_max_xfer_len,
-  disk__default_init,
-  query_id,
-  close
-};
+/**
+ * Create a new file-backed disk
+ *
+ * @ret filedisk_ptr    The address of a new filedisk, or NULL for failure
+ *
+ * This function should not be confused with a PDO creation routine, which is
+ * actually implemented for each device type.  This routine will allocate a
+ * filedisk_type, track it in a global list, as well as populate the disk
+ * with default values.
+ */
+static filedisk_type_ptr
+create_filedisk (
+  void
+ )
+{
+  disk__type_ptr disk_ptr;
+  filedisk_type_ptr filedisk_ptr;
+
+  /*
+   * Try to create a disk
+   */
+  disk_ptr = disk__create (  );
+  if ( disk_ptr == NULL )
+    goto err_nodisk;
+  /*
+   * File-backed disk devices might be used for booting and should
+   * not be allocated from a paged memory pool
+   */
+  filedisk_ptr = ExAllocatePool ( NonPagedPool, sizeof ( filedisk_type ) );
+  if ( filedisk_ptr == NULL )
+    goto err_nofiledisk;
+  RtlZeroMemory ( filedisk_ptr, sizeof ( filedisk_type ) );
+  /*
+   * Track the new file-backed disk in our global list
+   */
+  ExInterlockedInsertTailList ( &filedisk_list, &filedisk_ptr->tracking,
+                               &filedisk_list_lock );
+  /*
+   * Populate non-zero device defaults
+   */
+  filedisk_ptr->disk = disk_ptr;
+  filedisk_ptr->prev_free = disk_ptr->device->ops.free;
+  disk_ptr->device->ops.free = free_filedisk;
+  disk_ptr->disk_ops.io = io;
+  disk_ptr->disk_ops.pnp_id = query_id;
+  disk_ptr->disk_ops.close = close;
+  disk_ptr->ext = filedisk_ptr;
+
+  return filedisk_ptr;
+
+err_nofiledisk:
+
+  device__free ( disk_ptr->device );
+err_nodisk:
+
+  return NULL;
+}
+
+/**
+ * Initialize the global, file-backed disk-common environment
+ *
+ * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure
+ */
+NTSTATUS
+filedisk__init (
+  void
+ )
+{
+  /*
+   * Initialize the global list of file-backed disks
+   */
+  InitializeListHead ( &filedisk_list );
+  KeInitializeSpinLock ( &filedisk_list_lock );
+
+  return STATUS_SUCCESS;
+}
+
+/**
+ * Default file-backed disk deletion operation
+ *
+ * @v dev_ptr           Points to the file-backed disk device to delete
+ */
+static
+device__free_decl (
+  free_filedisk
+ )
+{
+  disk__type_ptr disk_ptr = disk__get_ptr ( dev_ptr );
+  filedisk_type_ptr filedisk_ptr = filedisk_get_ptr ( dev_ptr );
+  /*
+   * Free the "inherited class"
+   */
+  filedisk_ptr->prev_free ( dev_ptr );
+  /*
+   * Track the file-backed disk deletion in our global list.  Unfortunately,
+   * for now we have faith that a file-backed disk won't be deleted twice and
+   * result in a race condition.  Something to keep in mind...
+   */
+  ExInterlockedRemoveHeadList ( filedisk_ptr->tracking.Blink,
+                               &filedisk_list_lock );
+
+  ExFreePool ( filedisk_ptr );
+}
index 2bdc222..213f05a 100644 (file)
@@ -159,15 +159,7 @@ irp__handler_decl ( irp__process )
   NTSTATUS status = STATUS_NOT_SUPPORTED;
   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;
+  link = ( handler_chain_ptr ) dev_ptr->irp_handler_chain;
 
   while ( link != NULL )
     {
@@ -196,7 +188,7 @@ irp__handler_decl ( irp__process )
            || handling.any_minor;
          if ( handles_major && handles_minor )
            status =
-             handling.handler ( DeviceObject, Irp, Stack, DeviceExtension,
+             handling.handler ( DeviceObject, Irp, Stack, dev_ptr,
                                 completion_ptr );
          /*
           * Do not process the IRP any further down the stack
index 28cba39..fa479bd 100644 (file)
@@ -71,7 +71,7 @@ grub4dos__find (
   grub4dos_drive_mapping_ptr Grub4DosDriveMapSlotPtr;
   winvblock__uint32 i = 8;
   winvblock__bool FoundGrub4DosMapping = FALSE;
-  ramdisk__type ramdisk = { 0 };
+  ramdisk__type_ptr ramdisk_ptr;
 
   /*
    * Find a GRUB4DOS memory-mapped disk.  Start by looking at the
@@ -128,38 +128,42 @@ grub4dos__find (
              DBG ( "Skipping non-RAM disk GRUB4DOS mapping\n" );
              continue;
            }
+         ramdisk_ptr = ramdisk__create (  );
+         if ( ramdisk_ptr == NULL )
+           {
+             DBG ( "Could not create GRUB4DOS disk!\n" );
+             return;
+           }
          /*
           * Possible precision loss
           */
          if ( Grub4DosDriveMapSlotPtr[i].SourceODD )
            {
-             ramdisk.disk.media = disk__media_optical;
-             ramdisk.disk.SectorSize = 2048;
+             ramdisk_ptr->disk->media = disk__media_optical;
+             ramdisk_ptr->disk->SectorSize = 2048;
            }
          else
            {
-             ramdisk.disk.media =
+             ramdisk_ptr->disk->media =
                Grub4DosDriveMapSlotPtr[i].SourceDrive & 0x80 ?
                disk__media_hard : disk__media_floppy;
-             ramdisk.disk.SectorSize = 512;
+             ramdisk_ptr->disk->SectorSize = 512;
            }
-         DBG ( "RAM Drive is type: %d\n", ramdisk.disk.media );
-         ramdisk.DiskBuf =
+         DBG ( "RAM Drive is type: %d\n", ramdisk_ptr->disk->media );
+         ramdisk_ptr->DiskBuf =
            ( winvblock__uint32 ) ( Grub4DosDriveMapSlotPtr[i].SectorStart *
                                    512 );
-         ramdisk.disk.LBADiskSize = ramdisk.DiskSize =
+         ramdisk_ptr->disk->LBADiskSize = ramdisk_ptr->DiskSize =
            ( winvblock__uint32 ) Grub4DosDriveMapSlotPtr[i].SectorCount;
-         ramdisk.disk.Heads = Grub4DosDriveMapSlotPtr[i].MaxHead + 1;
-         ramdisk.disk.Sectors = Grub4DosDriveMapSlotPtr[i].DestMaxSector;
-         ramdisk.disk.Cylinders =
-           ramdisk.disk.LBADiskSize / ( ramdisk.disk.Heads *
-                                        ramdisk.disk.Sectors );
-         ramdisk.disk.BootDrive = TRUE;
-         ramdisk.disk.ops = &ramdisk__default_ops;
-         disk__put_dev_ops ( &ramdisk.disk.device );
-         ramdisk.disk.device.size = sizeof ( ramdisk__type );
+         ramdisk_ptr->disk->Heads = Grub4DosDriveMapSlotPtr[i].MaxHead + 1;
+         ramdisk_ptr->disk->Sectors =
+           Grub4DosDriveMapSlotPtr[i].DestMaxSector;
+         ramdisk_ptr->disk->Cylinders =
+           ramdisk_ptr->disk->LBADiskSize / ( ramdisk_ptr->disk->Heads *
+                                              ramdisk_ptr->disk->Sectors );
+         ramdisk_ptr->disk->BootDrive = TRUE;
          FoundGrub4DosMapping = TRUE;
-         bus__add_child ( bus__boot (  ), &ramdisk.disk.device );
+         bus__add_child ( bus__boot (  ), ramdisk_ptr->disk->device );
        }
       InterruptVector = &SafeMbrHookPtr->PrevHook;
     }
index 7c5148c..9e4192d 100644 (file)
@@ -49,7 +49,7 @@ check_mbft (
   winvblock__uint32 i;
   winvblock__uint8 Checksum = 0;
   safe_mbr_hook_ptr AssociatedHook;
-  ramdisk__type ramdisk = { 0 };
+  ramdisk__type_ptr ramdisk_ptr;
 
   if ( Offset >= 0x100000 )
     {
@@ -84,30 +84,33 @@ check_mbft (
     }
   DBG ( "MEMDISK DiskBuf: 0x%08x\n", mBFT->mdi.diskbuf );
   DBG ( "MEMDISK DiskSize: %d sectors\n", mBFT->mdi.disksize );
-  ramdisk.DiskBuf = mBFT->mdi.diskbuf;
-  ramdisk.disk.LBADiskSize = ramdisk.DiskSize = mBFT->mdi.disksize;
+  ramdisk_ptr = ramdisk__create (  );
+  if ( ramdisk_ptr == NULL )
+    {
+      DBG ( "Could not create MEMDISK disk!\n" );
+      return FALSE;
+    }
+  ramdisk_ptr->DiskBuf = mBFT->mdi.diskbuf;
+  ramdisk_ptr->disk->LBADiskSize = ramdisk_ptr->DiskSize = mBFT->mdi.disksize;
   if ( mBFT->mdi.driveno == 0xE0 )
     {
-      ramdisk.disk.media = disk__media_optical;
-      ramdisk.disk.SectorSize = 2048;
+      ramdisk_ptr->disk->media = disk__media_optical;
+      ramdisk_ptr->disk->SectorSize = 2048;
     }
   else
     {
       if ( mBFT->mdi.driveno & 0x80 )
-       ramdisk.disk.media = disk__media_hard;
+       ramdisk_ptr->disk->media = disk__media_hard;
       else
-       ramdisk.disk.media = disk__media_floppy;
-      ramdisk.disk.SectorSize = 512;
+       ramdisk_ptr->disk->media = disk__media_floppy;
+      ramdisk_ptr->disk->SectorSize = 512;
     }
-  DBG ( "RAM Drive is type: %d\n", ramdisk.disk.media );
-  ramdisk.disk.Cylinders = mBFT->mdi.cylinders;
-  ramdisk.disk.Heads = mBFT->mdi.heads;
-  ramdisk.disk.Sectors = mBFT->mdi.sectors;
-  ramdisk.disk.BootDrive = TRUE;
-  ramdisk.disk.ops = &ramdisk__default_ops;
-  disk__put_dev_ops ( &ramdisk.disk.device );
-  ramdisk.disk.device.size = sizeof ( ramdisk__type );
-  bus__add_child ( bus__boot (  ), &ramdisk.disk.device );
+  DBG ( "RAM Drive is type: %d\n", ramdisk_ptr->disk->media );
+  ramdisk_ptr->disk->Cylinders = mBFT->mdi.cylinders;
+  ramdisk_ptr->disk->Heads = mBFT->mdi.heads;
+  ramdisk_ptr->disk->Sectors = mBFT->mdi.sectors;
+  ramdisk_ptr->disk->BootDrive = TRUE;
+  bus__add_child ( bus__boot (  ), ramdisk_ptr->disk->device );
   AssociatedHook->Flags = 1;
   return TRUE;
 }
index 034d94c..bf06e38 100644 (file)
 #include "ramdisk.h"
 #include "debug.h"
 
+/*
+ * Yield a pointer to the RAM disk
+ */
+#define ramdisk_get_ptr( dev_ptr ) \
+  ( ( ramdisk__type_ptr ) ( disk__get_ptr ( dev_ptr ) )->ext )
+
+static LIST_ENTRY ramdisk_list;
+static KSPIN_LOCK ramdisk_list_lock;
+/* Forward declaration */
+static device__free_decl (
+  free_ramdisk
+ );
+
 /* With thanks to karyonix, who makes FiraDisk */
 static __inline void STDCALL
 fast_copy (
@@ -60,8 +73,8 @@ disk__io_decl (
   /*
    * Establish pointers to the disk and RAM disk
    */
-  disk_ptr = get_disk_ptr ( dev_ptr );
-  ramdisk_ptr = ramdisk__get_ptr ( dev_ptr );
+  disk_ptr = disk__get_ptr ( dev_ptr );
+  ramdisk_ptr = ramdisk_get_ptr ( dev_ptr );
 
   if ( sector_count < 1 )
     {
@@ -107,7 +120,7 @@ disk__pnp_id_decl (
   query_id
  )
 {
-  ramdisk__type_ptr ramdisk_ptr = ramdisk__get_ptr ( &disk_ptr->device );
+  ramdisk__type_ptr ramdisk_ptr = ramdisk_get_ptr ( disk_ptr->device );
   static PWCHAR hw_ids[disk__media_count] =
     { winvblock__literal_w L"\\RAMFloppyDisk",
     winvblock__literal_w L"\\RAMHardDisk",
@@ -138,10 +151,102 @@ disk__pnp_id_decl (
     }
 }
 
-disk__ops ramdisk__default_ops = {
-  io,
-  disk__default_max_xfer_len,
-  disk__default_init,
-  query_id,
-  disk__default_close
-};
+/**
+ * Create a new RAM disk
+ *
+ * @ret ramdisk_ptr     The address of a new RAM disk, or NULL for failure
+ *
+ * See the header file for additional details
+ */
+ramdisk__type_ptr
+ramdisk__create (
+  void
+ )
+{
+  disk__type_ptr disk_ptr;
+  ramdisk__type_ptr ramdisk_ptr;
+
+  /*
+   * Try to create a disk
+   */
+  disk_ptr = disk__create (  );
+  if ( disk_ptr == NULL )
+    goto err_nodisk;
+  /*
+   * RAM disk devices might be used for booting and should
+   * not be allocated from a paged memory pool
+   */
+  ramdisk_ptr = ExAllocatePool ( NonPagedPool, sizeof ( ramdisk__type ) );
+  if ( ramdisk_ptr == NULL )
+    goto err_noramdisk;
+  RtlZeroMemory ( ramdisk_ptr, sizeof ( ramdisk__type ) );
+  /*
+   * Track the new RAM disk in our global list
+   */
+  ExInterlockedInsertTailList ( &ramdisk_list, &ramdisk_ptr->tracking,
+                               &ramdisk_list_lock );
+  /*
+   * Populate non-zero device defaults
+   */
+  ramdisk_ptr->disk = disk_ptr;
+  ramdisk_ptr->prev_free = disk_ptr->device->ops.free;
+  disk_ptr->device->ops.free = free_ramdisk;
+  disk_ptr->disk_ops.io = io;
+  disk_ptr->disk_ops.pnp_id = query_id;
+  disk_ptr->ext = ramdisk_ptr;
+
+  return ramdisk_ptr;
+
+err_noramdisk:
+
+  device__free ( disk_ptr->device );
+err_nodisk:
+
+  return NULL;
+}
+
+/**
+ * Initialize the global, RAM disk-common environment
+ *
+ * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure
+ */
+NTSTATUS
+ramdisk__init (
+  void
+ )
+{
+  /*
+   * Initialize the global list of RAM disks
+   */
+  InitializeListHead ( &ramdisk_list );
+  KeInitializeSpinLock ( &ramdisk_list_lock );
+
+  return STATUS_SUCCESS;
+}
+
+/**
+ * Default RAM disk deletion operation
+ *
+ * @v dev_ptr           Points to the RAM disk device to delete
+ */
+static
+device__free_decl (
+  free_ramdisk
+ )
+{
+  disk__type_ptr disk_ptr = disk__get_ptr ( dev_ptr );
+  ramdisk__type_ptr ramdisk_ptr = ramdisk_get_ptr ( dev_ptr );
+  /*
+   * Free the "inherited class"
+   */
+  ramdisk_ptr->prev_free ( dev_ptr );
+  /*
+   * Track the RAM disk deletion in our global list.  Unfortunately,
+   * for now we have faith that a RAM disk won't be deleted twice and
+   * result in a race condition.  Something to keep in mind...
+   */
+  ExInterlockedRemoveHeadList ( ramdisk_ptr->tracking.Blink,
+                               &ramdisk_list_lock );
+
+  ExFreePool ( ramdisk_ptr );
+}