Improved disk driver stack.
[reactos.git] / reactos / drivers / storage / class2 / class2.c
index 49d2179..be78744 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: class2.c,v 1.1 2001/07/23 06:12:07 ekohl Exp $
+/* $Id: class2.c,v 1.2 2002/01/14 01:43:26 ekohl Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
 #include "../include/scsi.h"
 #include "../include/class2.h"
 
+//#define NDEBUG
+#include <debug.h>
 
-#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0)
+//#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0)
 
 #define VERSION "0.0.1"
 
+#define INQUIRY_DATA_SIZE 2048
+
+
+static NTSTATUS STDCALL
+ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject,
+                    IN PIRP Irp);
+
+static NTSTATUS STDCALL
+ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
+                  IN PIRP Irp);
+
+static NTSTATUS STDCALL
+ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
+                    IN PIRP Irp);
+
+static NTSTATUS STDCALL
+ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
+                      IN PIRP Irp);
+
+static NTSTATUS STDCALL
+ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
+                      IN PIRP Irp);
+
 //  -------------------------------------------------------  Public Interface
 
 //    DriverEntry
@@ -39,7 +64,7 @@ NTSTATUS STDCALL
 DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath)
 {
-  DbgPrint("ScsiPort Driver %s\n", VERSION);
+  DbgPrint("Class Driver %s\n", VERSION);
   return(STATUS_SUCCESS);
 }
 
@@ -66,9 +91,9 @@ ScsiClassDebugPrint(IN ULONG DebugPrintLevel,
 
 
 NTSTATUS STDCALL
-ScsiClassAsynchronousCompletion(PDEVICE_OBJECT DeviceObject,
-                               PIRP Irp,
-                               PVOID Context)
+ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject,
+                               IN PIRP Irp,
+                               IN PVOID Context)
 {
   UNIMPLEMENTED;
 }
@@ -125,7 +150,8 @@ ULONG STDCALL
 ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData,
                              PSCSI_ADAPTER_BUS_INFO AdapterInformation)
 {
-  UNIMPLEMENTED;
+  DPRINT("ScsiClassFindUnclaimedDevices() called!\n");
+  return(0);
 }
 
 
@@ -133,7 +159,42 @@ NTSTATUS STDCALL
 ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
                         PIO_SCSI_CAPABILITIES *PortCapabilities)
 {
-  UNIMPLEMENTED;
+  IO_STATUS_BLOCK IoStatusBlock;
+  NTSTATUS Status;
+  KEVENT Event;
+  PIRP Irp;
+
+  KeInitializeEvent(&Event,
+                   NotificationEvent,
+                   FALSE);
+
+  Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES,
+                                     PortDeviceObject,
+                                     NULL,
+                                     0,
+                                     PortCapabilities,
+                                     sizeof(PVOID),
+                                     FALSE,
+                                     &Event,
+                                     &IoStatusBlock);
+  if (Irp == NULL)
+    {
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  Status = IoCallDriver(PortDeviceObject,
+                       Irp);
+  if (Status == STATUS_PENDING)
+    {
+      KeWaitForSingleObject(&Event,
+                           Suspended,
+                           KernelMode,
+                           FALSE,
+                           NULL);
+      return(IoStatusBlock.Status);
+    }
+
+  return(Status);
 }
 
 
@@ -141,7 +202,58 @@ NTSTATUS STDCALL
 ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
                        PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
 {
-  UNIMPLEMENTED;
+  PSCSI_ADAPTER_BUS_INFO Buffer;
+  IO_STATUS_BLOCK IoStatusBlock;
+  NTSTATUS Status;
+  KEVENT Event;
+  PIRP Irp;
+
+  Buffer = ExAllocatePool(NonPagedPool, /* FIXME: use paged pool */
+                         INQUIRY_DATA_SIZE);
+  *ConfigInfo = Buffer;
+
+  if (Buffer == NULL)
+    {
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  KeInitializeEvent(&Event,
+                   NotificationEvent,
+                   FALSE);
+
+  Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA,
+                                     PortDeviceObject,
+                                     NULL,
+                                     0,
+                                     Buffer,
+                                     INQUIRY_DATA_SIZE,
+                                     FALSE,
+                                     &Event,
+                                     &IoStatusBlock);
+  if (Irp == NULL)
+    {
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  Status = IoCallDriver(PortDeviceObject,
+                       Irp);
+  if (Status == STATUS_PENDING)
+    {
+      KeWaitForSingleObject(&Event,
+                           Suspended,
+                           KernelMode,
+                           FALSE,
+                           NULL);
+      Status = IoStatusBlock.Status;
+    }
+
+  if (!NT_SUCCESS(Status))
+    {
+      ExFreePool(Buffer);
+      *ConfigInfo = NULL;
+    }
+
+  return(Status);
 }
 
 
@@ -150,7 +262,66 @@ ScsiClassInitialize(PVOID Argument1,
                    PVOID Argument2,
                    PCLASS_INIT_DATA InitializationData)
 {
-  UNIMPLEMENTED;
+  PDRIVER_OBJECT DriverObject = Argument1;
+  WCHAR NameBuffer[80];
+  UNICODE_STRING PortName;
+  ULONG PortNumber = 0;
+  PDEVICE_OBJECT PortDeviceObject;
+  PFILE_OBJECT FileObject;
+  BOOLEAN DiskFound = FALSE;
+  NTSTATUS Status;
+
+  DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose;
+  DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
+  DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
+  DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
+  DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassScsiDispatch;
+  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceDispatch;
+  DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
+  DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
+  if (InitializationData->ClassStartIo)
+    {
+      DriverObject->DriverStartIo = InitializationData->ClassStartIo;
+    }
+
+  /* look for ScsiPortX scsi port devices */
+  do
+    {
+      swprintf(NameBuffer,
+              L"\\Device\\ScsiPort%lu",
+               PortNumber);
+      RtlInitUnicodeString(&PortName,
+                          NameBuffer);
+      DPRINT1("Checking scsi port %ld\n", PortNumber);
+      Status = IoGetDeviceObjectPointer(&PortName,
+                                       FILE_READ_ATTRIBUTES,
+                                       &FileObject,
+                                       &PortDeviceObject);
+      DPRINT1("Status 0x%08lX\n", Status);
+      if (NT_SUCCESS(Status))
+       {
+         DPRINT1("ScsiPort%lu found.\n", PortNumber);
+
+         /* Check scsi port for attached disk drives */
+         if (InitializationData->ClassFindDevices(DriverObject,
+                                                  Argument2,
+                                                  InitializationData,
+                                                  PortDeviceObject,
+                                                  PortNumber))
+           {
+             DiskFound = TRUE;
+           }
+
+         ObDereferenceObject(PortDeviceObject);
+         ObDereferenceObject(FileObject);
+       }
+       PortNumber++;
+    }
+  while (NT_SUCCESS(Status));
+
+for(;;);
+
+  return((DiskFound == TRUE) ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE);
 }
 
 
@@ -211,21 +382,21 @@ ScsiClassModeSense(PDEVICE_OBJECT DeviceObject,
 
 
 ULONG STDCALL
-ScsiClassQueryTimeOutRegistryValue(PUNICODE_STRING RegistryPath)
+ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath)
 {
   UNIMPLEMENTED;
 }
 
 
 NTSTATUS STDCALL
-ScsiClassReadDriveCapacity(PDEVICE_OBJECT DeviceObject)
+ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
 {
   UNIMPLEMENTED;
 }
 
 
 VOID STDCALL
-ScsiClassReleaseQueue(PDEVICE_OBJECT DeviceObject)
+ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject)
 {
   UNIMPLEMENTED;
 }
@@ -262,4 +433,65 @@ ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject,
   UNIMPLEMENTED;
 }
 
+
+/* Internal Routines **************/
+
+static NTSTATUS STDCALL
+ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject,
+                    IN PIRP Irp)
+{
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return(STATUS_SUCCESS);
+}
+
+static NTSTATUS STDCALL
+ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
+                  IN PIRP Irp)
+{
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return(STATUS_SUCCESS);
+}
+
+
+static NTSTATUS STDCALL
+ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp)
+{
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return(STATUS_SUCCESS);
+}
+
+
+static NTSTATUS STDCALL
+ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
+                       IN PIRP Irp)
+{
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return(STATUS_SUCCESS);
+}
+
+
+static NTSTATUS STDCALL
+ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
+                      IN PIRP Irp)
+{
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return(STATUS_SUCCESS);
+}
+
 /* EOF */