[disk,filedisk] Export IRP handlers, create filedisk PDO
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Sat, 8 Jan 2011 23:44:51 +0000 (18:44 -0500)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Sat, 8 Jan 2011 23:44:51 +0000 (18:44 -0500)
Shuffled things around so that a new filedisk actually is
the device extension of a newly-created PDO.  The same is
intended for RAM disks, soon.

src/include/disk.h
src/include/filedisk.h
src/winvblock/disk/disk.c
src/winvblock/driver.c
src/winvblock/filedisk/filedisk.c
src/winvblock/filedisk/grub4dos.c

index 7895f3a..4c48088 100644 (file)
@@ -177,4 +177,15 @@ extern WVL_M_LIB NTSTATUS STDCALL WvlDiskCreatePdo(
 extern WVL_M_LIB VOID STDCALL WvDiskInit(IN WV_SP_DISK_T);
 extern WVL_M_LIB WV_SP_DISK_T disk__create(void);
 
+/* IRP-related. */
+extern WV_F_DEV_DISPATCH WvDiskIrpPower;
+extern WV_F_DEV_DISPATCH WvDiskIrpSysCtl;
+/* IRP_MJ_DEVICE_CONTROL dispatcher from disk/dev_ctl.c */
+extern WV_F_DEV_CTL disk_dev_ctl__dispatch;
+/* IRP_MJ_SCSI dispatcher from disk/scsi.c */
+extern WV_F_DEV_SCSI disk_scsi__dispatch;
+/* IRP_MJ_PNP dispatcher from disk/pnp.c */
+extern WV_F_DEV_PNP disk_pnp__dispatch;
+
+
 #endif  /* WV_M_DISK_H_ */
index 277ae72..28c7018 100644 (file)
@@ -26,7 +26,8 @@
  */
 
 typedef struct WV_FILEDISK_T {
-    WV_SP_DISK_T disk;
+    WV_S_DEV_EXT DevExt;
+    WV_S_DISK_T disk[1];
     HANDLE file;
     UINT32 hash;
     WV_FP_DEV_FREE prev_free;
@@ -37,34 +38,13 @@ typedef struct WV_FILEDISK_T {
     KSPIN_LOCK req_list_lock;
     KEVENT signal;
     WV_FP_DISK_IO sync_io;
-    char *filepath;
+    PCHAR filepath;
     UNICODE_STRING filepath_unicode;
   } WV_S_FILEDISK_T, * WV_SP_FILEDISK_T;
 
 extern NTSTATUS STDCALL WvFilediskAttach(IN PIRP);
-
-extern NTSTATUS WvFilediskModuleInit(void);
-
-/**
- * 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
- * WV_S_FILEDISK_T, track it in a global list, as well as populate the disk
- * with default values.
- */
-extern WV_SP_FILEDISK_T WvFilediskCreate(void);
-/**
- * Create a new threaded, file-backed disk.
- *
- * @ret filedisk_ptr    The address of a new filedisk, or NULL for failure.
- *
- * See WvFilediskCreate() above.  This routine uses threaded routines
- * for disk reads/writes, and frees asynchronously, too.
- */
-extern WV_SP_FILEDISK_T WvFilediskCreateThreaded(void);
+extern WV_SP_FILEDISK_T WvFilediskCreatePdo(IN WVL_E_DISK_MEDIA_TYPE);
+extern WV_SP_FILEDISK_T WvFilediskCreatePdoThreaded(IN WVL_E_DISK_MEDIA_TYPE);
 
 /* Yield a pointer to the file-backed disk. */
 #define filedisk__get_ptr(dev_ptr) \
index 2f7796f..9687027 100644 (file)
@@ -43,31 +43,23 @@ static long long __divdi3(long long u, long long v) {
   }
 #endif
 
-/* IRP_MJ_DEVICE_CONTROL dispatcher from disk/dev_ctl.c */
-extern WV_F_DEV_CTL disk_dev_ctl__dispatch;
-/* IRP_MJ_SCSI dispatcher from disk/scsi.c */
-extern WV_F_DEV_SCSI disk_scsi__dispatch;
-/* IRP_MJ_PNP dispatcher from disk/pnp.c */
-extern WV_F_DEV_PNP disk_pnp__dispatch;
-
-/* Forward declarations. */
-static WV_F_DEV_FREE WvDiskDevFree_;
-static WV_F_DEV_DISPATCH WvDiskIrpPower_;
-static WV_F_DEV_DISPATCH WvDiskIrpSysCtl_;
-static WV_F_DISK_INIT WvDiskDefaultInit_;
-static WV_F_DISK_CLOSE WvDiskDefaultClose_;
-
-/* Globals. */
+/** Exports. */
 BOOLEAN WvDiskIsRemovable[WvlDiskMediaTypes] = { TRUE, FALSE, TRUE };
 PWCHAR WvDiskCompatIds[WvlDiskMediaTypes] = {
     L"GenSFloppy",
     L"GenDisk",
     L"GenCdRom"
   };
+
+/** Private. */
+static WV_F_DEV_FREE WvDiskDevFree_;
+static WV_F_DISK_INIT WvDiskDefaultInit_;
+static WV_F_DISK_CLOSE WvDiskDefaultClose_;
+
 /* Device IRP major function dispatch table. */
-WV_S_DEV_IRP_MJ WvDiskIrpMj_ = {
-    WvDiskIrpPower_,
-    WvDiskIrpSysCtl_,
+static WV_S_DEV_IRP_MJ WvDiskIrpMj_ = {
+    WvDiskIrpPower,
+    WvDiskIrpSysCtl,
     disk_dev_ctl__dispatch,
     disk_scsi__dispatch,
     disk_pnp__dispatch,
@@ -104,12 +96,12 @@ static VOID STDCALL WvDiskDefaultClose_(IN WV_SP_DISK_T disk) {
     return;
   }
 
-static NTSTATUS STDCALL WvDiskIrpPower_(IN WV_SP_DEV_T dev, IN PIRP irp) {
+NTSTATUS STDCALL WvDiskIrpPower(IN WV_SP_DEV_T dev, IN PIRP irp) {
     PoStartNextPowerIrp(irp);
     return WvlIrpComplete(irp, 0, STATUS_NOT_SUPPORTED);
   }
 
-static NTSTATUS STDCALL WvDiskIrpSysCtl_(IN WV_SP_DEV_T dev, IN PIRP irp) {
+NTSTATUS STDCALL WvDiskIrpSysCtl(IN WV_SP_DEV_T dev, IN PIRP irp) {
     return WvlIrpComplete(irp, 0, irp->IoStatus.Status);
   }
 
index 75e1386..b85e2ba 100644 (file)
@@ -190,7 +190,6 @@ NTSTATUS STDCALL DriverEntry(
     /* Set the driver AddDevice callback. */
     DriverObject->DriverExtension->AddDevice = WvAttachFdo;
     /* Initialize various modules. */
-    WvFilediskModuleInit();     /* TODO: Check for error. */
     ramdisk__module_init();     /* TODO: Check for error. */
 
     /* Establish the bus PDO. */
index b2ae7dd..172976a 100644 (file)
 #include "filedisk.h"
 #include "debug.h"
 
-/* Globals. */
-static LIST_ENTRY filedisk_list;
-static KSPIN_LOCK filedisk_list_lock;
-
-/* Forward declarations. */
-static WV_F_DEV_FREE free_filedisk;
+/** Private. */
+static WV_F_DEV_FREE WvFilediskFree_;
 static WV_F_DISK_IO io;
 static WV_F_DISK_IO threaded_io;
-static WV_F_DISK_CLOSE close;
+static WV_F_DEV_CLOSE WvFilediskClose_;
 
 static NTSTATUS STDCALL io(
     IN WV_SP_DEV_T dev_ptr,
@@ -164,12 +160,6 @@ NTSTATUS STDCALL WvFilediskAttach(IN PIRP irp) {
     UINT32 sector_size, hash;
     ULONGLONG lba_size;
 
-    filedisk = WvFilediskCreate();
-    if (filedisk == NULL) {
-        DBG("Could not create file-backed disk!\n");
-        return STATUS_INSUFFICIENT_RESOURCES;
-      }
-
     RtlInitAnsiString(&ansi_path, buf + sizeof (WV_S_MOUNT_DISK));
     status = RtlAnsiStringToUnicodeString(&file_path, &ansi_path, TRUE);
     if (!NT_SUCCESS(status))
@@ -181,7 +171,7 @@ NTSTATUS STDCALL WvFilediskAttach(IN PIRP irp) {
         NULL,
         NULL
       );
-    /* Open the file.  The handle is closed by close() */
+    /* Open the file.  The handle is closed by WvFilediskClose_() */
     status = ZwCreateFile(
         &file,
         GENERIC_READ | GENERIC_WRITE,
@@ -241,10 +231,13 @@ NTSTATUS STDCALL WvFilediskAttach(IN PIRP irp) {
         while (*path_iterator)
           hash += *path_iterator++;
       }
-    /* Add the filedisk to the bus. */
-    if (!WvBusAddDev(filedisk->disk->Dev)) {
-        status = STATUS_UNSUCCESSFUL;
-        goto err_add_child;
+
+    /* Create the filedisk PDO. */
+    filedisk = WvFilediskCreatePdo(media_type);
+    if (filedisk == NULL) {
+        DBG("Could not create file-backed disk!\n");
+        status = STATUS_INSUFFICIENT_RESOURCES;
+        goto err_pdo;
       }
 
     /* Set filedisk parameters. */
@@ -257,10 +250,19 @@ NTSTATUS STDCALL WvFilediskAttach(IN PIRP irp) {
     filedisk->file = file;
     filedisk->hash = hash;
 
+    /* Add the filedisk to the bus. */
+    if (!WvBusAddDev(filedisk->disk->Dev)) {
+        status = STATUS_UNSUCCESSFUL;
+        goto err_add_child;
+      }
+
     return STATUS_SUCCESS;
 
     err_add_child:
 
+    WvFilediskFree_(filedisk->disk->Dev);
+    err_pdo:
+
     err_query_info:
 
     ZwClose(file);
@@ -268,100 +270,94 @@ NTSTATUS STDCALL WvFilediskAttach(IN PIRP irp) {
 
     err_ansi_to_unicode:
 
-    free_filedisk(filedisk->disk->Dev);
     return status;
   }
 
-static VOID STDCALL close(IN WV_SP_DISK_T disk_ptr) {
-    WV_SP_FILEDISK_T filedisk_ptr = filedisk__get_ptr(disk_ptr->Dev);
+static VOID STDCALL WvFilediskClose_(IN WV_SP_DEV_T dev) {
+    WV_SP_FILEDISK_T filedisk = CONTAINING_RECORD(
+        dev,
+        WV_S_FILEDISK_T,
+        disk[0].Dev
+      );
 
-    ZwClose(filedisk_ptr->file);
+    ZwClose(filedisk->file);
     return;
   }
 
 /**
- * Create a new file-backed disk.
+ * Create a filedisk PDO filled with the given disk parameters.
  *
- * @ret filedisk_ptr    The address of a new filedisk, or NULL for failure.
+ * @v MediaType                 The media type for the filedisk.
+ * @ret WV_SP_FILEDISK_T        Points to the new filedisk, or NULL.
  *
- * See the header file for additional details.
+ * Returns NULL if the PDO cannot be created.
  */
-WV_SP_FILEDISK_T WvFilediskCreate(void) {
-    WV_SP_DISK_T disk_ptr;
-    WV_SP_FILEDISK_T 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 = wv_mallocz(sizeof *filedisk_ptr);
-    if (filedisk_ptr == NULL)
-      goto err_nofiledisk;
-    /* Track the new file-backed disk in our global list. */
-    ExInterlockedInsertTailList(
-        &filedisk_list,
-        &filedisk_ptr->tracking,
-        &filedisk_list_lock
+WV_SP_FILEDISK_T STDCALL WvFilediskCreatePdo(
+    IN WVL_E_DISK_MEDIA_TYPE MediaType
+  ) {
+    static WV_S_DEV_IRP_MJ irp_mj = {
+        WvDiskIrpPower,
+        WvDiskIrpSysCtl,
+        disk_dev_ctl__dispatch,
+        disk_scsi__dispatch,
+        disk_pnp__dispatch,
+      };
+    NTSTATUS status;
+    WV_SP_FILEDISK_T filedisk;
+    PDEVICE_OBJECT pdo;
+  
+    DBG("Creating filedisk PDO...\n");
+
+    /* Create the disk PDO. */
+    status = WvlDiskCreatePdo(
+        WvDriverObj,
+        sizeof *filedisk,
+        MediaType,
+        &pdo
       );
-    /* Populate non-zero device defaults. */
-    filedisk_ptr->disk = disk_ptr;
-    filedisk_ptr->prev_free = disk_ptr->Dev->Ops.Free;
-    disk_ptr->Dev->Ops.Free = free_filedisk;
-    disk_ptr->Dev->Ops.PnpId = query_id;
-    disk_ptr->disk_ops.Io = io;
-    disk_ptr->disk_ops.Close = close;
-    disk_ptr->ext = filedisk_ptr;
-    disk_ptr->DriverObj = WvDriverObj;
-
-    return filedisk_ptr;
-
-    err_nofiledisk:
-
-    WvDevFree(disk_ptr->Dev);
-    err_nodisk:
+    if (!NT_SUCCESS(status)) {
+        WvlError("WvlDiskCreatePdo", status);
+        return NULL;
+      }
 
-    return NULL;
-  }
+    filedisk = pdo->DeviceExtension;
+    RtlZeroMemory(filedisk, sizeof *filedisk);
+    WvDiskInit(filedisk->disk);
+    WvDevInit(filedisk->disk->Dev);
+    filedisk->disk->Dev->Ops.Free = WvFilediskFree_;
+    filedisk->disk->Dev->Ops.PnpId = query_id;
+    filedisk->disk->Dev->Ops.Close = WvFilediskClose_;
+    filedisk->disk->Dev->ext = filedisk->disk;
+    filedisk->disk->Dev->IrpMj = &irp_mj;
+    filedisk->disk->disk_ops.Io = io;
+    filedisk->disk->ext = filedisk;
+    filedisk->disk->DriverObj = WvDriverObj;
+
+    /* Set associations for the PDO, device, disk. */
+    WvDevForDevObj(pdo, filedisk->disk->Dev);
+    KeInitializeEvent(
+        &filedisk->disk->SearchEvent,
+        SynchronizationEvent,
+        FALSE
+      );
+    KeInitializeSpinLock(&filedisk->disk->SpinLock);
+    filedisk->disk->Dev->Self = pdo;
 
-/**
- * Initialize the global, file-backed disk-common environment.
- *
- * @ret ntstatus        STATUS_SUCCESS or the NTSTATUS for a failure.
- */
-NTSTATUS WvFilediskModuleInit(void) {
-    /* Initialize the global list of file-backed disks. */
-    InitializeListHead(&filedisk_list);
-    KeInitializeSpinLock(&filedisk_list_lock);
+    /* Some device parameters. */
+    pdo->Flags |= DO_DIRECT_IO;         /* FIXME? */
+    pdo->Flags |= DO_POWER_INRUSH;      /* FIXME? */
 
-    return STATUS_SUCCESS;
+    DBG("New PDO: %p\n", pdo);
+    return filedisk;
   }
 
 /**
  * Default file-backed disk deletion operation.
  *
- * @v dev_ptr           Points to the file-backed disk device to delete.
+ * @v dev               Points to the file-backed disk device to delete.
  */
-static VOID STDCALL free_filedisk(IN WV_SP_DEV_T dev_ptr) {
-    WV_SP_DISK_T disk_ptr = disk__get_ptr(dev_ptr);
-    WV_SP_FILEDISK_T 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
-      );
-  
-    wv_free(filedisk_ptr);
+static VOID STDCALL WvFilediskFree_(IN WV_SP_DEV_T dev) {
+    IoDeleteDevice(dev->Self);
   }
 
 /* Threaded read/write request. */
@@ -425,7 +421,7 @@ static VOID STDCALL thread(IN PVOID StartContext) {
           } /* while requests */
       } /* main loop */
     /* Time to tear things down. */
-    free_filedisk(filedisk_ptr->disk->Dev);
+    WvFilediskFree_(filedisk_ptr->disk->Dev);
   }
 
 static NTSTATUS STDCALL threaded_io(
@@ -480,17 +476,21 @@ static VOID STDCALL free_threaded_filedisk(IN WV_SP_DEV_T dev_ptr) {
 /**
  * Create a new threaded, file-backed disk.
  *
+ * @v MediaType         The media type for the filedisk.
  * @ret filedisk_ptr    The address of a new filedisk, or NULL for failure.
  *
- * See the header file for additional details.
+ * See WvFilediskCreatePdo() above.  This routine uses threaded routines
+ * for disk reads/writes, and frees asynchronously, too.
  */
-WV_SP_FILEDISK_T WvFilediskCreateThreaded(void) {
+WV_SP_FILEDISK_T WvFilediskCreatePdoThreaded(
+    IN WVL_E_DISK_MEDIA_TYPE MediaType
+  ) {
     WV_SP_FILEDISK_T filedisk_ptr;
     OBJECT_ATTRIBUTES obj_attrs;
     HANDLE thread_handle;
 
     /* Try to create a filedisk. */
-    filedisk_ptr = WvFilediskCreate();
+    filedisk_ptr = WvFilediskCreatePdo(MediaType);
     if (filedisk_ptr == NULL)
       goto err_nofiledisk;
     /* Use threaded routines. */
index d27343e..2255b4b 100644 (file)
@@ -356,6 +356,9 @@ VOID filedisk_grub4dos__find(void) {
       /* Search for sector-mapped (typically file-backed) disks. */
       i = 8;
       while (i--) {
+          WVL_E_DISK_MEDIA_TYPE media_type;
+          UINT32 sector_size;
+
           if (
               (Grub4DosDriveMapSlotPtr[i].SectorCount == 0) ||
               (Grub4DosDriveMapSlotPtr[i].DestDrive == 0xff)
@@ -396,18 +399,31 @@ VOID filedisk_grub4dos__find(void) {
               "GRUB4DOS SectorCount: %d\n",
               Grub4DosDriveMapSlotPtr[i].SectorCount
             );
+          /* Possible precision loss. */
+          if (Grub4DosDriveMapSlotPtr[i].SourceODD) {
+              media_type = WvlDiskMediaTypeOptical;
+              sector_size = 2048;
+            } else {
+              media_type =
+                (Grub4DosDriveMapSlotPtr[i].SourceDrive & 0x80) ?
+                WvlDiskMediaTypeHard :
+                WvlDiskMediaTypeFloppy;
+              sector_size = 512;
+            }
           /*
            * Create the threaded, file-backed disk.  Hook the
            * read/write routine so we can accessing the backing disk
            * late(r) during the boot process.
            */
-          filedisk_ptr = WvFilediskCreateThreaded();
+          filedisk_ptr = WvFilediskCreatePdoThreaded(media_type);
           if (filedisk_ptr == NULL) {
               DBG("Could not create GRUB4DOS disk!\n");
               return;
             }
           sync_io = filedisk_ptr->sync_io;
           filedisk_ptr->sync_io = io;
+          filedisk_ptr->disk->Media = media_type;
+          filedisk_ptr->disk->SectorSize = sector_size;
           /* Find an associated filename, if one exists. */
           {   int j = 8;
 
@@ -441,17 +457,6 @@ VOID filedisk_grub4dos__find(void) {
                     );
                 } /* if */
             } /* j scope. */
-          /* Possible precision loss. */
-          if (Grub4DosDriveMapSlotPtr[i].SourceODD) {
-              filedisk_ptr->disk->Media = WvlDiskMediaTypeOptical;
-              filedisk_ptr->disk->SectorSize = 2048;
-            } else {
-              filedisk_ptr->disk->Media =
-                (Grub4DosDriveMapSlotPtr[i].SourceDrive & 0x80) ?
-                WvlDiskMediaTypeHard :
-                WvlDiskMediaTypeFloppy;
-              filedisk_ptr->disk->SectorSize = 512;
-            }
           DBG(
               "Sector-mapped disk is type: %d\n",
               filedisk_ptr->disk->Media