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/bootmg... ============================================================================== --- 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/s... ============================================================================== --- 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/freeld... ============================================================================== --- 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/freeld... ============================================================================== --- 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/includ... ============================================================================== --- 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/includ... ============================================================================== --- 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/reacto... ============================================================================== --- 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/window... ============================================================================== --- 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; }