[ros-diffs] [hpoussin] 46017: [freeldr] Load an additional SCSI driver if present (NTBOOTSYS.SYS on boot partition), to increase number of known storage devices. Works only with very simple miniport drivers.

hpoussin at svn.reactos.org hpoussin at svn.reactos.org
Mon Mar 8 23:04:38 CET 2010


Author: hpoussin
Date: Mon Mar  8 23:04:38 2010
New Revision: 46017

URL: http://svn.reactos.org/svn/reactos?rev=46017&view=rev
Log:
[freeldr] Load an additional SCSI driver if present (NTBOOTSYS.SYS on boot partition), to increase number of known storage devices.
Works only with very simple miniport drivers.

Added:
    trunk/reactos/boot/freeldr/freeldr/disk/scsiport.c   (with props)
Modified:
    trunk/reactos/boot/freeldr/freeldr/bootmgr.c
    trunk/reactos/boot/freeldr/freeldr/freeldr.c
    trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
    trunk/reactos/boot/freeldr/freeldr/include/disk.h
    trunk/reactos/boot/freeldr/freeldr/include/reactos.h
    trunk/reactos/boot/freeldr/freeldr/reactos/arcname.c
    trunk/reactos/boot/freeldr/freeldr/windows/peloader.c

Modified: trunk/reactos/boot/freeldr/freeldr/bootmgr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/bootmgr.c?rev=46017&r1=46016&r2=46017&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/bootmgr.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/bootmgr.c [iso-8859-1] Mon Mar  8 23:04:38 2010
@@ -119,6 +119,12 @@
 		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");

Added: trunk/reactos/boot/freeldr/freeldr/disk/scsiport.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/disk/scsiport.c?rev=46017&view=auto
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/disk/scsiport.c (added)
+++ trunk/reactos/boot/freeldr/freeldr/disk/scsiport.c [iso-8859-1] Mon Mar  8 23:04:38 2010
@@ -1,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 */

Propchange: trunk/reactos/boot/freeldr/freeldr/disk/scsiport.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/boot/freeldr/freeldr/freeldr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/freeldr.c?rev=46017&r1=46016&r2=46017&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/freeldr.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/freeldr.c [iso-8859-1] Mon Mar  8 23:04:38 2010
@@ -19,6 +19,9 @@
 
 #include <freeldr.h>
 #include <debug.h>
+
+VOID NTAPI HalpInitializePciStubs(VOID);
+VOID NTAPI HalpInitBusHandler(VOID);
 
 VOID BootMain(LPSTR CmdLine)
 {
@@ -44,5 +47,7 @@
 		return;
 	}
 
+	HalpInitializePciStubs();
+	HalpInitBusHandler();
 	RunLoader();
 }

Modified: trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild?rev=46017&r1=46016&r2=46017&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild [iso-8859-1] Mon Mar  8 23:04:38 2010
@@ -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>

Modified: trunk/reactos/boot/freeldr/freeldr/include/disk.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/include/disk.h?rev=46017&r1=46016&r2=46017&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/disk.h [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/disk.h [iso-8859-1] Mon Mar  8 23:04:38 2010
@@ -140,3 +140,5 @@
 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);

Modified: trunk/reactos/boot/freeldr/freeldr/include/reactos.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/include/reactos.h?rev=46017&r1=46016&r2=46017&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/reactos.h [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/reactos.h [iso-8859-1] Mon Mar  8 23:04:38 2010
@@ -73,6 +73,14 @@
 // 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);

Modified: trunk/reactos/boot/freeldr/freeldr/reactos/arcname.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/reactos/arcname.c?rev=46017&r1=46016&r2=46017&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/reactos/arcname.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/reactos/arcname.c [iso-8859-1] Mon Mar  8 23:04:38 2010
@@ -104,6 +104,62 @@
 	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];

Modified: trunk/reactos/boot/freeldr/freeldr/windows/peloader.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windows/peloader.c?rev=46017&r1=46016&r2=46017&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/peloader.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/windows/peloader.c [iso-8859-1] Mon Mar  8 23:04:38 2010
@@ -277,7 +277,7 @@
 	Status = ArcOpen(FileName, OpenReadOnly, &FileId);
 	if (Status != ESUCCESS)
 	{
-		UiMessageBox("Can not open the file");
+		//UiMessageBox("Can not open the file");
 		return FALSE;
 	}
 




More information about the Ros-diffs mailing list