[freeldr] Load an additional SCSI driver if present (NTBOOTSYS.SYS on boot partition...
authorHervé Poussineau <hpoussin@reactos.org>
Mon, 8 Mar 2010 22:04:38 +0000 (22:04 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Mon, 8 Mar 2010 22:04:38 +0000 (22:04 +0000)
Works only with very simple miniport drivers.

svn path=/trunk/; revision=46017

reactos/boot/freeldr/freeldr/bootmgr.c
reactos/boot/freeldr/freeldr/disk/scsiport.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/freeldr.c
reactos/boot/freeldr/freeldr/freeldr_base.rbuild
reactos/boot/freeldr/freeldr/include/disk.h
reactos/boot/freeldr/freeldr/include/reactos.h
reactos/boot/freeldr/freeldr/reactos/arcname.c
reactos/boot/freeldr/freeldr/windows/peloader.c

index 2a8e7be..0959de6 100644 (file)
@@ -119,6 +119,12 @@ VOID RunLoader(VOID)
                return;
        }
 
+       // Load additional SCSI driver (if any)
+       if (LoadBootDeviceDriver() != ESUCCESS)
+       {
+               UiMessageBoxCritical("Unable to load additional boot device driver");
+       }
+
        if (!IniFileInitialize())
        {
                UiMessageBoxCritical("Error initializing .ini file");
diff --git a/reactos/boot/freeldr/freeldr/disk/scsiport.c b/reactos/boot/freeldr/freeldr/disk/scsiport.c
new file mode 100644 (file)
index 0000000..d8d15b1
--- /dev/null
@@ -0,0 +1,1701 @@
+#include <freeldr.h>
+
+#define _SCSIPORT_
+
+#include <ntddk.h>
+#include <srb.h>
+#include <scsi.h>
+#include <ntddscsi.h>
+#include <ntddstor.h>
+#include <ntdddisk.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#define DPRINTM2(fmt, ...) DPRINTM(DPRINT_SCSIPORT, "(%s:%d) SCSIPORT: " fmt, __FILE__, __LINE__, __VA_ARGS__)
+
+#undef UNIMPLEMENTED
+#define UNIMPLEMENTED DPRINTM2("%s UNIMPLEMENTED\n", __FUNCTION__)
+
+#define SCSI_PORT_NEXT_REQUEST_READY  0x0008
+
+typedef struct
+{
+    PVOID NonCachedExtension;
+
+    ULONG BusNum;
+    ULONG MaxTargedIds;
+
+    ULONG InterruptFlags;
+
+    /* SRB extension stuff */
+    ULONG SrbExtensionSize;
+    PVOID SrbExtensionBuffer;
+
+    IO_SCSI_CAPABILITIES PortCapabilities;
+
+    PHW_INITIALIZE HwInitialize;
+    PHW_STARTIO HwStartIo;
+    PHW_INTERRUPT HwInterrupt;
+    PHW_RESET_BUS HwResetBus;
+
+    /* DMA related stuff */
+    PADAPTER_OBJECT AdapterObject;
+
+    ULONG CommonBufferLength;
+
+    PVOID MiniPortDeviceExtension;
+} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
+
+PSCSI_PORT_DEVICE_EXTENSION ScsiDeviceExtensions[SCSI_MAXIMUM_BUSES];
+
+ULONG
+ntohl(
+    IN ULONG Value)
+{
+    FOUR_BYTE Dest;
+    PFOUR_BYTE Source = (PFOUR_BYTE)&Value;
+
+    Dest.Byte0 = Source->Byte3;
+    Dest.Byte1 = Source->Byte2;
+    Dest.Byte2 = Source->Byte1;
+    Dest.Byte3 = Source->Byte0;
+
+    return Dest.AsULong;
+}
+
+BOOLEAN
+SpiSendSynchronousSrb(
+    IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+    IN PSCSI_REQUEST_BLOCK Srb)
+{
+    BOOLEAN ret;
+
+    ASSERT(!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE));
+
+    /* HACK: handle lack of interrupts */
+    while (!(DeviceExtension->InterruptFlags & SCSI_PORT_NEXT_REQUEST_READY))
+    {
+        KeStallExecutionProcessor(100 * 1000);
+        DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension);
+    }
+
+    DeviceExtension->InterruptFlags &= ~SCSI_PORT_NEXT_REQUEST_READY;
+    Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
+
+    if (!DeviceExtension->HwStartIo(
+            DeviceExtension->MiniPortDeviceExtension,
+            Srb))
+    {
+        ExFreePool(Srb);
+        return FALSE;
+    }
+
+    /* HACK: handle lack of interrupts */
+    while (Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)
+    {
+        KeStallExecutionProcessor(100 * 1000);
+        DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension);
+    }
+
+    ret = SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS;
+    ExFreePool(Srb);
+
+    return ret;
+}
+
+typedef struct tagDISKCONTEXT
+{
+    /* Device ID */
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    ULONG PathId;
+    ULONG TargetId;
+    ULONG Lun;
+
+    /* Device characteristics */
+    ULONG SectorSize;
+    ULONGLONG SectorOffset;
+    ULONGLONG SectorCount;
+    ULONGLONG SectorNumber;
+} DISKCONTEXT;
+
+static LONG DiskClose(ULONG FileId)
+{
+    DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
+
+    ExFreePool(Context);
+    return ESUCCESS;
+}
+
+static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
+{
+    DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
+
+    RtlZeroMemory(Information, sizeof(FILEINFORMATION));
+    Information->EndingAddress.QuadPart = Context->SectorCount * Context->SectorSize;
+    Information->CurrentAddress.LowPart = Context->SectorNumber * Context->SectorSize;
+
+    return ESUCCESS;
+}
+
+static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
+{
+    PSCSI_REQUEST_BLOCK Srb;
+    PCDB Cdb;
+    READ_CAPACITY_DATA ReadCapacityBuffer;
+
+    DISKCONTEXT* Context;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    ULONG ScsiBus, PathId, TargetId, Lun, Partition, PathSyntax;
+    ULONG SectorSize;
+    ULONGLONG SectorOffset = 0;
+    ULONGLONG SectorCount;
+
+    /* Parse ARC path */
+    if (!DissectArcPath2(Path, &ScsiBus, &TargetId, &Lun, &Partition, &PathSyntax))
+        return EINVAL;
+    if (PathSyntax != 0) /* scsi() format */
+        return EINVAL;
+    DeviceExtension = ScsiDeviceExtensions[ScsiBus];
+    PathId = ScsiBus - DeviceExtension->BusNum;
+
+    /* Get disk capacity and sector size */
+    Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
+    if (!Srb)
+        return ENOMEM;
+    RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
+    Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
+    Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+    Srb->PathId = PathId;
+    Srb->TargetId = TargetId;
+    Srb->Lun = Lun;
+    Srb->CdbLength = 10;
+    Srb->SrbFlags = SRB_FLAGS_DATA_IN;
+    Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
+    Srb->TimeOutValue = 5; /* in seconds */
+    Srb->DataBuffer = &ReadCapacityBuffer;
+    Cdb = (PCDB)Srb->Cdb;
+    Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
+    if (!SpiSendSynchronousSrb(DeviceExtension, Srb))
+    {
+        return EIO;
+    }
+
+    /* Transform result to host endianness */
+    SectorCount = ntohl(ReadCapacityBuffer.LogicalBlockAddress);
+    SectorSize = ntohl(ReadCapacityBuffer.BytesPerBlock);
+
+    if (Partition != 0)
+    {
+        /* Need to offset start of disk and length */
+        UNIMPLEMENTED;
+        return EIO;
+    }
+
+    Context = ExAllocatePool(PagedPool, sizeof(DISKCONTEXT));
+    if (!Context)
+        return ENOMEM;
+    Context->DeviceExtension = DeviceExtension;
+    Context->PathId = PathId;
+    Context->TargetId = TargetId;
+    Context->Lun = Lun;
+    Context->SectorSize = SectorSize;
+    Context->SectorOffset = SectorOffset;
+    Context->SectorCount = SectorCount;
+    Context->SectorNumber = 0;
+    FsSetDeviceSpecific(*FileId, Context);
+
+    return ESUCCESS;
+}
+
+static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
+{
+    DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
+    PSCSI_REQUEST_BLOCK Srb;
+    PCDB Cdb;
+    ULONG FullSectors, NbSectors;
+    ULONG Lba;
+
+    *Count = 0;
+
+    if (N == 0)
+        return ESUCCESS;
+
+    FullSectors = N / Context->SectorSize;
+    NbSectors = (N + Context->SectorSize - 1) / Context->SectorSize;
+    if (Context->SectorNumber + NbSectors >= Context->SectorCount)
+        return EINVAL;
+    if (FullSectors > 0xffff)
+        return EINVAL;
+
+    /* Read full sectors */
+    Lba = Context->SectorNumber;
+    if (FullSectors > 0)
+    {
+        Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
+        if (!Srb)
+            return ENOMEM;
+
+        RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
+        Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
+        Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+        Srb->PathId = Context->PathId;
+        Srb->TargetId = Context->TargetId;
+        Srb->Lun = Context->Lun;
+        Srb->CdbLength = 10;
+        Srb->SrbFlags = SRB_FLAGS_DATA_IN;
+        Srb->DataTransferLength = FullSectors * Context->SectorSize;
+        Srb->TimeOutValue = 5; /* in seconds */
+        Srb->DataBuffer = Buffer;
+        Cdb = (PCDB)Srb->Cdb;
+        Cdb->CDB10.OperationCode = SCSIOP_READ;
+        Cdb->CDB10.LogicalUnitNumber = Srb->Lun;
+        Cdb->CDB10.LogicalBlockByte0 = (Lba >> 24) & 0xff;
+        Cdb->CDB10.LogicalBlockByte1 = (Lba >> 16) & 0xff;
+        Cdb->CDB10.LogicalBlockByte2 = (Lba >> 8) & 0xff;
+        Cdb->CDB10.LogicalBlockByte3 = Lba & 0xff;
+        Cdb->CDB10.TransferBlocksMsb = (FullSectors >> 8) & 0xff;
+        Cdb->CDB10.TransferBlocksLsb = FullSectors & 0xff;
+        if (!SpiSendSynchronousSrb(Context->DeviceExtension, Srb))
+        {
+            return EIO;
+        }
+        Buffer = (PUCHAR)Buffer + FullSectors * Context->SectorSize;
+        N -= FullSectors * Context->SectorSize;
+        *Count += FullSectors * Context->SectorSize;
+        Lba += FullSectors;
+    }
+
+    /* Read incomplete last sector */
+    if (N > 0)
+    {
+        PUCHAR Sector;
+
+        Sector = ExAllocatePool(PagedPool, Context->SectorSize);
+        if (!Sector)
+            return ENOMEM;
+
+        Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
+        if (!Srb)
+        {
+            ExFreePool(Sector);
+            return ENOMEM;
+        }
+
+        RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
+        Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
+        Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+        Srb->PathId = Context->PathId;
+        Srb->TargetId = Context->TargetId;
+        Srb->Lun = Context->Lun;
+        Srb->CdbLength = 10;
+        Srb->SrbFlags = SRB_FLAGS_DATA_IN;
+        Srb->DataTransferLength = Context->SectorSize;
+        Srb->TimeOutValue = 5; /* in seconds */
+        Srb->DataBuffer = Sector;
+        Cdb = (PCDB)Srb->Cdb;
+        Cdb->CDB10.OperationCode = SCSIOP_READ;
+        Cdb->CDB10.LogicalUnitNumber = Srb->Lun;
+        Cdb->CDB10.LogicalBlockByte0 = (Lba >> 24) & 0xff;
+        Cdb->CDB10.LogicalBlockByte1 = (Lba >> 16) & 0xff;
+        Cdb->CDB10.LogicalBlockByte2 = (Lba >> 8) & 0xff;
+        Cdb->CDB10.LogicalBlockByte3 = Lba & 0xff;
+        Cdb->CDB10.TransferBlocksMsb = 0;
+        Cdb->CDB10.TransferBlocksLsb = 1;
+        if (!SpiSendSynchronousSrb(Context->DeviceExtension, Srb))
+        {
+            ExFreePool(Sector);
+            return EIO;
+        }
+        RtlCopyMemory(Buffer, Sector, N);
+        *Count += N;
+        ExFreePool(Sector);
+    }
+
+    return ESUCCESS;
+}
+
+static LONG DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
+{
+    DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
+
+    if (SeekMode != SeekAbsolute)
+        return EINVAL;
+    if (Position->QuadPart & (Context->SectorSize - 1))
+        return EINVAL;
+
+    Context->SectorNumber = Position->QuadPart / Context->SectorSize;
+    return ESUCCESS;
+}
+
+static const DEVVTBL DiskVtbl = {
+    DiskClose,
+    DiskGetFileInformation,
+    DiskOpen,
+    DiskRead,
+    DiskSeek,
+};
+
+NTSTATUS
+SpiCreatePortConfig(
+    IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+    IN PHW_INITIALIZATION_DATA HwInitData,
+    OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+    IN BOOLEAN ZeroStruct)
+{
+    ULONG Bus;
+
+    /* Zero out the struct if told so */
+    if (ZeroStruct)
+    {
+        /* First zero the portconfig */
+        RtlZeroMemory(ConfigInfo, sizeof(PORT_CONFIGURATION_INFORMATION));
+
+        /* Initialize the struct */
+        ConfigInfo->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
+        ConfigInfo->AdapterInterfaceType = HwInitData->AdapterInterfaceType;
+        ConfigInfo->InterruptMode = Latched;
+        ConfigInfo->DmaChannel = SP_UNINITIALIZED_VALUE;
+        ConfigInfo->DmaPort = SP_UNINITIALIZED_VALUE;
+        ConfigInfo->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
+        ConfigInfo->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS_PER_BUS;
+
+        /* Store parameters */
+        ConfigInfo->NeedPhysicalAddresses = HwInitData->NeedPhysicalAddresses;
+        ConfigInfo->MapBuffers = HwInitData->MapBuffers;
+        ConfigInfo->AutoRequestSense = HwInitData->AutoRequestSense;
+        ConfigInfo->ReceiveEvent = HwInitData->ReceiveEvent;
+        ConfigInfo->TaggedQueuing = HwInitData->TaggedQueuing;
+        ConfigInfo->MultipleRequestPerLu = HwInitData->MultipleRequestPerLu;
+
+        /* Get the disk usage */
+        ConfigInfo->AtdiskPrimaryClaimed = FALSE; // FIXME
+        ConfigInfo->AtdiskSecondaryClaimed = FALSE; // FIXME
+
+        /* Initiator bus id is not set */
+        for (Bus = 0; Bus < 8; Bus++)
+            ConfigInfo->InitiatorBusId[Bus] = (CCHAR)SP_UNINITIALIZED_VALUE;
+    }
+
+    ConfigInfo->NumberOfPhysicalBreaks = 17;
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+DDKCDECLAPI
+ScsiDebugPrint(
+    IN ULONG DebugPrintLevel,
+    IN PCCHAR DebugMessage,
+    IN ...)
+{
+    va_list ap;
+    CHAR Buffer[512];
+    ULONG Length;
+
+    if (DebugPrintLevel > 10)
+        return;
+
+    va_start(ap, DebugMessage);
+
+    /* Construct a string */
+    Length = _vsnprintf(Buffer, 512, DebugMessage, ap);
+
+    /* Check if we went past the buffer */
+    if (Length == MAXULONG)
+    {
+        /* Terminate it if we went over-board */
+        Buffer[sizeof(Buffer) - 1] = '\0';
+
+        /* Put maximum */
+        Length = sizeof(Buffer);
+    }
+
+    /* Print the message */
+    DPRINTM(DPRINT_SCSIPORT, "%s", Buffer);
+
+    /* Cleanup */
+    va_end(ap);
+}
+
+VOID
+DDKAPI
+ScsiPortCompleteRequest(
+    IN PVOID HwDeviceExtension,
+    IN UCHAR PathId,
+    IN UCHAR TargetId,
+    IN UCHAR Lun,
+    IN UCHAR SrbStatus)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+#undef ScsiPortConvertPhysicalAddressToUlong
+ULONG
+DDKAPI
+ScsiPortConvertPhysicalAddressToUlong(
+    IN SCSI_PHYSICAL_ADDRESS Address)
+{
+    return Address.LowPart;
+}
+
+SCSI_PHYSICAL_ADDRESS
+DDKAPI
+ScsiPortConvertUlongToPhysicalAddress(
+    IN ULONG UlongAddress)
+{
+    return RtlConvertUlongToLargeInteger(UlongAddress);
+}
+
+VOID
+DDKAPI
+ScsiPortFlushDma(
+    IN PVOID DeviceExtension)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+VOID
+DDKAPI
+ScsiPortFreeDeviceBase(
+    IN PVOID HwDeviceExtension,
+    IN PVOID MappedAddress)
+{
+    // Nothing to do
+}
+
+ULONG
+DDKAPI
+ScsiPortGetBusData(
+    IN PVOID DeviceExtension,
+    IN ULONG BusDataType,
+    IN ULONG SystemIoBusNumber,
+    IN ULONG SlotNumber,
+    IN PVOID Buffer,
+    IN ULONG Length)
+{
+    return HalGetBusDataByOffset(BusDataType, SystemIoBusNumber, SlotNumber, Buffer, 0, Length);
+}
+
+PVOID
+DDKAPI
+ScsiPortGetDeviceBase(
+    IN PVOID HwDeviceExtension,
+    IN INTERFACE_TYPE BusType,
+    IN ULONG SystemIoBusNumber,
+    IN SCSI_PHYSICAL_ADDRESS IoAddress,
+    IN ULONG NumberOfBytes,
+    IN BOOLEAN InIoSpace)
+{
+    PHYSICAL_ADDRESS TranslatedAddress;
+    ULONG AddressSpace;
+
+    AddressSpace = (ULONG)InIoSpace;
+    if (HalTranslateBusAddress(BusType,
+                               SystemIoBusNumber,
+                               IoAddress,
+                               &AddressSpace,
+                               &TranslatedAddress) == FALSE)
+    {
+        return NULL;
+    }
+
+    /* I/O space */
+    if (AddressSpace != 0)
+        return (PVOID)TranslatedAddress.u.LowPart;
+
+    // FIXME
+    UNIMPLEMENTED;
+    return (PVOID)IoAddress.LowPart;
+}
+
+PVOID
+DDKAPI
+ScsiPortGetLogicalUnit(
+    IN PVOID HwDeviceExtension,
+    IN UCHAR PathId,
+    IN UCHAR TargetId,
+    IN UCHAR Lun)
+{
+    // FIXME
+    UNIMPLEMENTED;
+    return NULL;
+}
+
+SCSI_PHYSICAL_ADDRESS
+DDKAPI
+ScsiPortGetPhysicalAddress(
+    IN PVOID HwDeviceExtension,
+    IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
+    IN PVOID VirtualAddress,
+    OUT ULONG *Length)
+{
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    SCSI_PHYSICAL_ADDRESS PhysicalAddress;
+    ULONG BufferLength = 0;
+    ULONG Offset;
+
+    DPRINTM2("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
+        HwDeviceExtension, Srb, VirtualAddress, Length);
+
+    DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
+
+    if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)
+    {
+        /* Simply look it up in the allocated common buffer */
+        Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer;
+
+        BufferLength = DeviceExtension->CommonBufferLength - Offset;
+        PhysicalAddress.QuadPart = Offset;
+    }
+    else
+    {
+        /* Nothing */
+        *Length = 0;
+        PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
+    }
+
+    *Length = BufferLength;
+    return PhysicalAddress;
+}
+
+PSCSI_REQUEST_BLOCK
+DDKAPI
+ScsiPortGetSrb(
+    IN PVOID DeviceExtension,
+    IN UCHAR PathId,
+    IN UCHAR TargetId,
+    IN UCHAR Lun,
+    IN LONG QueueTag)
+{
+    // FIXME
+    UNIMPLEMENTED;
+    return NULL;
+}
+
+NTSTATUS
+SpiAllocateCommonBuffer(
+    IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+    IN ULONG NonCachedSize)
+{
+    PVOID CommonBuffer;
+    ULONG CommonBufferLength, BufSize;
+
+    /* If size is 0, set it to 16 */
+    if (!DeviceExtension->SrbExtensionSize)
+        DeviceExtension->SrbExtensionSize = 16;
+
+    /* Calculate size */
+    BufSize = DeviceExtension->SrbExtensionSize;
+
+    /* Round it */
+    BufSize = (BufSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
+
+    /* Sum up into the total common buffer length, and round it to page size */
+    CommonBufferLength =
+        ROUND_TO_PAGES(NonCachedSize);
+
+    /* Allocate it */
+    if (!DeviceExtension->AdapterObject)
+    {
+        /* From nonpaged pool if there is no DMA */
+        CommonBuffer = ExAllocatePool(NonPagedPool, CommonBufferLength);
+    }
+    else
+    {
+        /* Perform a full request since we have a DMA adapter*/
+        UNIMPLEMENTED;
+        CommonBuffer = NULL;
+    }
+
+    /* Fail in case of error */
+    if (!CommonBuffer)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* Zero it */
+    RtlZeroMemory(CommonBuffer, CommonBufferLength);
+
+    /* Store its size in Device Extension */
+    DeviceExtension->CommonBufferLength = CommonBufferLength;
+
+    /* SrbExtension buffer is located at the beginning of the buffer */
+    DeviceExtension->SrbExtensionBuffer = CommonBuffer;
+
+    /* Non-cached extension buffer is located at the end of
+       the common buffer */
+    if (NonCachedSize)
+    {
+        CommonBufferLength -=  NonCachedSize;
+        DeviceExtension->NonCachedExtension = (PUCHAR)CommonBuffer + CommonBufferLength;
+    }
+    else
+    {
+        DeviceExtension->NonCachedExtension = NULL;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+PVOID
+DDKAPI
+ScsiPortGetUncachedExtension(
+    IN PVOID HwDeviceExtension,
+    IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+    IN ULONG NumberOfBytes)
+{
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    DEVICE_DESCRIPTION DeviceDescription;
+    ULONG MapRegistersCount;
+    NTSTATUS Status;
+
+    DPRINTM2("ScsiPortGetUncachedExtension(%p %p %lu)\n",
+        HwDeviceExtension, ConfigInfo, NumberOfBytes);
+
+    DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
+
+    /* Check for allocated common DMA buffer */
+    if (DeviceExtension->SrbExtensionBuffer != NULL)
+    {
+        return NULL;
+    }
+
+    /* Check for DMA adapter object */
+    if (DeviceExtension->AdapterObject == NULL)
+    {
+        /* Initialize DMA adapter description */
+        RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
+
+        DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
+        DeviceDescription.Master = ConfigInfo->Master;
+        DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
+        DeviceDescription.DemandMode = ConfigInfo->DemandMode;
+        DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
+        DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
+        DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
+        DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
+        DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
+        DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
+        DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
+        DeviceDescription.DmaPort = ConfigInfo->DmaPort;
+
+        /* Get a DMA adapter object */
+#if 0
+        DeviceExtension->AdapterObject =
+            HalGetAdapter(&DeviceDescription, &MapRegistersCount);
+
+        /* Fail in case of error */
+        if (DeviceExtension->AdapterObject == NULL)
+        {
+            return NULL;
+        }
+#else
+        MapRegistersCount = 0;
+#endif
+
+        /* Set number of physical breaks */
+        if (ConfigInfo->NumberOfPhysicalBreaks != 0 &&
+            MapRegistersCount > ConfigInfo->NumberOfPhysicalBreaks)
+        {
+            DeviceExtension->PortCapabilities.MaximumPhysicalPages =
+                ConfigInfo->NumberOfPhysicalBreaks;
+        }
+        else
+        {
+            DeviceExtension->PortCapabilities.MaximumPhysicalPages = MapRegistersCount;
+        }
+    }
+
+    /* Update Srb extension size */
+    if (DeviceExtension->SrbExtensionSize != ConfigInfo->SrbExtensionSize)
+        DeviceExtension->SrbExtensionSize = ConfigInfo->SrbExtensionSize;
+
+    /* Allocate a common DMA buffer */
+    Status = SpiAllocateCommonBuffer(DeviceExtension, NumberOfBytes);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINTM2("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status);
+        return NULL;
+    }
+
+    return DeviceExtension->NonCachedExtension;
+}
+
+PVOID
+DDKAPI
+ScsiPortGetVirtualAddress(
+    IN PVOID HwDeviceExtension,
+    IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
+{
+    // FIXME
+    UNIMPLEMENTED;
+    return NULL;
+}
+
+VOID
+SpiScanDevice(
+    IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+    IN PCHAR ArcName,
+    IN ULONG ScsiBus,
+    IN ULONG TargetId,
+    IN ULONG Lun)
+{
+    ULONG FileId, i;
+    ULONG Status;
+    NTSTATUS ret;
+    struct _DRIVE_LAYOUT_INFORMATION *PartitionBuffer;
+    CHAR PartitionName[64];
+
+    /* Register device with partition(0) suffix */
+    sprintf(PartitionName, "%spartition(0)", ArcName);
+    FsRegisterDevice(PartitionName, &DiskVtbl);
+
+    /* Read device partition table */
+    Status = ArcOpen(PartitionName, OpenReadOnly, &FileId);
+    if (Status == ESUCCESS)
+    {
+        ret = HALDISPATCH->HalIoReadPartitionTable((PDEVICE_OBJECT)FileId, 512, FALSE, &PartitionBuffer);
+        if (NT_SUCCESS(ret))
+        {
+            for (i = 0; i < PartitionBuffer->PartitionCount; i++)
+            {
+                if (PartitionBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED)
+                {
+                    sprintf(PartitionName, "%spartition(%lu)",
+                            ArcName, PartitionBuffer->PartitionEntry[i].PartitionNumber);
+                    FsRegisterDevice(PartitionName, &DiskVtbl);
+                }
+            }
+            ExFreePool(PartitionBuffer);
+        }
+        ArcClose(FileId);
+    }
+}
+
+VOID
+SpiScanAdapter(
+    IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+    IN ULONG ScsiBus,
+    IN ULONG PathId)
+{
+    CHAR ArcName[64];
+    PSCSI_REQUEST_BLOCK Srb;
+    PCDB Cdb;
+    INQUIRYDATA InquiryBuffer;
+    ULONG TargetId;
+    ULONG Lun;
+
+    if (!DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, PathId))
+    {
+        return;
+    }
+
+    /* Remember the extension */
+    ScsiDeviceExtensions[ScsiBus] = DeviceExtension;
+
+    for (TargetId = 0; TargetId < DeviceExtension->MaxTargedIds; TargetId++)
+    {
+        Lun = 0;
+        do
+        {
+            DPRINTM2("Scanning SCSI device %d.%d.%d\n",
+                ScsiBus, TargetId, Lun);
+
+            Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
+            if (!Srb)
+                break;
+            RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
+            Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
+            Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+            Srb->PathId = PathId;
+            Srb->TargetId = TargetId;
+            Srb->Lun = Lun;
+            Srb->CdbLength = 6;
+            Srb->SrbFlags = SRB_FLAGS_DATA_IN;
+            Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
+            Srb->TimeOutValue = 5; /* in seconds */
+            Srb->DataBuffer = &InquiryBuffer;
+            Cdb = (PCDB)Srb->Cdb;
+            Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
+            Cdb->CDB6INQUIRY.LogicalUnitNumber = Srb->Lun;
+            Cdb->CDB6INQUIRY.AllocationLength = Srb->DataTransferLength;
+            if (!SpiSendSynchronousSrb(DeviceExtension, Srb))
+            {
+                /* Don't check next LUNs */
+                break;
+            }
+
+            /* Device exists, create its ARC name */
+            if (InquiryBuffer.RemovableMedia)
+            {
+                sprintf(ArcName, "scsi(%ld)cdrom(%ld)fdisk(%ld)",
+                    ScsiBus, TargetId, Lun);
+                FsRegisterDevice(ArcName, &DiskVtbl);
+            }
+            else
+            {
+                sprintf(ArcName, "scsi(%ld)disk(%ld)rdisk(%ld)",
+                    ScsiBus, TargetId, Lun);
+                /* Now, check if it has partitions */
+                SpiScanDevice(DeviceExtension, ArcName, PathId, TargetId, Lun);
+            }
+
+            /* Check next LUN */
+            Lun++;
+        } while (Lun < SCSI_MAXIMUM_LOGICAL_UNITS);
+    }
+}
+
+VOID
+SpiResourceToConfig(
+    IN PHW_INITIALIZATION_DATA HwInitializationData,
+    IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
+    IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig)
+{
+    PACCESS_RANGE AccessRange;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData;
+    ULONG RangeNumber;
+    ULONG Index;
+
+    RangeNumber = 0;
+
+    /* Loop through all entries */
+    for (Index = 0; Index < ResourceDescriptor->PartialResourceList.Count; Index++)
+    {
+        PartialData = &ResourceDescriptor->PartialResourceList.PartialDescriptors[Index];
+
+        switch (PartialData->Type)
+        {
+        case CmResourceTypePort:
+            /* Copy access ranges */
+            if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
+            {
+                DPRINTM2("Got port at 0x%I64x, len 0x%x\n",
+                    PartialData->u.Port.Start.QuadPart, PartialData->u.Port.Length);
+                AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
+
+                AccessRange->RangeStart = PartialData->u.Port.Start;
+                AccessRange->RangeLength = PartialData->u.Port.Length;
+
+                AccessRange->RangeInMemory = FALSE;
+                RangeNumber++;
+            }
+            break;
+
+        case CmResourceTypeMemory:
+            /* Copy access ranges */
+            if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
+            {
+                DPRINTM2("Got memory at 0x%I64x, len 0x%x\n",
+                    PartialData->u.Memory.Start.QuadPart, PartialData->u.Memory.Length);
+                AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
+
+                AccessRange->RangeStart = PartialData->u.Memory.Start;
+                AccessRange->RangeLength = PartialData->u.Memory.Length;
+
+                AccessRange->RangeInMemory = TRUE;
+                RangeNumber++;
+            }
+            break;
+
+        case CmResourceTypeInterrupt:
+            /* Copy interrupt data */
+            DPRINTM2("Got interrupt level %d, vector %d\n",
+                PartialData->u.Interrupt.Level, PartialData->u.Interrupt.Vector);
+            PortConfig->BusInterruptLevel = PartialData->u.Interrupt.Level;
+            PortConfig->BusInterruptVector = PartialData->u.Interrupt.Vector;
+
+            /* Set interrupt mode accordingly to the resource */
+            if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
+            {
+                PortConfig->InterruptMode = Latched;
+            }
+            else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
+            {
+                PortConfig->InterruptMode = LevelSensitive;
+            }
+            break;
+
+        case CmResourceTypeDma:
+            DPRINTM2("Got DMA channel %d, port %d\n",
+                PartialData->u.Dma.Channel, PartialData->u.Dma.Port);
+            PortConfig->DmaChannel = PartialData->u.Dma.Channel;
+            PortConfig->DmaPort = PartialData->u.Dma.Port;
+            break;
+        }
+    }
+}
+
+BOOLEAN
+SpiGetPciConfigData(
+    IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
+    IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
+    IN ULONG BusNumber,
+    IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
+{
+    PCI_COMMON_CONFIG PciConfig;
+    PCI_SLOT_NUMBER SlotNumber;
+    ULONG DataSize;
+    ULONG DeviceNumber;
+    ULONG FunctionNumber;
+    CHAR VendorIdString[8];
+    CHAR DeviceIdString[8];
+    PCM_RESOURCE_LIST ResourceList;
+    NTSTATUS Status;
+
+    RtlZeroMemory(&ResourceList, sizeof(PCM_RESOURCE_LIST));
+    SlotNumber.u.AsULONG = 0;
+
+    /* Loop through all devices */
+    for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
+    {
+        SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+
+        /* Loop through all functions */
+        for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
+        {
+            SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+
+            /* Get PCI config bytes */
+            DataSize = HalGetBusDataByOffset(
+                PCIConfiguration,
+                BusNumber,
+                SlotNumber.u.AsULONG,
+                &PciConfig,
+                0,
+                sizeof(ULONG));
+
+            /* If result of HalGetBusData is 0, then the bus is wrong */
+            if (DataSize == 0)
+                return FALSE;
+
+            /* If result is PCI_INVALID_VENDORID, then this device has no more
+               "Functions" */
+            if (PciConfig.VendorID == PCI_INVALID_VENDORID)
+                break;
+
+            sprintf(VendorIdString, "%04hx", PciConfig.VendorID);
+            sprintf(DeviceIdString, "%04hx", PciConfig.DeviceID);
+
+            if (_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) ||
+                _strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength))
+            {
+                /* It is not our device */
+                continue;
+            }
+
+            DPRINTM2( "Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
+                PciConfig.VendorID, PciConfig.DeviceID,
+                BusNumber,
+                SlotNumber.u.bits.DeviceNumber, SlotNumber.u.bits.FunctionNumber);
+
+            Status = HalAssignSlotResources(NULL,
+                                            NULL,
+                                            NULL,
+                                            NULL,
+                                            PCIBus,
+                                            BusNumber,
+                                            SlotNumber.u.AsULONG,
+                                            &ResourceList);
+
+            if (!NT_SUCCESS(Status))
+                break;
+
+            /* Create configuration information */
+            SpiResourceToConfig(HwInitializationData,
+                                ResourceList->List,
+                                PortConfig);
+
+            /* Free the resource list */
+            ExFreePool(ResourceList);
+
+            /* Set dev & fn numbers */
+            NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
+            NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1;
+
+            /* Save the slot number */
+            PortConfig->SlotNumber = SlotNumber.u.AsULONG;
+
+            return TRUE;
+        }
+        NextSlotNumber->u.bits.FunctionNumber = 0;
+    }
+
+    NextSlotNumber->u.bits.DeviceNumber = 0;
+
+    return FALSE;
+}
+
+ULONG
+DDKAPI
+ScsiPortInitialize(
+    IN PVOID Argument1,
+    IN PVOID Argument2,
+    IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
+    IN PVOID HwContext OPTIONAL)
+{
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    ULONG DeviceExtensionSize;
+    PORT_CONFIGURATION_INFORMATION PortConfig;
+    BOOLEAN Again;
+    BOOLEAN FirstConfigCall = TRUE;
+    PCI_SLOT_NUMBER SlotNumber;
+    NTSTATUS Status;
+
+    if (HwInitializationData->HwInitializationDataSize != sizeof(HW_INITIALIZATION_DATA))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Check params for validity */
+    if ((HwInitializationData->HwInitialize == NULL) ||
+        (HwInitializationData->HwStartIo == NULL) ||
+        (HwInitializationData->HwInterrupt == NULL) ||
+        (HwInitializationData->HwFindAdapter == NULL) ||
+        (HwInitializationData->HwResetBus == NULL))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Zero starting slot number */
+    SlotNumber.u.AsULONG = 0;
+
+    while (TRUE)
+    {
+        Again = FALSE;
+
+        DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) + HwInitializationData->DeviceExtensionSize;
+        DeviceExtension = MmHeapAlloc(DeviceExtensionSize);
+        if (!DeviceExtension)
+        {
+            return STATUS_NO_MEMORY;
+        }
+        RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
+        DeviceExtension->InterruptFlags = SCSI_PORT_NEXT_REQUEST_READY;
+        DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
+        DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
+        DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
+        DeviceExtension->HwResetBus = HwInitializationData->HwResetBus;
+        DeviceExtension->MiniPortDeviceExtension = (PVOID)(DeviceExtension + 1);
+
+        Status = SpiCreatePortConfig(DeviceExtension,
+                                     HwInitializationData,
+                                     &PortConfig,
+                                     FirstConfigCall);
+        if (Status != STATUS_SUCCESS)
+        {
+            MmHeapFree(DeviceExtension);
+            return Status;
+        }
+
+        PortConfig.NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
+        PortConfig.AccessRanges = MmHeapAlloc(sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges);
+        if (!PortConfig.AccessRanges)
+        {
+           MmHeapFree(DeviceExtension);
+           return STATUS_NO_MEMORY;
+        }
+        RtlZeroMemory(PortConfig.AccessRanges, sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges);
+
+        /* Search for matching PCI device */
+        if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
+            (HwInitializationData->VendorIdLength > 0) &&
+            (HwInitializationData->VendorId != NULL) &&
+            (HwInitializationData->DeviceIdLength > 0) &&
+            (HwInitializationData->DeviceId != NULL))
+        {
+            PortConfig.BusInterruptLevel = 0;
+
+            /* Get PCI device data */
+            DPRINTM2("VendorId '%.*s'  DeviceId '%.*s'\n",
+                HwInitializationData->VendorIdLength,
+                HwInitializationData->VendorId,
+                HwInitializationData->DeviceIdLength,
+                HwInitializationData->DeviceId);
+
+            if (!SpiGetPciConfigData(HwInitializationData,
+                                     &PortConfig,
+                                     0, /* FIXME */
+                                     &SlotNumber))
+            {
+                /* Continue to the next bus, nothing here */
+                MmHeapFree(DeviceExtension);
+                return STATUS_INTERNAL_ERROR;
+            }
+
+            if (!PortConfig.BusInterruptLevel)
+            {
+                /* Bypass this slot, because no interrupt was assigned */
+                MmHeapFree(DeviceExtension);
+                return STATUS_INTERNAL_ERROR;
+            }
+        }
+
+        if (HwInitializationData->HwFindAdapter(
+             DeviceExtension->MiniPortDeviceExtension,
+             HwContext,
+             NULL,
+             NULL,
+             &PortConfig,
+             &Again) != SP_RETURN_FOUND)
+        {
+            MmHeapFree(DeviceExtension);
+            return STATUS_INTERNAL_ERROR;
+        }
+
+        /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
+        if (PortConfig.MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)
+            DeviceExtension->MaxTargedIds = SCSI_MAXIMUM_TARGETS_PER_BUS;
+        else
+            DeviceExtension->MaxTargedIds = PortConfig.MaximumNumberOfTargets;
+
+        DeviceExtension->BusNum = PortConfig.SystemIoBusNumber;
+
+        DPRINTM2("Adapter found: buses = %d, targets = %d\n",
+                 PortConfig.NumberOfBuses, DeviceExtension->MaxTargedIds);
+
+        /* Initialize adapter */
+        if (!DeviceExtension->HwInitialize(DeviceExtension->MiniPortDeviceExtension))
+        {
+            MmHeapFree(DeviceExtension);
+            return STATUS_INTERNAL_ERROR;
+        }
+
+        /* Scan bus */
+        {
+            ULONG ScsiBus;
+            for (ScsiBus = 0; ScsiBus < PortConfig.NumberOfBuses; ScsiBus++)
+            {
+                SpiScanAdapter(DeviceExtension, PortConfig.SystemIoBusNumber, ScsiBus);
+                PortConfig.SystemIoBusNumber++;
+            }
+        }
+
+        FirstConfigCall = FALSE;
+        if (!Again)
+        {
+            break;
+        }
+    }
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+DDKAPI
+ScsiPortIoMapTransfer(
+    IN PVOID HwDeviceExtension,
+    IN PSCSI_REQUEST_BLOCK Srb,
+    IN PVOID LogicalAddress,
+    IN ULONG Length)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+VOID
+DDKAPI
+ScsiPortLogError(
+    IN PVOID HwDeviceExtension,
+    IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
+    IN UCHAR PathId,
+    IN UCHAR TargetId,
+    IN UCHAR Lun,
+    IN ULONG ErrorCode,
+    IN ULONG UniqueId)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+VOID
+DDKAPI
+ScsiPortMoveMemory(
+    IN PVOID WriteBuffer,
+    IN PVOID ReadBuffer,
+    IN ULONG Length)
+{
+    RtlMoveMemory(WriteBuffer, ReadBuffer, Length);
+}
+
+VOID
+DDKCDECLAPI
+ScsiPortNotification(
+    IN SCSI_NOTIFICATION_TYPE NotificationType,
+    IN PVOID HwDeviceExtension,
+    IN ...)
+{
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    PSCSI_REQUEST_BLOCK Srb;
+    va_list ap;
+
+    DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
+
+    va_start(ap, HwDeviceExtension);
+
+    switch (NotificationType)
+    {
+        case RequestComplete:
+            /* Mask the SRB as completed */
+            Srb = va_arg(ap, PSCSI_REQUEST_BLOCK);
+            Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
+            break;
+
+        case NextRequest:
+            /* Say that device is ready */
+            DeviceExtension->InterruptFlags |= SCSI_PORT_NEXT_REQUEST_READY;
+            break;
+
+        default:
+            // FIXME
+            UNIMPLEMENTED;
+    }
+
+    va_end(ap);
+}
+
+VOID
+DDKAPI
+ScsiPortReadPortBufferUchar(
+    IN PUCHAR Port,
+    OUT PUCHAR Buffer,
+    IN ULONG Count)
+{
+    __inbytestring(H2I(Port), Buffer, Count);
+}
+
+VOID
+DDKAPI
+ScsiPortReadPortBufferUlong(
+    IN PULONG Port,
+    OUT PULONG Buffer,
+    IN ULONG Count)
+{
+    __indwordstring(H2I(Port), Buffer, Count);
+}
+
+VOID
+DDKAPI
+ScsiPortReadPortBufferUshort(
+    IN PUSHORT Port,
+    OUT PUSHORT Buffer,
+    IN ULONG Count)
+{
+    __inwordstring(H2I(Port), Buffer, Count);
+}
+
+UCHAR
+DDKAPI
+ScsiPortReadPortUchar(
+    IN PUCHAR Port)
+{
+    DPRINTM2("ScsiPortReadPortUchar(%p)\n",
+        Port);
+
+    return READ_PORT_UCHAR(Port);
+}
+
+ULONG
+DDKAPI
+ScsiPortReadPortUlong(
+    IN PULONG Port)
+{
+    return READ_PORT_ULONG(Port);
+}
+
+USHORT
+DDKAPI
+ScsiPortReadPortUshort(
+    IN PUSHORT Port)
+{
+    return READ_PORT_USHORT(Port);
+}
+
+VOID
+DDKAPI
+ScsiPortReadRegisterBufferUchar(
+    IN PUCHAR Register,
+    IN PUCHAR Buffer,
+    IN ULONG Count)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+VOID
+DDKAPI
+ScsiPortReadRegisterBufferUlong(
+    IN PULONG Register,
+    IN PULONG Buffer,
+    IN ULONG Count)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+VOID
+DDKAPI
+ScsiPortReadRegisterBufferUshort(
+    IN PUSHORT Register,
+    IN PUSHORT Buffer,
+    IN ULONG Count)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+UCHAR
+DDKAPI
+ScsiPortReadRegisterUchar(
+    IN PUCHAR Register)
+{
+    return READ_REGISTER_UCHAR(Register);
+}
+
+ULONG
+DDKAPI
+ScsiPortReadRegisterUlong(
+    IN PULONG Register)
+{
+    return READ_REGISTER_ULONG(Register);
+}
+
+USHORT
+DDKAPI
+ScsiPortReadRegisterUshort(
+    IN PUSHORT Register)
+{
+    return READ_REGISTER_USHORT(Register);
+}
+
+ULONG
+DDKAPI
+ScsiPortSetBusDataByOffset(
+    IN PVOID DeviceExtension,
+    IN ULONG BusDataType,
+    IN ULONG SystemIoBusNumber,
+    IN ULONG SlotNumber,
+    IN PVOID Buffer,
+    IN ULONG Offset,
+    IN ULONG Length)
+{
+    // FIXME
+    UNIMPLEMENTED;
+    return 0;
+}
+
+VOID
+DDKAPI
+ScsiPortStallExecution(
+    IN ULONG Delay)
+{
+    KeStallExecutionProcessor(Delay);
+}
+
+BOOLEAN
+DDKAPI
+ScsiPortValidateRange(
+    IN PVOID HwDeviceExtension,
+    IN INTERFACE_TYPE BusType,
+    IN ULONG SystemIoBusNumber,
+    IN SCSI_PHYSICAL_ADDRESS IoAddress,
+    IN ULONG NumberOfBytes,
+    IN BOOLEAN InIoSpace)
+{
+    // FIXME
+    UNIMPLEMENTED;
+    return TRUE;
+}
+
+#if 0
+// ScsiPortWmi*
+#endif
+
+
+VOID
+DDKAPI
+ScsiPortWritePortBufferUchar(
+    IN PUCHAR Port,
+    IN PUCHAR Buffer,
+    IN ULONG Count)
+{
+    __outbytestring(H2I(Port), Buffer, Count);
+}
+
+VOID
+DDKAPI
+ScsiPortWritePortBufferUlong(
+    IN PULONG Port,
+    IN PULONG Buffer,
+    IN ULONG Count)
+{
+    __outdwordstring(H2I(Port), Buffer, Count);
+}
+
+VOID
+DDKAPI
+ScsiPortWritePortBufferUshort(
+    IN PUSHORT Port,
+    IN PUSHORT Buffer,
+    IN ULONG Count)
+{
+    __outwordstring(H2I(Port), Buffer, Count);
+}
+
+VOID
+DDKAPI
+ScsiPortWritePortUchar(
+    IN PUCHAR Port,
+    IN UCHAR Value)
+{
+    WRITE_PORT_UCHAR(Port, Value);
+}
+
+VOID
+DDKAPI
+ScsiPortWritePortUlong(
+    IN PULONG Port,
+    IN ULONG Value)
+{
+    WRITE_PORT_ULONG(Port, Value);
+}
+
+VOID
+DDKAPI
+ScsiPortWritePortUshort(
+    IN PUSHORT Port,
+    IN USHORT Value)
+{
+    WRITE_PORT_USHORT(Port, Value);
+}
+
+VOID
+DDKAPI
+ScsiPortWriteRegisterBufferUchar(
+    IN PUCHAR Register,
+    IN PUCHAR Buffer,
+    IN ULONG Count)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+VOID
+DDKAPI
+ScsiPortWriteRegisterBufferUlong(
+    IN PULONG Register,
+    IN PULONG Buffer,
+    IN ULONG Count)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+VOID
+DDKAPI
+ScsiPortWriteRegisterBufferUshort(
+    IN PUSHORT Register,
+    IN PUSHORT Buffer,
+    IN ULONG Count)
+{
+    // FIXME
+    UNIMPLEMENTED;
+}
+
+VOID
+DDKAPI
+ScsiPortWriteRegisterUchar(
+    IN PUCHAR Register,
+    IN ULONG Value)
+{
+    WRITE_REGISTER_UCHAR(Register, Value);
+}
+
+VOID
+DDKAPI
+ScsiPortWriteRegisterUlong(
+    IN PULONG Register,
+    IN ULONG Value)
+{
+    WRITE_REGISTER_ULONG(Register, Value);
+}
+
+VOID
+DDKAPI
+ScsiPortWriteRegisterUshort(
+    IN PUSHORT Register,
+    IN USHORT Value)
+{
+    WRITE_REGISTER_USHORT(Register, Value);
+}
+
+ULONG
+LoadBootDeviceDriver(VOID)
+{
+    struct
+    {
+        CHAR* Name;
+        PVOID Function;
+    } ExportTable[] = 
+    {
+        { "ScsiDebugPrint", ScsiDebugPrint },
+        { "ScsiPortCompleteRequest", ScsiPortCompleteRequest },
+        { "ScsiPortConvertPhysicalAddressToUlong", ScsiPortConvertPhysicalAddressToUlong },
+        { "ScsiPortConvertUlongToPhysicalAddress", ScsiPortConvertUlongToPhysicalAddress },
+        { "ScsiPortFlushDma", ScsiPortFlushDma },
+        { "ScsiPortFreeDeviceBase", ScsiPortFreeDeviceBase },
+        { "ScsiPortGetBusData", ScsiPortGetBusData },
+        { "ScsiPortGetDeviceBase", ScsiPortGetDeviceBase },
+        { "ScsiPortGetLogicalUnit", ScsiPortGetLogicalUnit },
+        { "ScsiPortGetPhysicalAddress", ScsiPortGetPhysicalAddress },
+        { "ScsiPortGetSrb", ScsiPortGetSrb },
+        { "ScsiPortGetUncachedExtension", ScsiPortGetUncachedExtension },
+        { "ScsiPortGetVirtualAddress", ScsiPortGetVirtualAddress },
+        { "ScsiPortInitialize", ScsiPortInitialize },
+        { "ScsiPortIoMapTransfer", ScsiPortIoMapTransfer },
+        { "ScsiPortLogError", ScsiPortLogError },
+        { "ScsiPortMoveMemory", ScsiPortMoveMemory },
+        { "ScsiPortNotification", ScsiPortNotification },
+        { "ScsiPortReadPortBufferUchar", ScsiPortReadPortBufferUchar },
+        { "ScsiPortReadPortBufferUlong", ScsiPortReadPortBufferUlong },
+        { "ScsiPortReadPortBufferUshort", ScsiPortReadPortBufferUshort },
+        { "ScsiPortReadPortUchar", ScsiPortReadPortUchar },
+        { "ScsiPortReadPortUlong", ScsiPortReadPortUlong },
+        { "ScsiPortReadPortUshort", ScsiPortReadPortUshort },
+        { "ScsiPortReadRegisterBufferUchar", ScsiPortReadRegisterBufferUchar },
+        { "ScsiPortReadRegisterBufferUlong", ScsiPortReadRegisterBufferUlong },
+        { "ScsiPortReadRegisterBufferUshort", ScsiPortReadRegisterBufferUshort },
+        { "ScsiPortReadRegisterUchar", ScsiPortReadRegisterUchar },
+        { "ScsiPortReadRegisterUlong", ScsiPortReadRegisterUlong },
+        { "ScsiPortReadRegisterUshort", ScsiPortReadRegisterUshort },
+        { "ScsiPortSetBusDataByOffset", ScsiPortSetBusDataByOffset },
+        { "ScsiPortStallExecution", ScsiPortStallExecution },
+        { "ScsiPortValidateRange", ScsiPortValidateRange },
+        { "ScsiPortWritePortBufferUchar", ScsiPortWritePortBufferUchar },
+        { "ScsiPortWritePortBufferUlong", ScsiPortWritePortBufferUlong },
+        { "ScsiPortWritePortBufferUshort", ScsiPortWritePortBufferUshort },
+        { "ScsiPortWritePortUchar", ScsiPortWritePortUchar },
+        { "ScsiPortWritePortUlong", ScsiPortWritePortUlong },
+        { "ScsiPortWritePortUshort", ScsiPortWritePortUshort },
+        { "ScsiPortWriteRegisterBufferUchar", ScsiPortWriteRegisterBufferUchar },
+        { "ScsiPortWriteRegisterBufferUlong", ScsiPortWriteRegisterBufferUlong },
+        { "ScsiPortWriteRegisterBufferUshort", ScsiPortWriteRegisterBufferUshort },
+        { "ScsiPortWriteRegisterUchar", ScsiPortWriteRegisterUchar },
+        { "ScsiPortWriteRegisterUlong", ScsiPortWriteRegisterUlong },
+        { "ScsiPortWriteRegisterUshort", ScsiPortWriteRegisterUshort },
+    };
+    IMAGE_DOS_HEADER ImageDosHeader;
+    IMAGE_NT_HEADERS ImageNtHeaders;
+    IMAGE_EXPORT_DIRECTORY ImageExportDirectory;
+    CHAR* TableName[sizeof(ExportTable) / sizeof(ExportTable[0])];
+    USHORT OrdinalTable[sizeof(ExportTable) / sizeof(ExportTable[0])];
+    ULONG FunctionTable[sizeof(ExportTable) / sizeof(ExportTable[0])];
+
+    PIMAGE_NT_HEADERS NtHeaders;
+    LOADER_PARAMETER_BLOCK LoaderBlock;
+    PIMAGE_IMPORT_DESCRIPTOR ImportTable;
+    ULONG ImportTableSize;
+    PLDR_DATA_TABLE_ENTRY BootDdDTE, FreeldrDTE;
+    CHAR NtBootDdPath[MAX_PATH];
+    PVOID ImageBase;
+    ULONG (NTAPI *EntryPoint)(IN PVOID DriverObject, IN PVOID RegistryPath);
+    ULONG i;
+    BOOLEAN Status;
+
+    /* Some initialization of our temporary loader block */
+    RtlZeroMemory(&LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+    InitializeListHead(&LoaderBlock.LoadOrderListHead);
+
+    /* Create our fake executable header for freeldr.sys */
+    RtlZeroMemory(&ImageDosHeader, sizeof(IMAGE_DOS_HEADER));
+    RtlZeroMemory(&ImageNtHeaders, sizeof(IMAGE_NT_HEADERS));
+    RtlZeroMemory(&ImageExportDirectory, sizeof(IMAGE_EXPORT_DIRECTORY));
+    ImageDosHeader.e_magic = SWAPW(IMAGE_DOS_SIGNATURE);
+    ImageDosHeader.e_lfanew = SWAPD((ULONG_PTR)&ImageNtHeaders - (ULONG_PTR)&ImageDosHeader);
+    ImageNtHeaders.Signature = IMAGE_NT_SIGNATURE;
+    ImageNtHeaders.OptionalHeader.NumberOfRvaAndSizes = SWAPD(IMAGE_DIRECTORY_ENTRY_EXPORT + 1);
+    ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = 
+        SWAPW((ULONG_PTR)&ImageExportDirectory - (ULONG_PTR)&ImageDosHeader);
+    ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = 1;
+    ImageExportDirectory.NumberOfNames = sizeof(ExportTable) / sizeof(ExportTable[0]);
+    ImageExportDirectory.AddressOfNames = (ULONG_PTR)TableName - (ULONG_PTR)&ImageDosHeader;
+    ImageExportDirectory.AddressOfNameOrdinals = (ULONG_PTR)OrdinalTable - (ULONG_PTR)&ImageDosHeader;
+    ImageExportDirectory.NumberOfFunctions = sizeof(ExportTable) / sizeof(ExportTable[0]);
+    ImageExportDirectory.AddressOfFunctions = (ULONG_PTR)FunctionTable - (ULONG_PTR)&ImageDosHeader;
+
+    /* Fill freeldr.sys export table */
+    for (i = 0; i < sizeof(ExportTable) / sizeof(ExportTable[0]); i++)
+    {
+        TableName[i] = PaToVa((PVOID)((ULONG_PTR)ExportTable[i].Name - (ULONG_PTR)&ImageDosHeader));
+        OrdinalTable[i] = i;
+        FunctionTable[i] = (ULONG)((ULONG_PTR)ExportTable[i].Function - (ULONG_PTR)&ImageDosHeader);
+    }
+
+    /* Add freeldr.sys to list of loaded executables */
+    RtlZeroMemory(FreeldrDTE, sizeof(LDR_DATA_TABLE_ENTRY));
+    Status = WinLdrAllocateDataTableEntry(&LoaderBlock, "scsiport.sys",
+        "FREELDR.SYS", &ImageDosHeader, &FreeldrDTE);
+    if (!Status)
+        return EIO;
+
+    /* Create full ntbootdd.sys path */
+    MachDiskGetBootPath(NtBootDdPath, sizeof(NtBootDdPath));
+    strcat(NtBootDdPath, "\\NTBOOTDD.SYS");
+
+    /* Load file */
+    Status = WinLdrLoadImage(NtBootDdPath, LoaderBootDriver, &ImageBase);
+    if (!Status)
+    {
+        /* That's OK. File simply doesn't exist */
+        return ESUCCESS;
+    }
+
+    /* Fix imports */
+    Status = WinLdrAllocateDataTableEntry(&LoaderBlock, "ntbootdd.sys",
+        "NTBOOTDD.SYS", ImageBase, &BootDdDTE);
+    if (!Status)
+        return EIO;
+    Status = WinLdrScanImportDescriptorTable(&LoaderBlock, "", BootDdDTE);
+    if (!Status)
+        return EIO;
+
+    /* Change imports to PA */
+    ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(BootDdDTE->DllBase),
+        TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize);
+    for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != 0);ImportTable++)
+    {
+        PIMAGE_THUNK_DATA ThunkData = (PIMAGE_THUNK_DATA)VaToPa(RVA(BootDdDTE->DllBase, ImportTable->FirstThunk));
+
+        while (((PIMAGE_THUNK_DATA)ThunkData)->u1.AddressOfData != 0)
+        {
+            ThunkData->u1.Function = (ULONG)VaToPa((PVOID)ThunkData->u1.Function);
+            ThunkData++;
+        }
+    }
+
+    /* Relocate image to PA */
+    NtHeaders = RtlImageNtHeader(VaToPa(BootDdDTE->DllBase));
+    if (!NtHeaders)
+        return EIO;
+    Status = LdrRelocateImageWithBias(
+        VaToPa(BootDdDTE->DllBase),
+        NtHeaders->OptionalHeader.ImageBase - (ULONG_PTR)BootDdDTE->DllBase,
+        "FreeLdr",
+        TRUE,
+        TRUE, /* in case of conflict still return success */
+        FALSE);
+    if (!Status)
+        return EIO;
+
+    /* Call the entrypoint */
+    EntryPoint = VaToPa(BootDdDTE->EntryPoint);
+    (*EntryPoint)(NULL, NULL);
+
+    return ESUCCESS;
+}
+
+/* EOF */
index 3fa9b47..5761ed9 100644 (file)
@@ -20,6 +20,9 @@
 #include <freeldr.h>
 #include <debug.h>
 
+VOID NTAPI HalpInitializePciStubs(VOID);
+VOID NTAPI HalpInitBusHandler(VOID);
+
 VOID BootMain(LPSTR CmdLine)
 {
        CmdLineParse(CmdLine);
@@ -44,5 +47,7 @@ VOID BootMain(LPSTR CmdLine)
                return;
        }
 
+       HalpInitializePciStubs();
+       HalpInitBusHandler();
        RunLoader();
 }
index 9f42e74..fd3487f 100644 (file)
@@ -22,6 +22,7 @@
                <file>disk.c</file>
                <file>partition.c</file>
                <file>ramdisk.c</file>
+               <file>scsiport.c</file>
        </directory>
        <directory name="fs">
                <file>ext2.c</file>
index d29c31a..daaaa49 100644 (file)
@@ -140,3 +140,5 @@ BOOLEAN     DiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITI
 BOOLEAN        DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
 BOOLEAN        DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
 BOOLEAN        DiskReadBootRecord(ULONG DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord);
+
+ULONG LoadBootDeviceDriver(VOID);
index 0bc48f2..82e23ab 100644 (file)
@@ -73,6 +73,14 @@ VOID ReactOSRunSetupLoader(VOID);
 // ARC Path Functions
 //
 ///////////////////////////////////////////////////////////////////////////////////////
+BOOLEAN
+DissectArcPath2(
+    IN CHAR* ArcPath,
+    OUT ULONG* x,
+    OUT ULONG* y,
+    OUT ULONG* z,
+    OUT ULONG* Partition,
+    OUT ULONG *PathSyntax);
 BOOLEAN DissectArcPath(CHAR *ArcPath, CHAR *BootPath, ULONG* BootDrive, ULONG* BootPartition);
 VOID ConstructArcPath(PCHAR ArcPath, PCHAR SystemFolder, ULONG Disk, ULONG Partition);
 ULONG ConvertArcNameToBiosDriveNumber(PCHAR ArcPath);
index e46022c..3ca69fa 100644 (file)
@@ -104,6 +104,62 @@ BOOLEAN DissectArcPath(CHAR *ArcPath, CHAR *BootPath, ULONG* BootDrive, ULONG* B
        return TRUE;
 }
 
+/* PathSyntax: scsi() = 0, multi() = 1, ramdisk() = 2 */
+BOOLEAN
+DissectArcPath2(
+    IN CHAR* ArcPath,
+    OUT ULONG* x,
+    OUT ULONG* y,
+    OUT ULONG* z,
+    OUT ULONG* Partition,
+    OUT ULONG *PathSyntax)
+{
+    /* Detect ramdisk() */
+    if (_strnicmp(ArcPath, "ramdisk(0)", 10) == 0)
+    {
+        *x = *y = *z = 0;
+        *Partition = 1;
+        *PathSyntax = 2;
+        return TRUE;
+    }
+    /* Detect scsi()disk()rdisk()partition() */
+    else if (sscanf(ArcPath, "scsi(%lu)disk(%lu)rdisk(%lu)partition(%lu)", x, y, z, Partition) == 4)
+    {
+        *PathSyntax = 0;
+        return TRUE;
+    }
+    /* Detect scsi()cdrom()fdisk() */
+    else if (sscanf(ArcPath, "scsi(%lu)cdrom(%lu)fdisk(%lu)", x, y, z) == 3)
+    {
+        *Partition = 0;
+        *PathSyntax = 0;
+        return TRUE;
+    }
+    /* Detect multi()disk()rdisk()partition() */
+    else if (sscanf(ArcPath, "multi(%lu)disk(%lu)rdisk(%lu)partition(%lu)", x, y, z, Partition) == 4)
+    {
+        *PathSyntax = 1;
+        return TRUE;
+    }
+    /* Detect multi()disk()cdrom() */
+    else if (sscanf(ArcPath, "multi(%lu)disk(%lu)cdrom(%lu)", x, y, z) == 3)
+    {
+        *Partition = 1;
+        *PathSyntax = 1;
+        return TRUE;
+    }
+    /* Detect multi()disk()fdisk() */
+    else if (sscanf(ArcPath, "multi(%lu)disk(%lu)fdisk(%lu)", x, y, z) == 3)
+    {
+        *Partition = 1;
+        *PathSyntax = 1;
+        return TRUE;
+    }
+
+    /* Unknown syntax */
+    return FALSE;
+}
+
 VOID ConstructArcPath(PCHAR ArcPath, PCHAR SystemFolder, ULONG Disk, ULONG Partition)
 {
        char    tmp[50];
index 8f5d811..7a87e28 100644 (file)
@@ -277,7 +277,7 @@ WinLdrLoadImage(IN PCHAR FileName,
        Status = ArcOpen(FileName, OpenReadOnly, &FileId);
        if (Status != ESUCCESS)
        {
-               UiMessageBox("Can not open the file");
+               //UiMessageBox("Can not open the file");
                return FALSE;
        }