diff --git a/reactos/drivers/storage/atapi/atapi.c b/reactos/drivers/storage/atapi/atapi.c index 7b633a0ad6e..352f9ac72b7 100644 --- a/reactos/drivers/storage/atapi/atapi.c +++ b/reactos/drivers/storage/atapi/atapi.c @@ -1,4 +1,4 @@ -/* $Id: atapi.c,v 1.3 2002/01/14 01:43:02 ekohl Exp $ +/* $Id: atapi.c,v 1.4 2002/01/27 01:24:44 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS ATAPI miniport driver @@ -25,21 +25,46 @@ #include -#define NDEBUG -#include - #include "../include/srb.h" +#include "../include/scsi.h" #include "../include/ntddscsi.h" #include "atapi.h" #include "partitio.h" +#define NDEBUG +#include + #define VERSION "V0.0.1" // ------------------------------------------------------- File Static Data -typedef struct _IDE_CONTROLLER_PARAMETERS +// ATAPI_MINIPORT_EXTENSION +// +// DESCRIPTION: +// Extension to be placed in each port device object +// +// ACCESS: +// Allocated from NON-PAGED POOL +// Available at any IRQL +// + +typedef struct _ATAPI_MINIPORT_EXTENSION +{ + IDE_DRIVE_IDENTIFY DeviceParms[2]; + BOOLEAN DevicePresent[2]; + BOOLEAN DeviceAtapi[2]; +} ATAPI_MINIPORT_EXTENSION, *PATAPI_MINIPORT_EXTENSION; + + +typedef struct _UNIT_EXTENSION +{ + ULONG Dummy; +} UNIT_EXTENSION, *PUNIT_EXTENSION; + + +typedef struct _IDE_CONTROLLER_PARAMETERS { int CommandPortBase; int CommandPortSpan; @@ -76,8 +101,6 @@ static BOOLEAN IDEInitialized = FALSE; #pragma alloc_text(init, DriverEntry) #pragma alloc_text(init, IDECreateController) -#pragma alloc_text(init, IDECreateDevices) -#pragma alloc_text(init, IDECreateDevice) #pragma alloc_text(init, IDEPolledRead) // make the PASSIVE_LEVEL routines pageable, so that they don't @@ -92,64 +115,78 @@ static BOOLEAN IDEInitialized = FALSE; // ---------------------------------------------------- Forward Declarations -static NTSTATUS -AtapiFindControllers(IN PDRIVER_OBJECT DriverObject); +static ULONG STDCALL +AtapiFindCompatiblePciController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again); -static NTSTATUS -AtapiCreateController(IN PDRIVER_OBJECT DriverObject, - IN PIDE_CONTROLLER_PARAMETERS ControllerParams, - IN ULONG ControllerIdx); +static ULONG STDCALL +AtapiFindIsaBusController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again); -static NTSTATUS -AtapiCreatePortDevice(IN PDRIVER_OBJECT DriverObject, - IN PCONTROLLER_OBJECT ControllerObject, - IN ULONG ControllerNumber); +static ULONG STDCALL +AtapiFindNativePciController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again); + +static BOOLEAN STDCALL +AtapiInitialize(IN PVOID DeviceExtension); + +static BOOLEAN STDCALL +AtapiResetBus(IN PVOID DeviceExtension, + IN ULONG PathId); + +static BOOLEAN STDCALL +AtapiStartIo(IN PVOID DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +static BOOLEAN STDCALL +AtapiInterrupt(IN PVOID DeviceExtension); static BOOLEAN -AtapiFindDrives(PIDE_CONTROLLER_EXTENSION ControllerExtension); +AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PPORT_CONFIGURATION_INFORMATION ConfigInfo); + +static BOOLEAN +AtapiIdentifyATADevice(IN ULONG CommandPort, + IN ULONG DriveNum, + OUT PIDE_DRIVE_IDENTIFY DrvParms); + +static BOOLEAN +AtapiIdentifyATAPIDevice(IN ULONG CommandPort, + IN ULONG DriveNum, + OUT PIDE_DRIVE_IDENTIFY DrvParms); + +static BOOLEAN +IDEResetController(IN WORD CommandPort, + IN WORD ControlPort); + +static int +IDEPolledRead(IN WORD Address, + IN BYTE PreComp, + IN BYTE SectorCnt, + IN BYTE SectorNum, + IN BYTE CylinderLow, + IN BYTE CylinderHigh, + IN BYTE DrvHead, + IN BYTE Command, + OUT BYTE *Buffer); -BOOLEAN -AtapiIdentifyATAPIDrive(IN int CommandPort, - IN int DriveNum, - OUT PIDE_DRIVE_IDENTIFY DrvParms); -static BOOLEAN IDEResetController(IN WORD CommandPort, IN WORD ControlPort); -static BOOLEAN IDECreateDevices(IN PDRIVER_OBJECT DriverObject, - IN PCONTROLLER_OBJECT ControllerObject, - IN PIDE_CONTROLLER_EXTENSION ControllerExtension, - IN int DriveIdx, - IN int HarddiskIdx); -static BOOLEAN IDEGetDriveIdentification(IN int CommandPort, - IN int DriveNum, - OUT PIDE_DRIVE_IDENTIFY DrvParms); -static NTSTATUS IDECreateDevice(IN PDRIVER_OBJECT DriverObject, - OUT PDEVICE_OBJECT *DeviceObject, - IN PCONTROLLER_OBJECT ControllerObject, - IN int UnitNumber, - IN ULONG DiskNumber, - IN PIDE_DRIVE_IDENTIFY DrvParms, - IN ULONG PartitionIdx, - IN ULONGLONG Offset, - IN ULONGLONG Size); -static int IDEPolledRead(IN WORD Address, - IN BYTE PreComp, - IN BYTE SectorCnt, - IN BYTE SectorNum , - IN BYTE CylinderLow, - IN BYTE CylinderHigh, - IN BYTE DrvHead, - IN BYTE Command, - OUT BYTE *Buffer); -static NTSTATUS STDCALL IDEDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp); -static NTSTATUS STDCALL IDEDispatchReadWrite(IN PDEVICE_OBJECT pDO, IN PIRP Irp); static NTSTATUS STDCALL -AtapiDispatchScsi(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -static NTSTATUS STDCALL -AtapiDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); +IDEDispatchReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); static VOID STDCALL IDEStartIo(IN PDEVICE_OBJECT DeviceObject, @@ -164,18 +201,30 @@ IDEAllocateController(IN PDEVICE_OBJECT DeviceObject, static BOOLEAN STDCALL IDEStartController(IN OUT PVOID Context); -VOID IDEBeginControllerReset(PIDE_CONTROLLER_EXTENSION ControllerExtension); +VOID +IDEBeginControllerReset(PIDE_CONTROLLER_EXTENSION ControllerExtension); static BOOLEAN STDCALL IDEIsr(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); -static VOID IDEDpcForIsr(IN PKDPC Dpc, - IN PDEVICE_OBJECT DpcDeviceObject, - IN PIRP DpcIrp, - IN PVOID DpcContext); -static VOID IDEFinishOperation(PIDE_CONTROLLER_EXTENSION ControllerExtension); -static VOID STDCALL IDEIoTimer(PDEVICE_OBJECT DeviceObject, PVOID Context); +static VOID +IDEDpcForIsr(IN PKDPC Dpc, + IN PDEVICE_OBJECT DpcDeviceObject, + IN PIRP DpcIrp, + IN PVOID DpcContext); + +static VOID +IDEFinishOperation(PIDE_CONTROLLER_EXTENSION ControllerExtension); + +static VOID STDCALL +IDEIoTimer(PDEVICE_OBJECT DeviceObject, + PVOID Context); + + +static ULONG +AtapiExecuteScsi(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); // ---------------------------------------------------------------- Inlines @@ -236,418 +285,371 @@ IdeFindDrive(int Address, // key // // RETURNS: -// NTSTATUS +// NTSTATUS STDCALL NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { + HW_INITIALIZATION_DATA InitData; NTSTATUS Status; DbgPrint("ATAPI Driver %s\n", VERSION); - DriverObject->MajorFunction[IRP_MJ_CREATE] = IDEDispatchOpenClose; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = IDEDispatchOpenClose; - DriverObject->MajorFunction[IRP_MJ_READ] = IDEDispatchReadWrite; - DriverObject->MajorFunction[IRP_MJ_WRITE] = IDEDispatchReadWrite; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AtapiDispatchDeviceControl; - DriverObject->MajorFunction[IRP_MJ_SCSI] = AtapiDispatchScsi; + /* Initialize data structure */ + RtlZeroMemory(&InitData, + sizeof(HW_INITIALIZATION_DATA)); + InitData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA); + InitData.HwInitialize = AtapiInitialize; + InitData.HwResetBus = AtapiResetBus; + InitData.HwStartIo = AtapiStartIo; + InitData.HwInterrupt = AtapiInterrupt; - Status = AtapiFindControllers(DriverObject); - if (NT_SUCCESS(Status)) - { - IDEInitialized = TRUE; - } + InitData.DeviceExtensionSize = sizeof(ATAPI_MINIPORT_EXTENSION); + InitData.SpecificLuExtensionSize = sizeof(UNIT_EXTENSION); - DPRINT( "Returning from DriverEntry\n" ); - return Status; -} + InitData.MapBuffers = TRUE; + /* Search the PCI bus for compatibility mode ide controllers */ + InitData.HwFindAdapter = AtapiFindCompatiblePciController; + InitData.NumberOfAccessRanges = 2; + InitData.AdapterInterfaceType = PCIBus; -static NTSTATUS -AtapiFindControllers(IN PDRIVER_OBJECT DriverObject) -{ - PCI_COMMON_CONFIG PciConfig; - ULONG Bus; - ULONG Slot; - ULONG Size; - ULONG i; - NTSTATUS ReturnedStatus = STATUS_NO_SUCH_DEVICE; - NTSTATUS Status; - PCONFIGURATION_INFORMATION ConfigInfo; + InitData.VendorId = NULL; + InitData.VendorIdLength = 0; + InitData.DeviceId = NULL; + InitData.DeviceIdLength = 0; - DPRINT1("AtapiFindControllers() called!\n"); + Status = ScsiPortInitialize(DriverObject, + RegistryPath, + &InitData, + NULL); +// if (newStatus < statusToReturn) +// statusToReturn = newStatus; - ConfigInfo = IoGetConfigurationInformation(); - - /* Search PCI busses for IDE controllers */ - for (Bus = 0; Bus < 8; Bus++) - { - for (Slot = 0; Slot < 256; Slot++) - { - Size = ScsiPortGetBusData(NULL, - PCIConfiguration, - Bus, - Slot, - &PciConfig, - sizeof(PCI_COMMON_CONFIG)); - if (Size != 0) - { - if ((PciConfig.BaseClass == 0x01) && - (PciConfig.SubClass == 0x01)) - { - DPRINT1("IDE controller found!\n"); - - DPRINT1("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n", - Bus, - Slot>>3, - Slot & 0x07, - PciConfig.VendorID, - PciConfig.DeviceID); - if ((PciConfig.HeaderType & 0x7FFFFFFF) == 0) - { - DPRINT1(" IPR 0x%X ILR 0x%X\n", - PciConfig.u.type0.InterruptPin, - PciConfig.u.type0.InterruptLine); - } - - if (PciConfig.ProgIf & 0x01) - { - DPRINT1("Primary channel: PCI native mode\n"); - } - else - { - DPRINT1("Primary channel: Compatibility mode\n"); - if (ConfigInfo->AtDiskPrimaryAddressClaimed == FALSE) - { - Status = AtapiCreateController(DriverObject, - &Controllers[0], - ConfigInfo->ScsiPortCount); - if (NT_SUCCESS(Status)) - { - ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE; - ConfigInfo->ScsiPortCount++; - ReturnedStatus = Status; - } - } - else - { - /* - * FIXME: Switch controller to native pci mode - * if it is programmable. - */ - } - } - if (PciConfig.ProgIf & 0x02) - { - DPRINT1("Primary programmable: 1\n"); - } - else - { - DPRINT1("Primary programmable: 0\n"); - } - - if (PciConfig.ProgIf & 0x04) - { - DPRINT1("Secondary channel: PCI native mode\n"); - } - else - { - DPRINT1("Secondary channel: Compatibility mode\n"); - if (ConfigInfo->AtDiskSecondaryAddressClaimed == FALSE) - { - Status = AtapiCreateController(DriverObject, - &Controllers[1], - ConfigInfo->ScsiPortCount); - if (NT_SUCCESS(Status)) - { - ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE; - ConfigInfo->ScsiPortCount++; - ReturnedStatus = Status; - } - } - else - { - /* - * FIXME: Switch controller to native pci mode - * if it is programmable. - */ - } - } - if (PciConfig.ProgIf & 0x08) - { - DPRINT1("Secondary programmable: 1\n"); - } - else - { - DPRINT1("Secondary programmable: 0\n"); - } - - if (PciConfig.ProgIf & 0x80) - { - DPRINT1("Master IDE device: 1\n"); - } - else - { - DPRINT1("Master IDE device: 0\n"); - } - - for (i = 0; i < PCI_TYPE0_ADDRESSES; i++) - { - DPRINT1("BaseAddress: 0x%08X\n", PciConfig.u.type0.BaseAddresses[i]); - } - } + /* Search the ISA bus for ide controllers */ #if 0 - else if ((PciConfig.BaseClass == 0x01) && - (PciConfig.SubClass == 0x80)) - { - /* found other mass storage controller */ - DPRINT1("Found other mass storage controller!\n"); - } + InitData.HwFindAdapter = AtapiFindIsaBusController; + InitData.NumberOfAccessRanges = 2; + InitData.AdapterInterfaceType = Isa; + + InitData.VendorId = NULL; + InitData.VendorIdLength = 0; + InitData.DeviceId = NULL; + InitData.DeviceIdLength = 0; + + Status = ScsiPortInitialize(DriverObject, + RegistryPath, + &InitData, + NULL); +// if (newStatus < statusToReturn) +// statusToReturn = newStatus; #endif - } - } - } - /* Search for ISA IDE controller if no primary controller was found */ - if (ConfigInfo->AtDiskPrimaryAddressClaimed == FALSE) - { - DPRINT1("Searching for primary ISA IDE controller!\n"); + /* Search the PCI bus for native mode ide controllers */ +#if 0 + InitData.HwFindAdapter = AtapiFindNativePciController; + InitData.NumberOfAccessRanges = 2; + InitData.AdapterInterfaceType = PCIBus; - if (IDEResetController(Controllers[0].CommandPortBase, - Controllers[0].ControlPortBase)) - { - Status = AtapiCreateController(DriverObject, - &Controllers[0], - ConfigInfo->ScsiPortCount); - if (NT_SUCCESS(Status)) - { - DPRINT1(" Found primary ISA IDE controller!\n"); - ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE; - ConfigInfo->ScsiPortCount++; - ReturnedStatus = Status; - } - } - } + InitData.VendorId = NULL; + InitData.VendorIdLength = 0; + InitData.DeviceId = NULL; + InitData.DeviceIdLength = 0; - if (ConfigInfo->AtDiskSecondaryAddressClaimed == FALSE) - { - DPRINT1("Searching for secondary ISA IDE controller!\n"); + Status = ScsiPortInitialize(DriverObject, + RegistryPath, + &InitData, + (PVOID)i); +// if (newStatus < statusToReturn) +// statusToReturn = newStatus; +#endif - if (IDEResetController(Controllers[1].CommandPortBase, - Controllers[1].ControlPortBase)) - { - Status = AtapiCreateController(DriverObject, - &Controllers[1], - ConfigInfo->ScsiPortCount); - if (NT_SUCCESS(Status)) - { - DPRINT1(" Found secondary ISA IDE controller!\n"); - ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE; - ConfigInfo->ScsiPortCount++; - ReturnedStatus = Status; - } - } - } - - DPRINT1("AtapiFindControllers() done!\n"); -//for(;;); - return(ReturnedStatus); -} - - -// ---------------------------------------------------- Discardable statics - -// IDECreateController -// -// DESCRIPTION: -// Creates a controller object and a device object for each valid -// device on the controller -// -// RUN LEVEL: -// PASSIVE LEVEL -// -// ARGUMENTS: -// IN PDRIVER_OBJECT DriverObject The system created driver object -// IN PIDE_CONTROLLER_PARAMETERS The parameter block for this -// ControllerParams controller -// IN ULONG ControllerIdx The index of this controller -// -// RETURNS: -// TRUE Devices where found on this controller -// FALSE The controller does not respond or there are no devices on it -// - -static NTSTATUS -AtapiCreateController(IN PDRIVER_OBJECT DriverObject, - IN PIDE_CONTROLLER_PARAMETERS ControllerParams, - IN ULONG ControllerIdx) -{ - BOOLEAN CreatedDevices, ThisDriveExists; - int DriveIdx; - NTSTATUS Status; - PCONTROLLER_OBJECT ControllerObject; - PIDE_CONTROLLER_EXTENSION ControllerExtension; - - ControllerObject = IoCreateController(sizeof(IDE_CONTROLLER_EXTENSION)); - if (ControllerObject == NULL) - { - DbgPrint ("Could not create controller object for controller %d\n", - ControllerIdx); - return(STATUS_NO_SUCH_DEVICE); - } - - /* Fill out Controller extension data */ - ControllerExtension = (PIDE_CONTROLLER_EXTENSION) - ControllerObject->ControllerExtension; - ControllerExtension->Number = ControllerIdx; - ControllerExtension->CommandPortBase = ControllerParams->CommandPortBase; - ControllerExtension->ControlPortBase = ControllerParams->ControlPortBase; - ControllerExtension->Vector = ControllerParams->Vector; - ControllerExtension->DMASupported = FALSE; - ControllerExtension->ControllerInterruptBug = FALSE; - ControllerExtension->OperationInProgress = FALSE; - - /* Initialize the spin lock in the controller extension */ - KeInitializeSpinLock(&ControllerExtension->SpinLock); - - /* Register an interrupt handler for this controller */ - Status = IoConnectInterrupt(&ControllerExtension->Interrupt, - IDEIsr, - ControllerExtension, - &ControllerExtension->SpinLock, - ControllerExtension->Vector, - ControllerParams->IrqL, - ControllerParams->SynchronizeIrqL, - ControllerParams->InterruptMode, - FALSE, - ControllerParams->Affinity, - FALSE); - if (!NT_SUCCESS(Status)) - { - DbgPrint ("Could not Connect Interrupt %d\n", - ControllerExtension->Vector); - IoDeleteController (ControllerObject); - return(Status); - } - - Status = AtapiCreatePortDevice(DriverObject, - ControllerObject, - ControllerIdx); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Could not create port device %d\n", - ControllerIdx); - IoDisconnectInterrupt(ControllerExtension->Interrupt); - IoDeleteController(ControllerObject); - return(Status); - } - -// AtapiFindDrives(ControllerExtension); - - return(STATUS_SUCCESS); -} - - -static NTSTATUS -AtapiCreatePortDevice(IN PDRIVER_OBJECT DriverObject, - IN PCONTROLLER_OBJECT ControllerObject, - IN ULONG ControllerNumber) -{ - PATAPI_PORT_EXTENSION DeviceExtension; - PDEVICE_OBJECT PortDeviceObject; - WCHAR NameBuffer[IDE_MAX_NAME_LENGTH]; - UNICODE_STRING DeviceName; - NTSTATUS Status; - PIDE_CONTROLLER_EXTENSION ControllerExtension; - - /* Create a unicode device name */ - swprintf(NameBuffer, - L"\\Device\\ScsiPort%lu", - ControllerNumber); - RtlInitUnicodeString(&DeviceName, - NameBuffer); - - DPRINT1("Creating device: %wZ\n", &DeviceName); - - /* Create the port device */ - Status = IoCreateDevice(DriverObject, - sizeof(ATAPI_PORT_EXTENSION), - &DeviceName, - FILE_DEVICE_CONTROLLER, - 0, - TRUE, - &PortDeviceObject); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IoCreateDevice call failed! (Status 0x%lX)\n", Status); -// DbgPrint("IoCreateDevice call failed\n"); - return(Status); - } - DPRINT1("Created device: %wZ\n", &DeviceName); - - /* Set the buffering strategy here... */ - PortDeviceObject->Flags |= DO_DIRECT_IO; - PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; - - /* Fill out Device extension data */ - DeviceExtension = (PATAPI_PORT_EXTENSION)PortDeviceObject->DeviceExtension; - DeviceExtension->DeviceObject = PortDeviceObject; - DeviceExtension->ControllerObject = ControllerObject; - DeviceExtension->PortNumber = ControllerNumber; - - - /* Initialize the DPC object here */ - IoInitializeDpcRequest(PortDeviceObject, - IDEDpcForIsr); - - /* - * Initialize the controller timer here - * (since it has to be tied to a device) - */ - ControllerExtension = (PIDE_CONTROLLER_EXTENSION) - ControllerObject->ControllerExtension; - ControllerExtension->TimerState = IDETimerIdle; - ControllerExtension->TimerCount = 0; - ControllerExtension->TimerDevice = PortDeviceObject; - IoInitializeTimer(PortDeviceObject, - IDEIoTimer, - ControllerExtension); + DPRINT1( "Returning from DriverEntry\n" ); return(Status); } -static BOOLEAN -AtapiFindDrives(PIDE_CONTROLLER_EXTENSION ControllerExtension) +static ULONG STDCALL +AtapiFindCompatiblePciController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again) { - ULONG DriveIndex; + PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciConfig; + ULONG DataSize; + ULONG FunctionNumber; + BOOLEAN ChannelFound; + BOOLEAN DeviceFound; + + DPRINT("AtapiFindCompatiblePciController() Bus: %lu Slot: %lu\n", + ConfigInfo->SystemIoBusNumber, + ConfigInfo->SlotNumber); + + *Again = FALSE; + + /* both channels were claimed: exit */ + if (ConfigInfo->AtdiskPrimaryClaimed == TRUE && + ConfigInfo->AtdiskSecondaryClaimed == TRUE) + return(SP_RETURN_NOT_FOUND); + + + SlotNumber.u.AsULONG = 0; + for (FunctionNumber = 0 /*ConfigInfo->SlotNumber*/; FunctionNumber < 256; FunctionNumber++) + { +// SlotNumber.u.bits.FunctionNumber = FunctionNumber; +// SlotNumber.u.AsULONG = (FunctionNumber & 0x07); + SlotNumber.u.AsULONG = FunctionNumber; + + ChannelFound = FALSE; + DeviceFound = FALSE; + + DataSize = ScsiPortGetBusData(DeviceExtension, + PCIConfiguration, + 0, + SlotNumber.u.AsULONG, + &PciConfig, + sizeof(PCI_COMMON_CONFIG)); +// if (DataSize != sizeof(PCI_COMMON_CONFIG) || +// PciConfig.VendorID == PCI_INVALID_VENDORID) + if (DataSize == 0) + { +// if ((SlotNumber.u.AsULONG & 0x07) == 0) +// return(SP_RETURN_ERROR); /* No bus found */ + + continue; +// return(SP_RETURN_ERROR); + } + + if (PciConfig.BaseClass == 0x01 && + PciConfig.SubClass == 0x01) // && +// (PciConfig.ProgIf & 0x05) == 0) + { + /* both channels are in compatibility mode */ + DPRINT1("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n", + ConfigInfo->SystemIoBusNumber, +// SlotNumber.u.AsULONG >> 3, +// SlotNumber.u.AsULONG & 0x07, + SlotNumber.u.bits.DeviceNumber, + SlotNumber.u.bits.FunctionNumber, + PciConfig.VendorID, + PciConfig.DeviceID); + DPRINT("ProgIF 0x%02hx\n", PciConfig.ProgIf); + + DPRINT1("Found IDE controller in compatibility mode!\n"); + + ConfigInfo->NumberOfBuses = 1; + ConfigInfo->MaximumNumberOfTargets = 2; + ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */ + + if (ConfigInfo->AtdiskPrimaryClaimed == FALSE) + { + /* both channels unclaimed: claim primary channel */ + DPRINT1("Primary channel!\n"); + + ConfigInfo->BusInterruptLevel = 14; + ConfigInfo->InterruptMode = LevelSensitive; + + ConfigInfo->AccessRanges[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x01F0); + ConfigInfo->AccessRanges[0].RangeLength = 8; + ConfigInfo->AccessRanges[0].RangeInMemory = FALSE; + + ConfigInfo->AccessRanges[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x03F6); + ConfigInfo->AccessRanges[1].RangeLength = 1; + ConfigInfo->AccessRanges[1].RangeInMemory = FALSE; + + ConfigInfo->AtdiskPrimaryClaimed = TRUE; + ChannelFound = TRUE; + *Again = TRUE; + } + else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE) + { + /* primary channel claimed: claim secondary channel */ + DPRINT1("Secondary channel!\n"); + + ConfigInfo->BusInterruptLevel = 15; + ConfigInfo->InterruptMode = LevelSensitive; + + ConfigInfo->AccessRanges[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x0170); + ConfigInfo->AccessRanges[0].RangeLength = 8; + ConfigInfo->AccessRanges[0].RangeInMemory = FALSE; + + ConfigInfo->AccessRanges[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x0376); + ConfigInfo->AccessRanges[1].RangeLength = 1; + ConfigInfo->AccessRanges[1].RangeInMemory = FALSE; + + ConfigInfo->AtdiskSecondaryClaimed = TRUE; + ChannelFound = TRUE; + *Again = FALSE; + } + + /* Find attached devices */ + if (ChannelFound == TRUE) + { + DeviceFound = AtapiFindDevices(DevExt, + ConfigInfo); + } + DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_FOUND\n"); + return(SP_RETURN_FOUND); + } + } + + DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_NOT_FOUND\n"); + + return(SP_RETURN_NOT_FOUND); +} + + +static ULONG STDCALL +AtapiFindIsaBusController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again) +{ + PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + + DPRINT("AtapiFindIsaBusController() called!\n"); + + *Again = FALSE; + + if (ConfigInfo->AtdiskPrimaryClaimed == TRUE) + { + DPRINT("Primary IDE controller already claimed!\n"); + + } + + if (ConfigInfo->AtdiskSecondaryClaimed == TRUE) + { + DPRINT("Secondary IDE controller already claimed!\n"); + + } + + DPRINT("AtapiFindIsaBusController() done!\n"); + + return(SP_RETURN_NOT_FOUND); +} + + +static ULONG STDCALL +AtapiFindNativePciController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again) +{ + PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + + DPRINT("AtapiFindNativePciController() called!\n"); + + *Again = FALSE; + + DPRINT("AtapiFindNativePciController() done!\n"); + + return(SP_RETURN_NOT_FOUND); +} + + +static BOOLEAN STDCALL +AtapiInitialize(IN PVOID DeviceExtension) +{ + return(TRUE); +} + + +static BOOLEAN STDCALL +AtapiResetBus(IN PVOID DeviceExtension, + IN ULONG PathId) +{ + return(TRUE); +} + + +static BOOLEAN STDCALL +AtapiStartIo(IN PVOID DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb) +{ + PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + ULONG Result; + + DPRINT1("AtapiStartIo() called\n"); + + switch (Srb->Function) + { + case SRB_FUNCTION_EXECUTE_SCSI: + + Result = AtapiExecuteScsi(DevExt, + Srb); + + break; + + } + + Srb->SrbStatus = Result; + + return(TRUE); +} + + +static BOOLEAN STDCALL +AtapiInterrupt(IN PVOID DeviceExtension) +{ + return(TRUE); +} + + + + + + +// ---------------------------------------------------- Discardable statics + + +static BOOLEAN +AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PPORT_CONFIGURATION_INFORMATION ConfigInfo) +{ + BOOLEAN DeviceFound = FALSE; + ULONG CommandPortBase; + ULONG UnitNumber; ULONG Retries; BYTE High, Low; - IDE_DRIVE_IDENTIFY DrvParms; - DPRINT1("AtapiFindDrives() called\n"); + DPRINT("AtapiFindDevices() called\n"); - for (DriveIndex = 0; DriveIndex < 2; DriveIndex++) +// CommandPortBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart); + CommandPortBase = ScsiPortConvertPhysicalAddressToUlong(ConfigInfo->AccessRanges[0].RangeStart); + + DPRINT(" CommandPortBase: %x\n", CommandPortBase); + + for (UnitNumber = 0; UnitNumber < 2; UnitNumber++) { /* disable interrupts */ - IDEWriteDriveControl(ControllerExtension->ControlPortBase, IDE_DC_nIEN); + IDEWriteDriveControl(CommandPortBase, + IDE_DC_nIEN); /* select drive */ - IDEWriteDriveHead(ControllerExtension->CommandPortBase, - IDE_DH_FIXED | (DriveIndex ? IDE_DH_DRV1 : 0)); + IDEWriteDriveHead(CommandPortBase, + IDE_DH_FIXED | (UnitNumber ? IDE_DH_DRV1 : 0)); ScsiPortStallExecution(500); - IDEWriteCylinderHigh(ControllerExtension->CommandPortBase, 0); - IDEWriteCylinderLow(ControllerExtension->CommandPortBase, 0); - IDEWriteCommand(ControllerExtension->CommandPortBase, 0x08); /* IDE_COMMAND_ATAPI_RESET */ + IDEWriteCylinderHigh(CommandPortBase, 0); + IDEWriteCylinderLow(CommandPortBase, 0); + IDEWriteCommand(CommandPortBase, 0x08); /* IDE_COMMAND_ATAPI_RESET */ // ScsiPortStallExecution(1000*1000); -// IDEWriteDriveHead(ControllerExtension->CommandPortBase, -// IDE_DH_FIXED | (DriveIndex ? IDE_DH_DRV1 : 0)); +// IDEWriteDriveHead(CommandPortBase, +// IDE_DH_FIXED | (UnitNumber ? IDE_DH_DRV1 : 0)); // IDE_DH_FIXED); for (Retries = 0; Retries < 20000; Retries++) { - if (!(IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_BUSY)) + if (!(IDEReadStatus(CommandPortBase) & IDE_SR_BUSY)) { break; } @@ -655,47 +657,55 @@ AtapiFindDrives(PIDE_CONTROLLER_EXTENSION ControllerExtension) } if (Retries >= IDE_RESET_BUSY_TIMEOUT * 1000) { - DPRINT1("Timeout on drive %lu\n", DriveIndex); -// return FALSE; + DbgPrint("Timeout on drive %lu\n", UnitNumber); + return(DeviceFound); } - High = IDEReadCylinderHigh(ControllerExtension->CommandPortBase); - Low = IDEReadCylinderLow(ControllerExtension->CommandPortBase); + High = IDEReadCylinderHigh(CommandPortBase); + Low = IDEReadCylinderLow(CommandPortBase); + + DPRINT(" Check drive %lu: High 0x%x Low 0x%x\n", + UnitNumber, + High, + Low); - DPRINT1("Check drive %lu: High 0x%lx Low 0x%lx\n", DriveIndex, High, Low); if (High == 0xEB && Low == 0x14) { -// DPRINT1("ATAPI drive found!\n"); - if (!AtapiIdentifyATAPIDrive(ControllerExtension->CommandPortBase, DriveIndex, &DrvParms)) + if (AtapiIdentifyATAPIDevice(CommandPortBase, + UnitNumber, + &DeviceExtension->DeviceParms[UnitNumber])) { - DPRINT1("No drive found!\n"); + DPRINT(" ATAPI drive found!\n"); + DeviceExtension->DevicePresent[UnitNumber] = TRUE; + DeviceExtension->DeviceAtapi[UnitNumber] = TRUE; + DeviceFound = TRUE; } else { - DPRINT1("ATAPI drive found!\n"); + DPRINT(" No ATAPI drive found!\n"); } } else { - - if (!IDEGetDriveIdentification(ControllerExtension->CommandPortBase, DriveIndex, &DrvParms)) + if (AtapiIdentifyATADevice(CommandPortBase, + UnitNumber, + &DeviceExtension->DeviceParms[UnitNumber])) { - DPRINT1("No drive found!\n"); -// DPRINT1("Giving up on drive %d on controller %d...\n", -// DriveIndex, -// ControllerExtension->CommandPortBase); -// return FALSE; + DPRINT(" IDE drive found!\n"); + DeviceExtension->DevicePresent[UnitNumber] = TRUE; + DeviceExtension->DeviceAtapi[UnitNumber] = FALSE; + DeviceFound = TRUE; } else { - DPRINT1("IDE drive found!\n"); + DPRINT(" No IDE drive found!\n"); } - - } - } - return TRUE; + + DPRINT("AtapiFindDrives() done\n"); + + return(DeviceFound); } @@ -714,225 +724,46 @@ AtapiFindDrives(PIDE_CONTROLLER_EXTENSION ControllerExtension) // RETURNS: // -BOOLEAN -IDEResetController(IN WORD CommandPort, - IN WORD ControlPort) +static BOOLEAN +IDEResetController(IN WORD CommandPort, + IN WORD ControlPort) { - int Retries; + int Retries; - // Assert drive reset line + /* Assert drive reset line */ IDEWriteDriveControl(ControlPort, IDE_DC_SRST); - // Wait for min. 25 microseconds + /* Wait for min. 25 microseconds */ ScsiPortStallExecution(IDE_RESET_PULSE_LENGTH); - // Negate drive reset line + /* Negate drive reset line */ IDEWriteDriveControl(ControlPort, 0); - // Wait for BUSY negation + /* Wait for BUSY negation */ for (Retries = 0; Retries < IDE_RESET_BUSY_TIMEOUT * 1000; Retries++) { if (!(IDEReadStatus(CommandPort) & IDE_SR_BUSY)) - { - break; - } + { + break; + } ScsiPortStallExecution(10); } - CHECKPOINT; + + CHECKPOINT; if (Retries >= IDE_RESET_BUSY_TIMEOUT * 1000) { - return FALSE; + return(FALSE); } - CHECKPOINT; + + CHECKPOINT; + // return TRUE if controller came back to life. and // the registers are initialized correctly - return IDEReadError(CommandPort) == 1; + return(IDEReadError(CommandPort) == 1); } -// IDECreateDevices -// -// DESCRIPTION: -// Create the raw device and any partition devices on this drive -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// IN PDRIVER_OBJECT DriverObject The system created driver object -// IN PCONTROLLER_OBJECT ControllerObject -// IN PIDE_CONTROLLER_EXTENSION ControllerExtension -// The IDE controller extension for -// this device -// IN int DriveIdx The index of the drive on this -// controller -// IN int HarddiskIdx The NT device number for this -// drive -// -// RETURNS: -// TRUE Drive exists and devices were created -// FALSE no devices were created for this device -// -BOOLEAN -IDECreateDevices(IN PDRIVER_OBJECT DriverObject, - IN PCONTROLLER_OBJECT ControllerObject, - IN PIDE_CONTROLLER_EXTENSION ControllerExtension, - IN int DriveIdx, - IN int HarddiskIdx) -{ - WCHAR NameBuffer[IDE_MAX_NAME_LENGTH]; - int CommandPort; - NTSTATUS Status; - IDE_DRIVE_IDENTIFY DrvParms; - PDEVICE_OBJECT DiskDeviceObject; - PDEVICE_OBJECT PartitionDeviceObject; - PIDE_DEVICE_EXTENSION DiskDeviceExtension; - PIDE_DEVICE_EXTENSION PartitionDeviceExtension; - UNICODE_STRING UnicodeDeviceDirName; - OBJECT_ATTRIBUTES DeviceDirAttributes; - HANDLE Handle; - ULONG SectorCount = 0; - PDRIVE_LAYOUT_INFORMATION PartitionList = NULL; - PPARTITION_INFORMATION PartitionEntry; - ULONG i; - - // Copy I/O port offsets for convenience - CommandPort = ControllerExtension->CommandPortBase; -// ControlPort = ControllerExtension->ControlPortBase; - DPRINT("probing IDE controller %d Addr %04lx Drive %d\n", - ControllerExtension->Number, - CommandPort, - DriveIdx); - - /* Get the Drive Identification Data */ - if (!IDEGetDriveIdentification(CommandPort, DriveIdx, &DrvParms)) - { - DPRINT("Giving up on drive %d on controller %d...\n", - DriveIdx, - ControllerExtension->Number); - return FALSE; - } - - /* Create the harddisk device directory */ - swprintf (NameBuffer, - L"\\Device\\Harddisk%d", - HarddiskIdx); - RtlInitUnicodeString(&UnicodeDeviceDirName, - NameBuffer); - InitializeObjectAttributes(&DeviceDirAttributes, - &UnicodeDeviceDirName, - 0, - NULL, - NULL); - Status = ZwCreateDirectoryObject(&Handle, 0, &DeviceDirAttributes); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Could not create device dir object\n"); - return FALSE; - } - - /* Create the disk device */ - if (DrvParms.Capabilities & IDE_DRID_LBA_SUPPORTED) - { - SectorCount = - (ULONG)((DrvParms.TMSectorCountHi << 16) + DrvParms.TMSectorCountLo); - } - else - { - SectorCount = - (ULONG)(DrvParms.LogicalCyls * DrvParms.LogicalHeads * DrvParms.SectorsPerTrack); - } - DPRINT("SectorCount %lu\n", SectorCount); - - Status = IDECreateDevice(DriverObject, - &DiskDeviceObject, - ControllerObject, - DriveIdx, - HarddiskIdx, - &DrvParms, - 0, - 0, - SectorCount); - if (!NT_SUCCESS(Status)) - { - DbgPrint("IDECreateDevice call failed for raw device\n"); - return FALSE; - } - - /* Increase number of available physical disk drives */ - IoGetConfigurationInformation()->DiskCount++; - - DiskDeviceExtension = (PIDE_DEVICE_EXTENSION)DiskDeviceObject->DeviceExtension; - DiskDeviceExtension->DiskExtension = (PVOID)DiskDeviceExtension; - - /* - * Initialize the controller timer here - * (since it has to be tied to a device) - */ - if (DriveIdx == 0) - { - ControllerExtension->TimerState = IDETimerIdle; - ControllerExtension->TimerCount = 0; - ControllerExtension->TimerDevice = DiskDeviceObject; - IoInitializeTimer(DiskDeviceObject, - IDEIoTimer, - ControllerExtension); - } - - DPRINT("DrvParms.BytesPerSector %ld\n",DrvParms.BytesPerSector); - - /* Read partition table */ - Status = IoReadPartitionTable(DiskDeviceObject, - DrvParms.BytesPerSector, - TRUE, - &PartitionList); - if (!NT_SUCCESS(Status)) - { - DbgPrint("IoReadPartitionTable() failed\n"); - return FALSE; - } - - DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount); - for (i=0;i < PartitionList->PartitionCount; i++) - { - PartitionEntry = &PartitionList->PartitionEntry[i]; - - DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n", - i, - PartitionEntry->PartitionNumber, - PartitionEntry->BootIndicator, - PartitionEntry->PartitionType, - PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/, - PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/); - - /* Create device for partition */ - Status = IDECreateDevice(DriverObject, - &PartitionDeviceObject, - ControllerObject, - DriveIdx, - HarddiskIdx, - &DrvParms, - PartitionEntry->PartitionNumber, - PartitionEntry->StartingOffset.QuadPart / 512 /* DrvParms.BytesPerSector*/, - PartitionEntry->PartitionLength.QuadPart / 512 /*DrvParms.BytesPerSector*/); - if (!NT_SUCCESS(Status)) - { - DbgPrint("IDECreateDevice() failed\n"); - break; - } - - /* Initialize pointer to disk device extension */ - PartitionDeviceExtension = (PIDE_DEVICE_EXTENSION)PartitionDeviceObject->DeviceExtension; - PartitionDeviceExtension->DiskExtension = (PVOID)DiskDeviceExtension; - } - - if (PartitionList != NULL) - ExFreePool(PartitionList); - - return TRUE; -} - -// IDEGetDriveIdentification +// AtapiIdentifyATADevice // // DESCRIPTION: // Get the identification block from the drive @@ -949,20 +780,76 @@ IDECreateDevices(IN PDRIVER_OBJECT DriverObject, // TRUE The drive identification block was retrieved successfully // -BOOLEAN -IDEGetDriveIdentification(IN int CommandPort, - IN int DriveNum, - OUT PIDE_DRIVE_IDENTIFY DrvParms) +static BOOLEAN +AtapiIdentifyATADevice(IN ULONG CommandPort, + IN ULONG DriveNum, + OUT PIDE_DRIVE_IDENTIFY DrvParms) { - - // Get the Drive Identify block from drive or die - if (IDEPolledRead(CommandPort, 0, 0, 0, 0, 0, (DriveNum ? IDE_DH_DRV1 : 0), - IDE_CMD_IDENT_DRV, (BYTE *)DrvParms) != 0) + /* Get the Drive Identify block from drive or die */ + if (IDEPolledRead((WORD)CommandPort, 0, 1, 0, 0, 0, (DriveNum ? IDE_DH_DRV1 : 0), + IDE_CMD_IDENT_ATA_DRV, (BYTE *)DrvParms) != 0) { return FALSE; } - // Report on drive parameters if debug mode + /* Report on drive parameters if debug mode */ + IDESwapBytePairs(DrvParms->SerialNumber, 20); + IDESwapBytePairs(DrvParms->FirmwareRev, 8); + IDESwapBytePairs(DrvParms->ModelNumber, 40); + DPRINT("Config:%04x Cyls:%5d Heads:%2d Sectors/Track:%3d Gaps:%02d %02d\n", + DrvParms->ConfigBits, + DrvParms->LogicalCyls, + DrvParms->LogicalHeads, + DrvParms->SectorsPerTrack, + DrvParms->InterSectorGap, + DrvParms->InterSectorGapSize); + DPRINT("Bytes/PLO:%3d Vendor Cnt:%2d Serial number:[%.20s]\n", + DrvParms->BytesInPLO, + DrvParms->VendorUniqueCnt, + DrvParms->SerialNumber); + DPRINT("Cntlr type:%2d BufSiz:%5d ECC bytes:%3d Firmware Rev:[%.8s]\n", + DrvParms->ControllerType, + DrvParms->BufferSize * IDE_SECTOR_BUF_SZ, + DrvParms->ECCByteCnt, + DrvParms->FirmwareRev); + DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber); + DPRINT("RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n", + (DrvParms->RWMultImplemented) & 0xff, + (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0, + (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0, + DrvParms->MinPIOTransTime, + DrvParms->MinDMATransTime); + DPRINT("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%ld\n", + DrvParms->TMCylinders, + DrvParms->TMHeads, + DrvParms->TMSectorsPerTrk, + (ULONG)(DrvParms->TMCapacityLo + (DrvParms->TMCapacityHi << 16))); + DPRINT("TM:SectorCount: 0x%04x%04x = %lu\n", + DrvParms->TMSectorCountHi, + DrvParms->TMSectorCountLo, + (ULONG)((DrvParms->TMSectorCountHi << 16) + DrvParms->TMSectorCountLo)); + + DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector); + if (DrvParms->BytesPerSector == 0) + DrvParms->BytesPerSector = 512; /* FIXME !!!*/ + return TRUE; +} + + +static BOOLEAN +AtapiIdentifyATAPIDevice(IN ULONG CommandPort, + IN ULONG DriveNum, + OUT PIDE_DRIVE_IDENTIFY DrvParms) +{ + /* Get the Drive Identify block from drive or die */ + if (IDEPolledRead((WORD)CommandPort, 0, 1, 0, 0, 0, (DriveNum ? IDE_DH_DRV1 : 0), + IDE_CMD_IDENT_ATAPI_DRV, (BYTE *)DrvParms) != 0) /* atapi_identify */ + { + DPRINT1("IDEPolledRead() failed\n"); + return FALSE; + } + + /* Report on drive parameters if debug mode */ IDESwapBytePairs(DrvParms->SerialNumber, 20); IDESwapBytePairs(DrvParms->FirmwareRev, 8); IDESwapBytePairs(DrvParms->ModelNumber, 40); @@ -999,193 +886,12 @@ IDEGetDriveIdentification(IN int CommandPort, DrvParms->TMSectorCountLo, (ULONG)((DrvParms->TMSectorCountHi << 16) + DrvParms->TMSectorCountLo)); - DPRINT1("BytesPerSector %d\n", DrvParms->BytesPerSector); - if (DrvParms->BytesPerSector == 0) - DrvParms->BytesPerSector = 512; /* FIXME !!!*/ - return TRUE; -} - - -BOOLEAN -AtapiIdentifyATAPIDrive(IN int CommandPort, - IN int DriveNum, - OUT PIDE_DRIVE_IDENTIFY DrvParms) -{ - - // Get the Drive Identify block from drive or die - if (IDEPolledRead(CommandPort, 0, 0, 0, 0, 0, (DriveNum ? IDE_DH_DRV1 : 0), - 0xA1 /*IDE_CMD_IDENT_DRV*/, (BYTE *)DrvParms) != 0) /* atapi_identify */ - { - DPRINT1("IDEPolledRead() failed\n"); - return FALSE; - } - - // Report on drive parameters if debug mode - IDESwapBytePairs(DrvParms->SerialNumber, 20); - IDESwapBytePairs(DrvParms->FirmwareRev, 8); - IDESwapBytePairs(DrvParms->ModelNumber, 40); - DPRINT1("Config:%04x Cyls:%5d Heads:%2d Sectors/Track:%3d Gaps:%02d %02d\n", - DrvParms->ConfigBits, - DrvParms->LogicalCyls, - DrvParms->LogicalHeads, - DrvParms->SectorsPerTrack, - DrvParms->InterSectorGap, - DrvParms->InterSectorGapSize); - DPRINT1("Bytes/PLO:%3d Vendor Cnt:%2d Serial number:[%.20s]\n", - DrvParms->BytesInPLO, - DrvParms->VendorUniqueCnt, - DrvParms->SerialNumber); - DPRINT1("Cntlr type:%2d BufSiz:%5d ECC bytes:%3d Firmware Rev:[%.8s]\n", - DrvParms->ControllerType, - DrvParms->BufferSize * IDE_SECTOR_BUF_SZ, - DrvParms->ECCByteCnt, - DrvParms->FirmwareRev); - DPRINT1("Model:[%.40s]\n", DrvParms->ModelNumber); - DPRINT1("RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n", - (DrvParms->RWMultImplemented) & 0xff, - (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0, - (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0, - DrvParms->MinPIOTransTime, - DrvParms->MinDMATransTime); - DPRINT1("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%ld\n", - DrvParms->TMCylinders, - DrvParms->TMHeads, - DrvParms->TMSectorsPerTrk, - (ULONG)(DrvParms->TMCapacityLo + (DrvParms->TMCapacityHi << 16))); - DPRINT1("TM:SectorCount: 0x%04x%04x = %lu\n", - DrvParms->TMSectorCountHi, - DrvParms->TMSectorCountLo, - (ULONG)((DrvParms->TMSectorCountHi << 16) + DrvParms->TMSectorCountLo)); - - DPRINT1("BytesPerSector %d\n", DrvParms->BytesPerSector); + DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector); // DrvParms->BytesPerSector = 512; /* FIXME !!!*/ return TRUE; } -// IDECreateDevice -// -// DESCRIPTION: -// Creates a device by calling IoCreateDevice and a sylbolic link for Win32 -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// IN PDRIVER_OBJECT DriverObject The system supplied driver object -// OUT PDEVICE_OBJECT *DeviceObject The created device object -// IN PCONTROLLER_OBJECT ControllerObject The Controller for the device -// IN BOOLEAN LBASupported Does the drive support LBA addressing? -// IN BOOLEAN DMASupported Does the drive support DMA? -// IN int SectorsPerLogCyl Sectors per cylinder -// IN int SectorsPerLogTrk Sectors per track -// IN DWORD Offset First valid sector for this device -// IN DWORD Size Count of valid sectors for this device -// -// RETURNS: -// NTSTATUS -// - -NTSTATUS -IDECreateDevice(IN PDRIVER_OBJECT DriverObject, - OUT PDEVICE_OBJECT *DeviceObject, - IN PCONTROLLER_OBJECT ControllerObject, - IN int UnitNumber, - IN ULONG DiskNumber, - IN PIDE_DRIVE_IDENTIFY DrvParms, - IN ULONG PartitionNumber, - IN ULONGLONG Offset, - IN ULONGLONG Size) -{ - WCHAR NameBuffer[IDE_MAX_NAME_LENGTH]; - WCHAR ArcNameBuffer[IDE_MAX_NAME_LENGTH + 15]; - UNICODE_STRING DeviceName; - UNICODE_STRING ArcName; - NTSTATUS RC; - PIDE_DEVICE_EXTENSION DeviceExtension; - - // Create a unicode device name - swprintf(NameBuffer, - L"\\Device\\Harddisk%d\\Partition%d", - DiskNumber, - PartitionNumber); - RtlInitUnicodeString(&DeviceName, - NameBuffer); - - // Create the device - RC = IoCreateDevice(DriverObject, sizeof(IDE_DEVICE_EXTENSION), - &DeviceName, FILE_DEVICE_DISK, 0, TRUE, DeviceObject); - if (!NT_SUCCESS(RC)) - { - DbgPrint ("IoCreateDevice call failed\n"); - return RC; - } - - // Set the buffering strategy here... - (*DeviceObject)->Flags |= DO_DIRECT_IO; - (*DeviceObject)->AlignmentRequirement = FILE_WORD_ALIGNMENT; - - // Fill out Device extension data - DeviceExtension = (PIDE_DEVICE_EXTENSION) (*DeviceObject)->DeviceExtension; - DeviceExtension->DeviceObject = (*DeviceObject); - DeviceExtension->ControllerObject = ControllerObject; - DeviceExtension->DiskExtension = NULL; - DeviceExtension->UnitNumber = UnitNumber; - DeviceExtension->LBASupported = - (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0; - DeviceExtension->DMASupported = - (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0; - // FIXME: deal with bizarre sector sizes - DeviceExtension->BytesPerSector = 512 /* DrvParms->BytesPerSector */; - DeviceExtension->SectorsPerLogCyl = DrvParms->LogicalHeads * - DrvParms->SectorsPerTrack; - DeviceExtension->SectorsPerLogTrk = DrvParms->SectorsPerTrack; - DeviceExtension->LogicalHeads = DrvParms->LogicalHeads; - DeviceExtension->LogicalCylinders = - (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? DrvParms->TMCylinders : DrvParms->LogicalCyls; - DeviceExtension->Offset = Offset; - DeviceExtension->Size = Size; - DPRINT("%wZ: offset %lu size %lu \n", - &DeviceName, - DeviceExtension->Offset, - DeviceExtension->Size); - - // Initialize the DPC object here - IoInitializeDpcRequest(*DeviceObject, IDEDpcForIsr); - - if (PartitionNumber != 0) - { - DbgPrint("%wZ %luMB\n", &DeviceName, Size / 2048); - } - - /* assign arc name */ - if (PartitionNumber == 0) - { - swprintf(ArcNameBuffer, - L"\\ArcName\\multi(0)disk(0)rdisk(%d)", - DiskNumber); - } - else - { - swprintf(ArcNameBuffer, - L"\\ArcName\\multi(0)disk(0)rdisk(%d)partition(%d)", - DiskNumber, - PartitionNumber); - } - RtlInitUnicodeString (&ArcName, - ArcNameBuffer); - DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName); - RC = IoAssignArcName (&ArcName, - &DeviceName); - if (!NT_SUCCESS(RC)) - { - DbgPrint ("IoAssignArcName (%wZ) failed (Status %x)\n", &ArcName, RC); - } - - return RC; -} - - // IDEPolledRead // // DESCRIPTION: @@ -1220,23 +926,24 @@ IDEPolledRead(IN WORD Address, IN BYTE Command, OUT BYTE *Buffer) { - BYTE Status; - int RetryCount; + ULONG SectorCount = 0; + ULONG RetryCount; + BOOLEAN Junk = FALSE; + UCHAR Status; /* Wait for STATUS.BUSY and STATUS.DRQ to clear */ for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) { Status = IDEReadStatus(Address); if (!(Status & IDE_SR_BUSY) && !(Status & IDE_SR_DRQ)) - { - break; - } + { + break; + } ScsiPortStallExecution(10); } if (RetryCount == IDE_MAX_BUSY_RETRIES) { - CHECKPOINT1; - return IDE_ER_ABRT; + return(IDE_ER_ABRT); } /* Write Drive/Head to select drive */ @@ -1247,14 +954,13 @@ IDEPolledRead(IN WORD Address, { Status = IDEReadStatus(Address); if (!(Status & IDE_SR_BUSY) && !(Status & IDE_SR_DRQ)) - { - break; - } + { + break; + } ScsiPortStallExecution(10); } if (RetryCount >= IDE_MAX_BUSY_RETRIES) { - CHECKPOINT1; return IDE_ER_ABRT; } @@ -1262,21 +968,21 @@ IDEPolledRead(IN WORD Address, if (DrvHead & IDE_DH_LBA) { DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n", - DrvHead & IDE_DH_DRV1 ? 1 : 0, - ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum, - SectorCnt, - Command); + DrvHead & IDE_DH_DRV1 ? 1 : 0, + ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum, + SectorCnt, + Command); } else { DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n", - DrvHead & IDE_DH_DRV1 ? 1 : 0, - CylinderHigh, - CylinderLow, - DrvHead & 0x0f, - SectorNum, - SectorCnt, - Command); + DrvHead & IDE_DH_DRV1 ? 1 : 0, + CylinderHigh, + CylinderLow, + DrvHead & 0x0f, + SectorNum, + SectorCnt, + Command); } /* Setup command parameters */ @@ -1291,99 +997,85 @@ IDEPolledRead(IN WORD Address, IDEWriteCommand(Address, Command); ScsiPortStallExecution(50); + /* wait for DRQ or error */ + for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++) + { + Status = IDEReadStatus(Address); + if (!(Status & IDE_SR_BUSY)) + { + if (Status & IDE_SR_ERR) + { + return(IDE_ER_ABRT); + } + if (Status & IDE_SR_DRQ) + { + break; + } + else + { + return(IDE_ER_ABRT); + } + } + ScsiPortStallExecution(10); + } + + /* timed out */ + if (RetryCount >= IDE_MAX_POLL_RETRIES) + { + return(IDE_ER_ABRT); + } + while (1) { - // wait for DRQ or error - for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++) - { - Status = IDEReadStatus(Address); - if (!(Status & IDE_SR_BUSY)) - { - if (Status & IDE_SR_ERR) - { - CHECKPOINT1; - return IDE_ER_ABRT; - } - if (Status & IDE_SR_DRQ) - { - break; - } - else - { - CHECKPOINT1; - return IDE_ER_ABRT; - } - } - ScsiPortStallExecution(10); - } - if (RetryCount >= IDE_MAX_POLL_RETRIES) - { - CHECKPOINT1; - return IDE_ER_ABRT; - } + /* Read data into buffer */ + if (Junk == FALSE) + { + IDEReadBlock(Address, Buffer, IDE_SECTOR_BUF_SZ); + Buffer += IDE_SECTOR_BUF_SZ; + } + else + { + UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ]; + IDEReadBlock(Address, JunkBuffer, IDE_SECTOR_BUF_SZ); + } + SectorCount++; - // Read data into buffer - IDEReadBlock(Address, Buffer, IDE_SECTOR_BUF_SZ); - Buffer += IDE_SECTOR_BUF_SZ; - - // Check for more sectors to read -/* - for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES && - (IDEReadStatus(Address) & IDE_SR_DRQ); RetryCount++) - ; - if (!(IDEReadStatus(Address) & IDE_SR_BUSY)) - { - CHECKPOINT1; - return 0; - } -*/ + /* Check for error or more sectors to read */ for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) - { - Status = IDEReadStatus(Address); - if (!(Status & IDE_SR_BUSY)) - { - if (Status & IDE_SR_DRQ) - { - break; - } - else - { - CHECKPOINT1; - return 0; - } - } - } + { + Status = IDEReadStatus(Address); + if (!(Status & IDE_SR_BUSY)) + { + if (Status & IDE_SR_ERR) + { + return(IDE_ER_ABRT); + } + if (Status & IDE_SR_DRQ) + { + if (SectorCount >= SectorCnt) + { + DPRINT("Buffer size exceeded!\n"); + Junk = TRUE; + } + break; + } + else + { + if (SectorCount > SectorCnt) + { + DPRINT("Read %lu sectors of junk!\n", + SectorCount - SectorCnt); + } + return(0); + } + } + } } } + // ------------------------------------------- Nondiscardable statics -// IDEDispatchOpenClose -// -// DESCRIPTION: -// Answer requests for Open/Close calls: a null operation -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// Standard dispatch arguments -// -// RETURNS: -// NTSTATUS -// - -static NTSTATUS STDCALL -IDEDispatchOpenClose(IN PDEVICE_OBJECT pDO, - IN PIRP Irp) -{ - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = FILE_OPENED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_SUCCESS; -} - // IDEDispatchReadWrite // // DESCRIPTION: @@ -1470,102 +1162,6 @@ DPRINT("AdjOffset:%ld:%ld + Length:%ld = AdjExtent:%ld:%ld\n", } -// AtapiDispatchScsi -// -// DESCRIPTION: -// Answer requests for SCSI calls -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// Standard dispatch arguments -// -// RETURNS: -// NTSTATUS -// - -static NTSTATUS STDCALL -AtapiDispatchScsi(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - DPRINT1("AtapiDispatchScsi()\n"); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return(STATUS_SUCCESS); -} - - -// AtapiDispatchDeviceControl -// -// DESCRIPTION: -// Answer requests for device control calls -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// Standard dispatch arguments -// -// RETURNS: -// NTSTATUS -// - -static NTSTATUS STDCALL -AtapiDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION Stack; - - DPRINT1("AtapiDispatchDeviceControl()\n"); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_SCSI_GET_CAPABILITIES: - { - PIO_SCSI_CAPABILITIES Capabilities; - - DPRINT1(" IOCTL_SCSI_GET_CAPABILITIES\n"); - - Capabilities = (PIO_SCSI_CAPABILITIES)(*((PIO_SCSI_CAPABILITIES*)Irp->AssociatedIrp.SystemBuffer)); - Capabilities->Length = sizeof(IO_SCSI_CAPABILITIES); - Capabilities->MaximumTransferLength = 65536; /* FIXME: preliminary values!!! */ - Capabilities->MaximumPhysicalPages = 1; - Capabilities->SupportedAsynchronousEvents = 0; - Capabilities->AlignmentMask = 0; - Capabilities->TaggedQueuing = FALSE; - Capabilities->AdapterScansDown = FALSE; - Capabilities->AdapterUsesPio = TRUE; - - Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES); - } - break; - - case IOCTL_SCSI_GET_INQUIRY_DATA: - DPRINT1(" IOCTL_SCSI_GET_INQUIRY_DATA\n"); - break; - - default: - DPRINT1(" unknown ioctl code: 0x%lX\n", - Stack->Parameters.DeviceIoControl.IoControlCode); - break; - } - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return(STATUS_SUCCESS); -} - - // IDEStartIo // // DESCRIPTION: @@ -2316,4 +1912,101 @@ IDEIoTimer(PDEVICE_OBJECT DeviceObject, } } + +static ULONG +AtapiExecuteScsi(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb) +{ + ULONG SrbStatus = SRB_STATUS_SUCCESS; + + DPRINT1("AtapiExecuteScsi() called!\n"); + + DPRINT1("PathId: %lu TargetId: %lu Lun: %lu\n", + Srb->PathId, + Srb->TargetId, + Srb->Lun); + + switch (Srb->Cdb[0]) + { + case SCSIOP_INQUIRY: + if ((Srb->PathId == 0) && + (Srb->TargetId < 2) && + (Srb->Lun == 0) && + (DeviceExtension->DevicePresent[Srb->TargetId] == TRUE)) + { + PINQUIRYDATA InquiryData; + PIDE_DRIVE_IDENTIFY DeviceParams; + ULONG i; + + DPRINT1("SCSIOP_INQUIRY: TargetId: %lu\n", Srb->TargetId); + + InquiryData = Srb->DataBuffer; + DeviceParams = &DeviceExtension->DeviceParms[Srb->TargetId]; + + /* clear buffer */ + for (i = 0; i < Srb->DataTransferLength; i++) + { + ((PUCHAR)Srb->DataBuffer)[i] = 0; + } + + /* set device class */ + if (DeviceExtension->DeviceAtapi[Srb->TargetId] == FALSE) + { + /* hard-disk */ + InquiryData->DeviceType = DIRECT_ACCESS_DEVICE; + } + else + { + /* FIXME: this is incorrect use SCSI-INQUIRY command!! */ + /* cdrom drive */ + InquiryData->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE; + } + + DPRINT1("ConfigBits: 0x%x\n", DeviceParams->ConfigBits); + if (DeviceParams->ConfigBits & 0x80) + { + DPRINT1("Removable media!\n"); + InquiryData->RemovableMedia = 1; + } + + for (i = 0; i < 20; i += 2) + { + InquiryData->VendorId[i] = + ((PUCHAR)DeviceParams->ModelNumber)[i]; + InquiryData->VendorId[i+1] = + ((PUCHAR)DeviceParams->ModelNumber)[i+1]; + } + + for (i = 0; i < 4; i++) + { + InquiryData->ProductId[12+i] = ' '; + } + + for (i = 0; i < 4; i += 2) + { + InquiryData->ProductRevisionLevel[i] = + ((PUCHAR)DeviceParams->FirmwareRev)[i]; + InquiryData->ProductRevisionLevel[i+1] = + ((PUCHAR)DeviceParams->FirmwareRev)[i+1]; + } + + SrbStatus = SRB_STATUS_SUCCESS; + } + else + { + SrbStatus = SRB_STATUS_SELECTION_TIMEOUT; + } + break; + + case SCSIOP_MODE_SENSE: + break; + + } + + DPRINT1("AtapiExecuteScsi() done!\n"); + + return(SrbStatus); +} + + /* EOF */ diff --git a/reactos/drivers/storage/atapi/atapi.h b/reactos/drivers/storage/atapi/atapi.h index cb93059f20e..2886ae74f1e 100644 --- a/reactos/drivers/storage/atapi/atapi.h +++ b/reactos/drivers/storage/atapi/atapi.h @@ -55,18 +55,18 @@ extern "C" { #define IDE_DH_HDMASK 0x0F #define IDE_DH_DRV0 0x00 #define IDE_DH_DRV1 0x10 -#define IDE_REG_STATUS 0x0007 -#define IDE_SR_BUSY 0x80 -#define IDE_SR_DRDY 0x40 -#define IDE_SR_DRQ 0x08 -#define IDE_SR_ERR 0x01 -#define IDE_REG_COMMAND 0x0007 -#define IDE_CMD_READ 0x20 -#define IDE_CMD_READ_RETRY 0x21 -#define IDE_CMD_WRITE 0x30 -#define IDE_CMD_WRITE_RETRY 0x31 -#define IDE_CMD_IDENT_DRV 0xEC - +#define IDE_REG_STATUS 0x0007 +#define IDE_SR_BUSY 0x80 +#define IDE_SR_DRDY 0x40 +#define IDE_SR_DRQ 0x08 +#define IDE_SR_ERR 0x01 +#define IDE_REG_COMMAND 0x0007 +#define IDE_CMD_READ 0x20 +#define IDE_CMD_READ_RETRY 0x21 +#define IDE_CMD_WRITE 0x30 +#define IDE_CMD_WRITE_RETRY 0x31 +#define IDE_CMD_IDENT_ATA_DRV 0xEC +#define IDE_CMD_IDENT_ATAPI_DRV 0xA1 // // Access macros for command registers // Each macro takes an address of the command port block, and data @@ -154,46 +154,6 @@ typedef struct _IDE_DEVICE_EXTENSION } IDE_DEVICE_EXTENSION, *PIDE_DEVICE_EXTENSION; -// ATAPI_PORT_EXTENSION -// -// DESCRIPTION: -// Extension to be placed in each device object -// -// ACCESS: -// Allocated from NON-PAGED POOL -// Available at any IRQL -// - -typedef struct _ATAPI_PORT_EXTENSION -{ - PDEVICE_OBJECT DeviceObject; - PCONTROLLER_OBJECT ControllerObject; - ULONG PortNumber; -#if 0 - struct _IDE_DEVICE_EXTESION *DiskExtension; - PARTITION_INFORMATION PartitionInfo; - int UnitNumber; - BOOLEAN LBASupported; - BOOLEAN DMASupported; - int BytesPerSector; - int LogicalHeads; - int LogicalCylinders; - int SectorsPerLogCyl; - int SectorsPerLogTrk; - int Offset; - int Size; - - int Operation; - ULONG BytesRequested; - ULONG BytesToTransfer; - ULONG BytesRemaining; - ULONG StartingSector; - int SectorsTransferred; - BYTE *TargetAddress; -#endif -} ATAPI_PORT_EXTENSION, *PATAPI_PORT_EXTENSION; - - // IDE_TIMER_STATES // // DESCRIPTION: @@ -217,7 +177,8 @@ typedef enum _IDE_TIMER_STATES { // Available at any IRQL // -typedef struct _IDE_CONTROLLER_EXTENSION { +typedef struct _IDE_CONTROLLER_EXTENSION +{ KSPIN_LOCK SpinLock; int Number; int Vector; @@ -239,9 +200,12 @@ typedef struct _IDE_CONTROLLER_EXTENSION { } IDE_CONTROLLER_EXTENSION, *PIDE_CONTROLLER_EXTENSION; + + // IDE_DRIVE_IDENTIFY -typedef struct _IDE_DRIVE_IDENTIFY { +typedef struct _IDE_DRIVE_IDENTIFY +{ WORD ConfigBits; /*00*/ WORD LogicalCyls; /*01*/ WORD Reserved02; /*02*/ @@ -280,7 +244,8 @@ typedef struct _IDE_DRIVE_IDENTIFY { WORD Reserved59; /*59*/ WORD TMSectorCountLo; /*60*/ WORD TMSectorCountHi; /*61*/ - WORD Reserved62[194]; /*62*/ + WORD Reserved62[193]; /*62*/ + WORD Checksum; /*255*/ } IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY; diff --git a/reactos/drivers/storage/class2/class2.c b/reactos/drivers/storage/class2/class2.c index be78744eec5..297647c707b 100644 --- a/reactos/drivers/storage/class2/class2.c +++ b/reactos/drivers/storage/class2/class2.c @@ -1,4 +1,4 @@ -/* $Id: class2.c,v 1.2 2002/01/14 01:43:26 ekohl Exp $ +/* $Id: class2.c,v 1.3 2002/01/27 01:25:01 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -7,14 +7,21 @@ * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) */ +/* + * TODO: + * - ScsiClassClaimDevice() must send a claim/unclaim request to + * scsiport.sys. + */ + +/* INCLUDES *****************************************************************/ + #include #include "../include/scsi.h" #include "../include/class2.h" -//#define NDEBUG +#define NDEBUG #include -//#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0) #define VERSION "0.0.1" @@ -41,7 +48,8 @@ static NTSTATUS STDCALL ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -// ------------------------------------------------------- Public Interface + +/* FUNCTIONS ****************************************************************/ // DriverEntry // @@ -113,7 +121,28 @@ ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject, BOOLEAN Release, PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL) { - UNIMPLEMENTED; + NTSTATUS Status; + + DPRINT1("ScsiClassClaimDevice() called\n"); + + if (NewPortDeviceObject != NULL) + *NewPortDeviceObject = NULL; + + if (Release == TRUE) + { + ObDereferenceObject(PortDeviceObject); + return(STATUS_SUCCESS); + } + + ObReferenceObjectByPointer(PortDeviceObject, + 0, + NULL, + KernelMode); + + if (NewPortDeviceObject != NULL) + *NewPortDeviceObject = PortDeviceObject; + + return(STATUS_SUCCESS); } @@ -124,7 +153,20 @@ ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, IN OUT PDEVICE_OBJECT *DeviceObject, IN PCLASS_INIT_DATA InitializationData) { - UNIMPLEMENTED; + DPRINT1("ScsiClassCreateDeviceObject() called\n"); + +#if 0 + Status = IoCreateDevice(DriverObject, + InitializationData->DeviceExtensionSize, + &UnicodeName, + InitializationData->DeviceType, + InitializationData->DeviceCharacteristics, + FALSE, + &InternalDeviceObject); +#endif + + + return(STATUS_SUCCESS); } @@ -150,8 +192,43 @@ ULONG STDCALL ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData, PSCSI_ADAPTER_BUS_INFO AdapterInformation) { + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; + PUCHAR Buffer; + ULONG Bus; + ULONG UnclaimedDevices = 0; + NTSTATUS Status; + DPRINT("ScsiClassFindUnclaimedDevices() called!\n"); - return(0); + + DPRINT("NumberOfBuses: %lu\n",AdapterInformation->NumberOfBuses); + Buffer = (PUCHAR)AdapterInformation; + for (Bus = 0; Bus < (ULONG)AdapterInformation->NumberOfBuses; Bus++) + { + DPRINT("Searching bus %lu\n", Bus); + + UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterInformation->BusData[Bus].InquiryDataOffset); + + while (AdapterInformation->BusData[Bus].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + DPRINT("Device: '%.8s'\n", InquiryData->VendorId); + + if ((InitializationData->ClassFindDeviceCallBack(InquiryData) == TRUE) && + (UnitInfo->DeviceClaimed == FALSE)) + { + UnclaimedDevices++; + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA) (Buffer + UnitInfo->NextInquiryDataOffset); + } + } + + return(UnclaimedDevices); } @@ -159,11 +236,20 @@ NTSTATUS STDCALL ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject, PIO_SCSI_CAPABILITIES *PortCapabilities) { + PIO_SCSI_CAPABILITIES Buffer; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; KEVENT Event; PIRP Irp; + *PortCapabilities = NULL; + Buffer = ExAllocatePool(NonPagedPool, /* FIXME: use paged pool */ + sizeof(IO_SCSI_CAPABILITIES)); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + KeInitializeEvent(&Event, NotificationEvent, FALSE); @@ -172,13 +258,14 @@ ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject, PortDeviceObject, NULL, 0, - PortCapabilities, - sizeof(PVOID), + Buffer, + sizeof(IO_SCSI_CAPABILITIES), FALSE, &Event, &IoStatusBlock); if (Irp == NULL) { + ExFreePool(Buffer); return(STATUS_INSUFFICIENT_RESOURCES); } @@ -191,7 +278,16 @@ ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject, KernelMode, FALSE, NULL); - return(IoStatusBlock.Status); + Status = IoStatusBlock.Status; + } + + if (!NT_SUCCESS(Status)) + { + ExFreePool(Buffer); + } + else + { + *PortCapabilities = Buffer; } return(Status); @@ -208,10 +304,9 @@ ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject, KEVENT Event; PIRP Irp; - Buffer = ExAllocatePool(NonPagedPool, /* FIXME: use paged pool */ + *ConfigInfo = NULL; + Buffer = ExAllocatePool(NonPagedPool, INQUIRY_DATA_SIZE); - *ConfigInfo = Buffer; - if (Buffer == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); @@ -232,6 +327,7 @@ ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject, &IoStatusBlock); if (Irp == NULL) { + ExFreePool(Buffer); return(STATUS_INSUFFICIENT_RESOURCES); } @@ -250,7 +346,10 @@ ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject, if (!NT_SUCCESS(Status)) { ExFreePool(Buffer); - *ConfigInfo = NULL; + } + else + { + *ConfigInfo = Buffer; } return(Status); @@ -262,15 +361,18 @@ ScsiClassInitialize(PVOID Argument1, PVOID Argument2, PCLASS_INIT_DATA InitializationData) { + PCONFIGURATION_INFORMATION ConfigInfo; PDRIVER_OBJECT DriverObject = Argument1; WCHAR NameBuffer[80]; UNICODE_STRING PortName; - ULONG PortNumber = 0; + ULONG PortNumber; PDEVICE_OBJECT PortDeviceObject; PFILE_OBJECT FileObject; BOOLEAN DiskFound = FALSE; NTSTATUS Status; + DPRINT("ScsiClassInitialize() called!\n"); + DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose; DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite; @@ -284,20 +386,22 @@ ScsiClassInitialize(PVOID Argument1, DriverObject->DriverStartIo = InitializationData->ClassStartIo; } + ConfigInfo = IoGetConfigurationInformation(); + /* look for ScsiPortX scsi port devices */ - do + for (PortNumber = 0; PortNumber < ConfigInfo->ScsiPortCount; PortNumber++) { swprintf(NameBuffer, L"\\Device\\ScsiPort%lu", PortNumber); RtlInitUnicodeString(&PortName, NameBuffer); - DPRINT1("Checking scsi port %ld\n", PortNumber); + DPRINT("Checking scsi port %ld\n", PortNumber); Status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject); - DPRINT1("Status 0x%08lX\n", Status); + DPRINT("Status 0x%08lX\n", Status); if (NT_SUCCESS(Status)) { DPRINT1("ScsiPort%lu found.\n", PortNumber); @@ -311,14 +415,10 @@ ScsiClassInitialize(PVOID Argument1, { DiskFound = TRUE; } - - ObDereferenceObject(PortDeviceObject); - ObDereferenceObject(FileObject); } - PortNumber++; } - while (NT_SUCCESS(Status)); + DPRINT("ScsiClassInitialize() done!\n"); for(;;); return((DiskFound == TRUE) ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE); @@ -434,12 +534,17 @@ ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject, } -/* Internal Routines **************/ +/* INTERNAL FUNCTIONS *******************************************************/ static NTSTATUS STDCALL ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { +// PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + +// if (deviceExtension->ClassCreateClose) +// return(deviceExtension->ClassCreateClose(DeviceObject, Irp)); + Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -447,6 +552,7 @@ ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject, return(STATUS_SUCCESS); } + static NTSTATUS STDCALL ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) diff --git a/reactos/drivers/storage/disk/disk.c b/reactos/drivers/storage/disk/disk.c index cb2e31616e9..847640cfdd6 100644 --- a/reactos/drivers/storage/disk/disk.c +++ b/reactos/drivers/storage/disk/disk.c @@ -1,8 +1,8 @@ -/* $Id: disk.c,v 1.2 2002/01/14 01:44:03 ekohl Exp $ +/* $Id: disk.c,v 1.3 2002/01/27 01:25:15 ekohl Exp $ * */ -// ------------------------------------------------------------------------- +/* INCLUDES *****************************************************************/ #include @@ -10,14 +10,17 @@ #include "../include/class2.h" #include "../include/ntddscsi.h" -//#define NDEBUG +#define NDEBUG #include #define VERSION "V0.0.1" -//static NTSTATUS -//DiskCreateDevices(VOID); +typedef struct _DISK_DEVICE_EXTENSION +{ + ULONG Dummy; +} DISK_DEVICE_EXTENSION, *PDISK_DEVICE_EXTENSION; + BOOLEAN STDCALL @@ -27,6 +30,19 @@ DiskClassFindDevices(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PortDeviceObject, ULONG PortNumber); +BOOLEAN STDCALL +DiskClassCheckDevice(IN PINQUIRYDATA InquiryData); + + +static NTSTATUS +DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, /* what's this used for? */ + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber, + IN ULONG DiskNumber, + IN PIO_SCSI_CAPABILITIES Capabilities, /* what's this used for? */ + IN PSCSI_INQUIRY_DATA InquiryData, + IN PCLASS_INIT_DATA InitializationData); NTSTATUS STDCALL DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject, @@ -38,6 +54,7 @@ DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, +/* FUNCTIONS ****************************************************************/ // DriverEntry // @@ -64,16 +81,22 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, { CLASS_INIT_DATA InitData; - DbgPrint("Disk Class Driver %s\n", VERSION); + DbgPrint("Disk Class Driver %s\n", + VERSION); + DPRINT("RegistryPath '%wZ'\n", + RegistryPath); + + RtlZeroMemory(&InitData, + sizeof(CLASS_INIT_DATA)); InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA); - InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION); // + sizeof(DISK_DATA) + InitData.DeviceExtensionSize = sizeof(DISK_DEVICE_EXTENSION); InitData.DeviceType = FILE_DEVICE_DISK; InitData.DeviceCharacteristics = 0; InitData.ClassError = NULL; // DiskClassProcessError; - InitData.ClassReadWriteVerification = NULL; // DiskClassReadWriteVerification; - InitData.ClassFindDeviceCallBack = NULL; // DiskClassDeviceVerification; + InitData.ClassReadWriteVerification = NULL; // DiskClassReadWriteCheck; + InitData.ClassFindDeviceCallBack = DiskClassCheckDevice; InitData.ClassFindDevices = DiskClassFindDevices; InitData.ClassDeviceControl = DiskClassDeviceControl; InitData.ClassShutdownFlush = DiskClassShutdownFlush; @@ -86,25 +109,37 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, } -// DiskClassFindDevices -// -// DESCRIPTION: -// This function searches for device that are attached to the given scsi port. -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// IN PDRIVER_OBJECT DriverObject System allocated Driver Object for this driver -// IN PUNICODE_STRING RegistryPath Name of registry driver service key -// IN PCLASS_INIT_DATA InitializationData Pointer to the main initialization data -// IN PDEVICE_OBJECT PortDeviceObject Scsi port device object -// IN ULONG PortNumber Port number -// -// RETURNS: -// TRUE: At least one disk drive was found -// FALSE: No disk drive found -// +/********************************************************************** + * NAME EXPORTED + * DiskClassFindDevices + * + * DESCRIPTION + * This function searches for device that are attached to the + * given scsi port. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * System allocated Driver Object for this driver + * + * RegistryPath + * Name of registry driver service key + * + * InitializationData + * Pointer to the main initialization data + * + * PortDeviceObject + * Pointer to the port Device Object + * + * PortNumber + * Port number + * + * RETURN VALUE + * TRUE: At least one disk drive was found + * FALSE: No disk drive found + */ BOOLEAN STDCALL DiskClassFindDevices(PDRIVER_OBJECT DriverObject, @@ -113,12 +148,16 @@ DiskClassFindDevices(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PortDeviceObject, ULONG PortNumber) { - PIO_SCSI_CAPABILITIES PortCapabilities = NULL; + PCONFIGURATION_INFORMATION ConfigInfo; + PIO_SCSI_CAPABILITIES PortCapabilities; PSCSI_ADAPTER_BUS_INFO AdapterBusInfo; + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; PCHAR Buffer; + ULONG Bus; ULONG DeviceCount; + BOOLEAN FoundDevice; NTSTATUS Status; -// PCONFIGURATION_INFORMATION ConfigInfo; DPRINT1("DiskClassFindDevices() called.\n"); @@ -131,160 +170,282 @@ DiskClassFindDevices(PDRIVER_OBJECT DriverObject, return(FALSE); } -// DPRINT1("MaximumTransferLength: %lu\n", Capabilities.MaximumTransferLength); + DPRINT1("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength); /* Get inquiry data */ Status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *)&Buffer); if (!NT_SUCCESS(Status)) { - DPRINT("ScsiClassGetInquiryData() failed! (Status 0x%lX)\n", Status); + DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status); return(FALSE); } - /* Get number of unclaimed devices */ + /* Check whether there are unclaimed devices */ AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer; DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData, AdapterBusInfo); if (DeviceCount == 0) { - DPRINT("ScsiClassFindUnclaimedDevices() returned 0!"); + DPRINT1("No unclaimed devices!\n"); return(FALSE); } -// ConfigInfo = IoGetConfigurationInformation(); -// DPRINT1("Number of SCSI ports: %lu\n", ConfigInfo->ScsiPortCount); + DPRINT1("Found %lu unclaimed devices!\n", DeviceCount); + ConfigInfo = IoGetConfigurationInformation(); + /* Search each bus of this adapter */ + for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++) + { + DPRINT("Searching bus %lu\n", Bus); + UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset); + + while (AdapterBusInfo->BusData[Bus].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) || + (InquiryData->DeviceType == OPTICAL_DEVICE)) && + (InquiryData->DeviceTypeQualifier == 0) && + (UnitInfo->DeviceClaimed == FALSE)) + { + DPRINT1("Vendor: '%.24s'\n", + InquiryData->VendorId); + + /* Create device objects for disk */ + Status = DiskClassCreateDeviceObject(DriverObject, + RegistryPath, + PortDeviceObject, + PortNumber, + ConfigInfo->DiskCount, + PortCapabilities, + UnitInfo, + InitializationData); + if (NT_SUCCESS(Status)) + { + ConfigInfo->DiskCount++; + FoundDevice = TRUE; + } + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset); + } + } ExFreePool(Buffer); + ExFreePool(PortCapabilities); - return(TRUE); + DPRINT1("DiskClassFindDevices() done\n"); + + return(FoundDevice); } -// IDECreateDevice +/********************************************************************** + * NAME EXPORTED + * DiskClassCheckDevice + * + * DESCRIPTION + * This function checks the InquiryData for the correct device + * type and qualifier. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * InquiryData + * Pointer to the inquiry data for the device in question. + * + * RETURN VALUE + * TRUE: A disk device was found. + * FALSE: Otherwise. + */ + +BOOLEAN STDCALL +DiskClassCheckDevice(IN PINQUIRYDATA InquiryData) +{ + return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE || + InquiryData->DeviceType == OPTICAL_DEVICE) && + InquiryData->DeviceTypeQualifier == 0); +} + + + +// IDECreateDevices // // DESCRIPTION: -// Creates a device by calling IoCreateDevice and a symbolic link for Win32 +// Create the raw device and any partition devices on this drive // // RUN LEVEL: // PASSIVE_LEVEL // // ARGUMENTS: -// IN PDRIVER_OBJECT DriverObject The system supplied driver object -// OUT PDEVICE_OBJECT *DeviceObject The created device object -// IN PCONTROLLER_OBJECT ControllerObject The Controller for the device -// IN BOOLEAN LBASupported Does the drive support LBA addressing? -// IN BOOLEAN DMASupported Does the drive support DMA? -// IN int SectorsPerLogCyl Sectors per cylinder -// IN int SectorsPerLogTrk Sectors per track -// IN DWORD Offset First valid sector for this device -// IN DWORD Size Count of valid sectors for this device +// IN PDRIVER_OBJECT DriverObject The system created driver object +// IN PCONTROLLER_OBJECT ControllerObject +// IN PIDE_CONTROLLER_EXTENSION ControllerExtension +// The IDE controller extension for +// this device +// IN int DriveIdx The index of the drive on this +// controller +// IN int HarddiskIdx The NT device number for this +// drive // // RETURNS: -// NTSTATUS +// TRUE Drive exists and devices were created +// FALSE no devices were created for this device // -#if 0 -NTSTATUS -IDECreateDevice(IN PDRIVER_OBJECT DriverObject, - OUT PDEVICE_OBJECT *DeviceObject, - IN PCONTROLLER_OBJECT ControllerObject, - IN int UnitNumber, - IN ULONG DiskNumber, - IN ULONG PartitionNumber, - IN PIDE_DRIVE_IDENTIFY DrvParms, - IN DWORD Offset, - IN DWORD Size) + +static NTSTATUS +DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, /* what's this used for? */ + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber, + IN ULONG DiskNumber, + IN PIO_SCSI_CAPABILITIES Capabilities, /* what's this used for? */ + IN PSCSI_INQUIRY_DATA InquiryData, + IN PCLASS_INIT_DATA InitializationData) /* what's this used for? */ { - WCHAR NameBuffer[IDE_MAX_NAME_LENGTH]; - WCHAR ArcNameBuffer[IDE_MAX_NAME_LENGTH + 15]; - UNICODE_STRING DeviceName; - UNICODE_STRING ArcName; - NTSTATUS RC; - PIDE_DEVICE_EXTENSION DeviceExtension; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeDeviceDirName; + WCHAR NameBuffer[80]; + CHAR NameBuffer2[80]; + PDEVICE_OBJECT DiskDeviceObject; + HANDLE Handle; - // Create a unicode device name - swprintf(NameBuffer, - L"\\Device\\Harddisk%d\\Partition%d", - DiskNumber, - PartitionNumber); - RtlInitUnicodeString(&DeviceName, - NameBuffer); - - // Create the device - RC = IoCreateDevice(DriverObject, sizeof(IDE_DEVICE_EXTENSION), - &DeviceName, FILE_DEVICE_DISK, 0, TRUE, DeviceObject); - if (!NT_SUCCESS(RC)) - { - DPRINT("IoCreateDevice call failed\n",0); - return RC; - } - - // Set the buffering strategy here... - (*DeviceObject)->Flags |= DO_DIRECT_IO; - (*DeviceObject)->AlignmentRequirement = FILE_WORD_ALIGNMENT; - - // Fill out Device extension data - DeviceExtension = (PIDE_DEVICE_EXTENSION) (*DeviceObject)->DeviceExtension; - DeviceExtension->DeviceObject = (*DeviceObject); - DeviceExtension->ControllerObject = ControllerObject; - DeviceExtension->UnitNumber = UnitNumber; - DeviceExtension->LBASupported = - (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0; - DeviceExtension->DMASupported = - (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0; - // FIXME: deal with bizarre sector sizes - DeviceExtension->BytesPerSector = 512 /* DrvParms->BytesPerSector */; - DeviceExtension->SectorsPerLogCyl = DrvParms->LogicalHeads * - DrvParms->SectorsPerTrack; - DeviceExtension->SectorsPerLogTrk = DrvParms->SectorsPerTrack; - DeviceExtension->LogicalHeads = DrvParms->LogicalHeads; - DeviceExtension->Offset = Offset; - DeviceExtension->Size = Size; - DPRINT("%wZ: offset %d size %d \n", - &DeviceName, - DeviceExtension->Offset, - DeviceExtension->Size); - - // Initialize the DPC object here - IoInitializeDpcRequest(*DeviceObject, IDEDpcForIsr); - - if (PartitionNumber != 0) - { - DbgPrint("%wZ %dMB\n", &DeviceName, Size / 2048); - } - - /* assign arc name */ - if (PartitionNumber == 0) - { - swprintf(ArcNameBuffer, - L"\\ArcName\\multi(0)disk(0)rdisk(%d)", - DiskNumber); - } - else - { - swprintf(ArcNameBuffer, - L"\\ArcName\\multi(0)disk(0)rdisk(%d)partition(%d)", - DiskNumber, - PartitionNumber); - } - RtlInitUnicodeString (&ArcName, - ArcNameBuffer); - DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName); - RC = IoAssignArcName (&ArcName, - &DeviceName); - if (!NT_SUCCESS(RC)) - { - DPRINT("IoAssignArcName (%wZ) failed (Status %x)\n", - &ArcName, RC); - } - - - return RC; -} +#if 0 + IDE_DRIVE_IDENTIFY DrvParms; + PIDE_DEVICE_EXTENSION DiskDeviceExtension; + PDEVICE_OBJECT PartitionDeviceObject; + PIDE_DEVICE_EXTENSION PartitionDeviceExtension; + ULONG SectorCount = 0; + PDRIVE_LAYOUT_INFORMATION PartitionList = NULL; + PPARTITION_INFORMATION PartitionEntry; #endif + ULONG i; + NTSTATUS Status; + + DPRINT1("DiskClassCreateDeviceObjects() called\n"); + + /* Create the harddisk device directory */ + swprintf(NameBuffer, + L"\\Device\\Harddisk%d", + DiskNumber); + RtlInitUnicodeString(&UnicodeDeviceDirName, + NameBuffer); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeDeviceDirName, + 0, + NULL, + NULL); + Status = ZwCreateDirectoryObject(&Handle, + 0, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not create device dir object\n"); + return(Status); + } + + /* Claim the disk device */ + Status = ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + FALSE, + &PortDeviceObject); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not claim disk device\n"); + + ZwMakeTemporaryObject(Handle); + ZwClose(Handle); + + return(Status); + } + + /* Create disk device (Partition 0) */ + sprintf(NameBuffer2, + "\\Device\\Harddisk%d\\Partition0", + DiskNumber); + + Status = ScsiClassCreateDeviceObject(DriverObject, + NameBuffer2, + NULL, + &DiskDeviceObject, + InitializationData); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status); + + ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + TRUE, + NULL); + ZwMakeTemporaryObject(Handle); + ZwClose(Handle); + + return(Status); + } + + +#if 0 + /* Read partition table */ + Status = IoReadPartitionTable(DiskDeviceObject, + DrvParms.BytesPerSector, + TRUE, + &PartitionList); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IoReadPartitionTable() failed\n"); + return FALSE; + } + + DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount); + for (i=0;i < PartitionList->PartitionCount; i++) + { + PartitionEntry = &PartitionList->PartitionEntry[i]; + + DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n", + i, + PartitionEntry->PartitionNumber, + PartitionEntry->BootIndicator, + PartitionEntry->PartitionType, + PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/, + PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/); + + /* Create device for partition */ + Status = IDECreateDevice(DriverObject, + &PartitionDeviceObject, + ControllerObject, + DriveIdx, + HarddiskIdx, + &DrvParms, + PartitionEntry->PartitionNumber, + PartitionEntry->StartingOffset.QuadPart / 512 /* DrvParms.BytesPerSector*/, + PartitionEntry->PartitionLength.QuadPart / 512 /*DrvParms.BytesPerSector*/); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IDECreateDevice() failed\n"); + break; + } + + /* Initialize pointer to disk device extension */ + PartitionDeviceExtension = (PIDE_DEVICE_EXTENSION)PartitionDeviceObject->DeviceExtension; + PartitionDeviceExtension->DiskExtension = (PVOID)DiskDeviceExtension; + } + + if (PartitionList != NULL) + ExFreePool(PartitionList); +#endif + + DPRINT1("DiskClassCreateDeviceObjects() done\n"); + + return(STATUS_SUCCESS); +} + diff --git a/reactos/drivers/storage/include/scsi.h b/reactos/drivers/storage/include/scsi.h index 625a5c5e36b..62f1a8e1c03 100644 --- a/reactos/drivers/storage/include/scsi.h +++ b/reactos/drivers/storage/include/scsi.h @@ -1,4 +1,4 @@ -/* $Id: scsi.h,v 1.2 2002/01/14 01:44:18 ekohl Exp $ +/* $Id: scsi.h,v 1.3 2002/01/27 01:25:33 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -10,175 +10,157 @@ #ifndef __STORAGE_INCLUDE_SCSI_H #define __STORAGE_INCLUDE_SCSI_H -// -// Command Descriptor Block. Passed by SCSI controller chip over the SCSI bus -// -typedef union _CDB { +/* Command Descriptor Block */ - // - // Generic 6-Byte CDB - // - - struct _CDB6GENERIC { - UCHAR OperationCode; - UCHAR Immediate : 1; - UCHAR CommandUniqueBits : 4; - UCHAR LogicalUnitNumber : 3; - UCHAR CommandUniqueBytes[3]; - UCHAR Link : 1; - UCHAR Flag : 1; - UCHAR Reserved : 4; - UCHAR VendorUnique : 2; +typedef union _CDB +{ + /* Generic 6-Byte CDB */ + struct _CDB6GENERIC + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR CommandUniqueBits:4; + UCHAR LogicalUnitNumber:3; + UCHAR CommandUniqueBytes[3]; + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved:4; + UCHAR VendorUnique:2; } CDB6GENERIC, *PCDB6GENERIC; - // - // Standard 6-byte CDB - // - - struct _CDB6READWRITE { - UCHAR OperationCode; - UCHAR LogicalBlockMsb1 : 5; - UCHAR LogicalUnitNumber : 3; - UCHAR LogicalBlockMsb0; - UCHAR LogicalBlockLsb; - UCHAR TransferBlocks; - UCHAR Control; + /* Standard 6-byte CDB */ + struct _CDB6READWRITE + { + UCHAR OperationCode; + UCHAR LogicalBlockMsb1:5; + UCHAR LogicalUnitNumber:3; + UCHAR LogicalBlockMsb0; + UCHAR LogicalBlockLsb; + UCHAR TransferBlocks; + UCHAR Control; } CDB6READWRITE, *PCDB6READWRITE; - - // - // SCSI Inquiry CDB - // - - struct _CDB6INQUIRY { - UCHAR OperationCode; - UCHAR Reserved1 : 5; - UCHAR LogicalUnitNumber : 3; - UCHAR PageCode; - UCHAR IReserved; - UCHAR AllocationLength; - UCHAR Control; + /* SCSI Inquiry CDB */ + struct _CDB6INQUIRY + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR PageCode; + UCHAR IReserved; + UCHAR AllocationLength; + UCHAR Control; } CDB6INQUIRY, *PCDB6INQUIRY; - // - // SCSI Format CDB - // - - struct _CDB6FORMAT { - UCHAR OperationCode; - UCHAR FormatControl : 5; - UCHAR LogicalUnitNumber : 3; - UCHAR FReserved1; - UCHAR InterleaveMsb; - UCHAR InterleaveLsb; - UCHAR FReserved2; + /* SCSI Format CDB */ + struct _CDB6FORMAT + { + UCHAR OperationCode; + UCHAR FormatControl:5; + UCHAR LogicalUnitNumber:3; + UCHAR FReserved1; + UCHAR InterleaveMsb; + UCHAR InterleaveLsb; + UCHAR FReserved2; } CDB6FORMAT, *PCDB6FORMAT; - // - // Standard 10-byte CDB - - struct _CDB10 { - UCHAR OperationCode; - UCHAR RelativeAddress : 1; - UCHAR Reserved1 : 2; - UCHAR ForceUnitAccess : 1; - UCHAR DisablePageOut : 1; - UCHAR LogicalUnitNumber : 3; - UCHAR LogicalBlockByte0; - UCHAR LogicalBlockByte1; - UCHAR LogicalBlockByte2; - UCHAR LogicalBlockByte3; - UCHAR Reserved2; - UCHAR TransferBlocksMsb; - UCHAR TransferBlocksLsb; - UCHAR Control; + /* Standard 10-byte CDB */ + struct _CDB10 + { + UCHAR OperationCode; + UCHAR RelativeAddress:1; + UCHAR Reserved1:2; + UCHAR ForceUnitAccess:1; + UCHAR DisablePageOut:1; + UCHAR LogicalUnitNumber:3; + UCHAR LogicalBlockByte0; + UCHAR LogicalBlockByte1; + UCHAR LogicalBlockByte2; + UCHAR LogicalBlockByte3; + UCHAR Reserved2; + UCHAR TransferBlocksMsb; + UCHAR TransferBlocksLsb; + UCHAR Control; } CDB10, *PCDB10; - // - // CD Rom Audio CDBs - // - - struct _PAUSE_RESUME { - UCHAR OperationCode; - UCHAR Reserved1 : 5; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2[6]; - UCHAR Action; - UCHAR Control; + /* CD Rom Audio CDBs */ + struct _PAUSE_RESUME + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[6]; + UCHAR Action; + UCHAR Control; } PAUSE_RESUME, *PPAUSE_RESUME; - // - // Read Table of Contents - // - - struct _READ_TOC { - UCHAR OperationCode; - UCHAR Reserved0 : 1; - UCHAR Msf : 1; - UCHAR Reserved1 : 3; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2[4]; - UCHAR StartingTrack; - UCHAR AllocationLength[2]; - UCHAR Control : 6; - UCHAR Format : 2; + /* Read Table of Contents */ + struct _READ_TOC + { + UCHAR OperationCode; + UCHAR Reserved0:1; + UCHAR Msf:1; + UCHAR Reserved1:3; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[4]; + UCHAR StartingTrack; + UCHAR AllocationLength[2]; + UCHAR Control:6; + UCHAR Format:2; } READ_TOC, *PREAD_TOC; - struct _PLAY_AUDIO_MSF { - UCHAR OperationCode; - UCHAR Reserved1 : 5; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2; - UCHAR StartingM; - UCHAR StartingS; - UCHAR StartingF; - UCHAR EndingM; - UCHAR EndingS; - UCHAR EndingF; - UCHAR Control; + struct _PLAY_AUDIO_MSF + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2; + UCHAR StartingM; + UCHAR StartingS; + UCHAR StartingF; + UCHAR EndingM; + UCHAR EndingS; + UCHAR EndingF; + UCHAR Control; } PLAY_AUDIO_MSF, *PPLAY_AUDIO_MSF; - // - // Read SubChannel Data - // - - struct _SUBCHANNEL { - UCHAR OperationCode; - UCHAR Reserved0 : 1; - UCHAR Msf : 1; - UCHAR Reserved1 : 3; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2 : 6; - UCHAR SubQ : 1; - UCHAR Reserved3 : 1; - UCHAR Format; - UCHAR Reserved4[2]; - UCHAR TrackNumber; - UCHAR AllocationLength[2]; - UCHAR Control; + /* Read SubChannel Data */ + struct _SUBCHANNEL + { + UCHAR OperationCode; + UCHAR Reserved0:1; + UCHAR Msf:1; + UCHAR Reserved1:3; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2:6; + UCHAR SubQ:1; + UCHAR Reserved3:1; + UCHAR Format; + UCHAR Reserved4[2]; + UCHAR TrackNumber; + UCHAR AllocationLength[2]; + UCHAR Control; } SUBCHANNEL, *PSUBCHANNEL; - // - // Read CD. Used by Atapi for raw sector reads. - // - - struct _READ_CD { - UCHAR OperationCode; - UCHAR Reserved0 : 2; - UCHAR ExpectedSectorType : 3; - UCHAR Reserved1 : 3; - UCHAR StartingLBA[4]; - UCHAR TransferBlocks[3]; - UCHAR Reserved2 : 1; - UCHAR ErrorFlags : 2; - UCHAR IncludeEDC : 1; - UCHAR IncludeUserData : 1; - UCHAR HeaderCode : 2; - UCHAR IncludeSyncData : 1; - UCHAR SubChannelSelection : 3; - UCHAR Reserved3 : 5; - UCHAR Reserved4; + /* Read CD. Used by Atapi for raw sector reads. */ + struct _READ_CD + { + UCHAR OperationCode; + UCHAR Reserved0 : 2; + UCHAR ExpectedSectorType : 3; + UCHAR Reserved1 : 3; + UCHAR StartingLBA[4]; + UCHAR TransferBlocks[3]; + UCHAR Reserved2 : 1; + UCHAR ErrorFlags : 2; + UCHAR IncludeEDC : 1; + UCHAR IncludeUserData : 1; + UCHAR HeaderCode : 2; + UCHAR IncludeSyncData : 1; + UCHAR SubChannelSelection : 3; + UCHAR Reserved3 : 5; + UCHAR Reserved4; } READ_CD, *PREAD_CD; // @@ -320,7 +302,7 @@ typedef union _CDB { UCHAR Control; } SEEK, *PSEEK; - struct _ERASE { + struct _ERASE { UCHAR OperationCode; UCHAR Long : 1; UCHAR Immediate : 1; @@ -330,7 +312,8 @@ typedef union _CDB { UCHAR Control; } ERASE, *PERASE; - struct _START_STOP { + struct _START_STOP + { UCHAR OperationCode; UCHAR Immediate: 1; UCHAR Reserved1 : 4; @@ -342,7 +325,7 @@ typedef union _CDB { UCHAR Control; } START_STOP, *PSTART_STOP; - struct _MEDIA_REMOVAL { + struct _MEDIA_REMOVAL { UCHAR OperationCode; UCHAR Reserved1 : 5; UCHAR LogicalUnitNumber : 3; @@ -461,29 +444,25 @@ typedef union _CDB { UCHAR Reserved5[3]; } LOAD_UNLOAD, *PLOAD_UNLOAD; - struct _MECH_STATUS { - UCHAR OperationCode; - UCHAR Reserved1[7]; - UCHAR AllocationLength[2]; - UCHAR Reserved2[2]; + struct _MECH_STATUS + { + UCHAR OperationCode; + UCHAR Reserved1[7]; + UCHAR AllocationLength[2]; + UCHAR Reserved2[2]; } MECH_STATUS, *PMECH_STATUS; - } CDB, *PCDB; -// -// Command Descriptor Block constants. -// +/* Command Descriptor Block constants */ #define CDB6GENERIC_LENGTH 6 #define CDB10GENERIC_LENGTH 10 #define CDB12GENERIC_LENGTH 12 #define SETBITON 1 #define SETBITOFF 0 -// -// Mode Sense/Select page constants. -// +/* Mode Sense/Select page constants */ #define MODE_PAGE_ERROR_RECOVERY 0x01 #define MODE_PAGE_DISCONNECT 0x02 #define MODE_PAGE_FORMAT_DEVICE 0x03 @@ -863,10 +842,7 @@ typedef struct _SENSE_DATA #define SCSI_SENSEQ_END_OF_MEDIA_DETECTED 0x02 #define SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED 0x04 - -// -// SCSI IO Device Control Codes -// +/* SCSI IO Device Control Codes */ #define FILE_DEVICE_SCSI 0x0000001b @@ -874,9 +850,7 @@ typedef struct _SENSE_DATA #define IOCTL_SCSI_EXECUTE_OUT ((FILE_DEVICE_SCSI << 16) + 0x0012) #define IOCTL_SCSI_EXECUTE_NONE ((FILE_DEVICE_SCSI << 16) + 0x0013) -// -// SMART support in atapi -// +/* SMART support in atapi */ #define IOCTL_SCSI_MINIPORT_SMART_VERSION ((FILE_DEVICE_SCSI << 16) + 0x0500) #define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501) @@ -893,8 +867,9 @@ typedef struct _SENSE_DATA // Read Capacity Data - returned in Big Endian format // -typedef struct _READ_CAPACITY_DATA { - ULONG LogicalBlockAddress; +typedef struct _READ_CAPACITY_DATA +{ + ULONG LogicalBlockAddress; ULONG BytesPerBlock; } READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA; @@ -952,23 +927,22 @@ typedef struct _MODE_PARAMETER_BLOCK { UCHAR BlockLength[3]; }MODE_PARAMETER_BLOCK, *PMODE_PARAMETER_BLOCK; -// -// Define Disconnect-Reconnect page. -// -typedef struct _MODE_DISCONNECT_PAGE { - UCHAR PageCode : 6; - UCHAR Reserved : 1; - UCHAR PageSavable : 1; - UCHAR PageLength; - UCHAR BufferFullRatio; - UCHAR BufferEmptyRatio; - UCHAR BusInactivityLimit[2]; - UCHAR BusDisconnectTime[2]; - UCHAR BusConnectTime[2]; - UCHAR MaximumBurstSize[2]; - UCHAR DataTransferDisconnect : 2; - UCHAR Reserved2[3]; +/* Define Disconnect-Reconnect page */ +typedef struct _MODE_DISCONNECT_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR BufferFullRatio; + UCHAR BufferEmptyRatio; + UCHAR BusInactivityLimit[2]; + UCHAR BusDisconnectTime[2]; + UCHAR BusConnectTime[2]; + UCHAR MaximumBurstSize[2]; + UCHAR DataTransferDisconnect:2; + UCHAR Reserved2[3]; }MODE_DISCONNECT_PAGE, *PMODE_DISCONNECT_PAGE; // @@ -1212,14 +1186,15 @@ typedef struct _PORT_OUTPUT { UCHAR Volume; } PORT_OUTPUT, *PPORT_OUTPUT; -typedef struct _AUDIO_OUTPUT { - UCHAR CodePage; - UCHAR ParameterLength; - UCHAR Immediate; - UCHAR Reserved[2]; - UCHAR LbaFormat; - UCHAR LogicalBlocksPerSecond[2]; - PORT_OUTPUT PortOutput[4]; +typedef struct _AUDIO_OUTPUT +{ + UCHAR CodePage; + UCHAR ParameterLength; + UCHAR Immediate; + UCHAR Reserved[2]; + UCHAR LbaFormat; + UCHAR LogicalBlocksPerSecond[2]; + PORT_OUTPUT PortOutput[4]; } AUDIO_OUTPUT, *PAUDIO_OUTPUT; // diff --git a/reactos/drivers/storage/include/srb.h b/reactos/drivers/storage/include/srb.h index 45cde4725ba..3bba5d7b19e 100644 --- a/reactos/drivers/storage/include/srb.h +++ b/reactos/drivers/storage/include/srb.h @@ -1,4 +1,4 @@ -/* $Id: srb.h,v 1.2 2002/01/14 01:44:19 ekohl Exp $ +/* $Id: srb.h,v 1.3 2002/01/27 01:25:34 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -59,7 +59,8 @@ typedef struct _PORT_CONFIGURATION_INFORMATION DMA_SPEED DmaSpeed; ULONG AlignmentMask; ULONG NumberOfAccessRanges; - ACCESS_RANGE (*AccessRanges)[]; +// ACCESS_RANGE (*AccessRanges)[]; + PACCESS_RANGE AccessRanges; PVOID Reserved; UCHAR NumberOfBuses; CCHAR InitiatorBusId[8]; @@ -336,102 +337,74 @@ ScsiPortConvertUlongToPhysicalAddress(IN ULONG UlongAddress); VOID STDCALL ScsiPortFlushDma(IN PVOID HwDeviceExtension); -VOID -STDCALL -ScsiPortFreeDeviceBase ( - IN PVOID HwDeviceExtension, - IN PVOID MappedAddress - ); - -ULONG -STDCALL -ScsiPortGetBusData ( - IN PVOID DeviceExtension, - IN ULONG BusDataType, - IN ULONG SystemIoBusNumber, - IN ULONG SlotNumber, - IN PVOID Buffer, - IN ULONG Length - ); - -PVOID -STDCALL -ScsiPortGetDeviceBase ( - IN PVOID HwDeviceExtension, - IN INTERFACE_TYPE BusType, - IN ULONG SystemIoBusNumber, - IN SCSI_PHYSICAL_ADDRESS IoAddress, - IN ULONG NumberOfBytes, - IN BOOLEAN InIoSpace - ); - -PVOID -STDCALL -ScsiPortGetLogicalUnit ( - IN PVOID HwDeviceExtension, - IN UCHAR PathId, - IN UCHAR TargetId, - IN UCHAR Lun - ); - -SCSI_PHYSICAL_ADDRESS -STDCALL -ScsiPortGetPhysicalAddress ( - IN PVOID HwDeviceExtension, - IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, - IN PVOID VirtualAddress, - OUT PULONG Length - ); - -PSCSI_REQUEST_BLOCK -STDCALL -ScsiPortGetSrb ( - IN PVOID DeviceExtension, - IN UCHAR PathId, - IN UCHAR TargetId, - IN UCHAR Lun, - IN LONG QueueTag - ); - -PVOID STDCALL -ScsiPortGetUncachedExtension ( - IN PVOID HwDeviceExtension, - IN PPORT_CONFIGURATION_INFORMATION ConfigInfo, - IN ULONG NumberOfBytes - ); - -PVOID STDCALL -ScsiPortGetVirtualAddress ( - IN PVOID HwDeviceExtension, - IN SCSI_PHYSICAL_ADDRESS PhysicalAddress - ); +VOID STDCALL +ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension, + IN PVOID MappedAddress); ULONG STDCALL -ScsiPortInitialize ( - IN PVOID Argument1, - IN PVOID Argument2, - IN struct _HW_INITIALIZATION_DATA *HwInitializationData, - IN PVOID HwContext - ); +ScsiPortGetBusData(IN PVOID DeviceExtension, + IN ULONG BusDataType, + IN ULONG SystemIoBusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length); + +PVOID STDCALL +ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension, + IN INTERFACE_TYPE BusType, + IN ULONG SystemIoBusNumber, + IN SCSI_PHYSICAL_ADDRESS IoAddress, + IN ULONG NumberOfBytes, + IN BOOLEAN InIoSpace); + +PVOID STDCALL +ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun); + +SCSI_PHYSICAL_ADDRESS STDCALL +ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, + IN PVOID VirtualAddress, + OUT PULONG Length); + +PSCSI_REQUEST_BLOCK STDCALL +ScsiPortGetSrb(IN PVOID DeviceExtension, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun, + IN LONG QueueTag); + +PVOID STDCALL +ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension, + IN PPORT_CONFIGURATION_INFORMATION ConfigInfo, + IN ULONG NumberOfBytes); + +PVOID STDCALL +ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension, + IN SCSI_PHYSICAL_ADDRESS PhysicalAddress); + +ULONG STDCALL +ScsiPortInitialize(IN PVOID Argument1, + IN PVOID Argument2, + IN struct _HW_INITIALIZATION_DATA *HwInitializationData, + IN PVOID HwContext); VOID STDCALL -ScsiPortIoMapTransfer ( - IN PVOID HwDeviceExtension, - IN PSCSI_REQUEST_BLOCK Srb, - IN ULONG LogicalAddress, - IN ULONG Length - ); +ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb, + IN ULONG LogicalAddress, + IN ULONG Length); VOID STDCALL -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 - ); +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); VOID STDCALL ScsiPortMoveMemory(OUT PVOID Destination, diff --git a/reactos/drivers/storage/scsiport/scsiport.c b/reactos/drivers/storage/scsiport/scsiport.c index afc477b83d8..7bdb281d9d1 100644 --- a/reactos/drivers/storage/scsiport/scsiport.c +++ b/reactos/drivers/storage/scsiport/scsiport.c @@ -1,4 +1,22 @@ -/* $Id: scsiport.c,v 1.2 2002/01/14 01:45:03 ekohl Exp $ +/* + * ReactOS kernel + * Copyright (C) 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: scsiport.c,v 1.3 2002/01/27 01:25:49 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -7,39 +25,153 @@ * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) */ +/* INCLUDES *****************************************************************/ + #include #include "../include/srb.h" +#include "../include/scsi.h" +#include "../include/ntddscsi.h" +#define NDEBUG +#include -#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0) #define VERSION "0.0.1" +/* TYPES *********************************************************************/ + +/* + * SCSI_PORT_DEVICE_EXTENSION + * + * DESCRIPTION + * First part of the port objects device extension. The second + * part is the miniport-specific device extension. + */ + +typedef struct _SCSI_PORT_DEVICE_EXTENSION +{ + ULONG Length; + ULONG MiniPortExtensionSize; + PORT_CONFIGURATION_INFORMATION PortConfig; + + PHW_STARTIO HwStartIo; + + UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */ +} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION; + + +/* + * SCSI_PORT_TIMER_STATES + * + * DESCRIPTION + * An enumeration containing the states in the timer DFA + */ + +typedef enum _SCSI_PORT_TIMER_STATES +{ + IDETimerIdle, + IDETimerCmdWait, + IDETimerResetWaitForBusyNegate, + IDETimerResetWaitForDrdyAssert +} SCSI_PORT_TIMER_STATES; + + +/* + * SCSI_PORT_CONTROLLER_EXTENSION + * + * DESCRIPTION + * Driver-defined structure used to hold miscellaneous controller information. + * + * ACCESS + * Allocated from NON-PAGED POOL + * Available at any IRQL + */ + +typedef struct _SCSI_PORT_CONTROLLER_EXTENSION +{ + KSPIN_LOCK SpinLock; + ULONG Number; + ULONG Vector; + BOOLEAN DMASupported; + BOOLEAN ControllerInterruptBug; + PKINTERRUPT Interrupt; + + BOOLEAN OperationInProgress; + UCHAR DeviceStatus; + PSCSI_PORT_DEVICE_EXTENSION DeviceForOperation; + PIRP CurrentIrp; + ULONG Retries; + + SCSI_PORT_TIMER_STATES TimerState; + LONG TimerCount; + + PDEVICE_OBJECT PortDeviceObject; + +} SCSI_PORT_CONTROLLER_EXTENSION, *PSCSI_PORT_CONTROLLER_EXTENSION; + + +/* GLOBALS *******************************************************************/ + + static NTSTATUS STDCALL ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +static NTSTATUS STDCALL +ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS STDCALL +ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static VOID STDCALL +ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS +ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, + IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension, + IN ULONG PortCount); + +static BOOLEAN STDCALL +ScsiPortIsr(IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext); + +static VOID +ScsiPortDpcForIsr(IN PKDPC Dpc, + IN PDEVICE_OBJECT DpcDeviceObject, + IN PIRP DpcIrp, + IN PVOID DpcContext); + +static VOID STDCALL +ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject, + PVOID Context); -// ------------------------------------------------------- Public Interface +/* FUNCTIONS *****************************************************************/ -// DriverEntry -// -// DESCRIPTION: -// This function initializes the driver. -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// IN PDRIVER_OBJECT DriverObject System allocated Driver Object -// for this driver -// IN PUNICODE_STRING RegistryPath Name of registry driver service -// key -// -// RETURNS: -// NTSTATUS +/********************************************************************** + * NAME EXPORTED + * DriverEntry + * + * DESCRIPTION + * This function initializes the driver. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * System allocated Driver Object for this driver. + * + * RegistryPath + * Name of registry driver service key. + * + * RETURN VALUE + * Status. + */ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject, @@ -50,6 +182,30 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, } +/********************************************************************** + * NAME EXPORTED + * ScsiDebugPrint + * + * DESCRIPTION + * Prints debugging messages. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DebugPrintLevel + * Debug level of the given message. + * + * DebugMessage + * Pointer to printf()-compatible format string. + * + * ... + Additional output data (see printf()). + * + * RETURN VALUE + * None. + */ + VOID ScsiDebugPrint(IN ULONG DebugPrintLevel, IN PCHAR DebugMessage, @@ -215,6 +371,18 @@ ScsiPortInitialize(IN PVOID Argument1, { PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1; PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2; + PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension; + PCONFIGURATION_INFORMATION SystemConfig; + PPORT_CONFIGURATION_INFORMATION PortConfig; + BOOLEAN Again; + ULONG i; + ULONG Result; + NTSTATUS Status; + ULONG MaxBus; + PACCESS_RANGE AccessRanges; + ULONG ExtensionSize; + + DPRINT1("ScsiPortInitialize() called!\n"); if ((HwInitializationData->HwInitialize == NULL) || (HwInitializationData->HwStartIo == NULL) || @@ -223,20 +391,113 @@ ScsiPortInitialize(IN PVOID Argument1, (HwInitializationData->HwResetBus == NULL)) return(STATUS_INVALID_PARAMETER); -// DriverObject->DriverStartIo = HwInitializationData->HwStartIo; - -// DriverObject->DriverStartIo = ScsiPortStartIo; + DriverObject->DriverStartIo = ScsiPortStartIo; DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose; -// DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl; -// DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatch; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl; + DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi; // DriverObject->MajorFunction[IRP_MJ_READ] = IDEDispatchReadWrite; // DriverObject->MajorFunction[IRP_MJ_WRITE] = IDEDispatchReadWrite; // DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = IDEDispatchQueryInformation; // DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = IDEDispatchSetInformation; - UNIMPLEMENTED; + + + + SystemConfig = IoGetConfigurationInformation(); + + ExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) + + HwInitializationData->DeviceExtensionSize; + PseudoDeviceExtension = ExAllocatePool(PagedPool, + ExtensionSize); + RtlZeroMemory(PseudoDeviceExtension, + ExtensionSize); + PseudoDeviceExtension->Length = ExtensionSize; + PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize; + PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo; + + PortConfig = &PseudoDeviceExtension->PortConfig; + + PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION); + PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType; + PortConfig->InterruptMode = + (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched; + PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed; + PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed; + PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges; + + PortConfig->AccessRanges = + ExAllocatePool(PagedPool, + sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges); + + + PortConfig->SystemIoBusNumber = 0; + PortConfig->SlotNumber = 0; + + MaxBus = (PortConfig->AdapterInterfaceType == PCIBus) ? 8 : 1; + + DPRINT("MaxBus: %lu\n", MaxBus); + + while (TRUE) + { + DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber); + +// RtlZeroMemory(AccessRanges, +// sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges); + + /* Note: HwFindAdapter is called once for each bus */ + Result = (HwInitializationData->HwFindAdapter)(&PseudoDeviceExtension->MiniPortDeviceExtension, + HwContext, + NULL, /* BusInformation */ + NULL, /* ArgumentString */ + &PseudoDeviceExtension->PortConfig, + &Again); + DPRINT("HwFindAdapter() result: %lu\n", Result); + + if (Result == SP_RETURN_FOUND) + { + DPRINT("ScsiPortInitialize(): Found HBA!\n"); + + Status = ScsiPortCreatePortDevice(DriverObject, + PseudoDeviceExtension, + SystemConfig->ScsiPortCount); + + if (!NT_SUCCESS(Status)) + { + DbgPrint("ScsiPortCreatePortDevice() failed! (Status 0x%lX)\n", Status); + + ExFreePool(PortConfig->AccessRanges); + ExFreePool(PseudoDeviceExtension); + + return(Status); + } + + /* Update the configuration info */ + SystemConfig->AtDiskPrimaryAddressClaimed = PortConfig->AtdiskPrimaryClaimed; + SystemConfig->AtDiskSecondaryAddressClaimed = PortConfig->AtdiskSecondaryClaimed; + SystemConfig->ScsiPortCount++; + } + + if (Again == FALSE) + { + PortConfig->SystemIoBusNumber++; + PortConfig->SlotNumber = 0; + } + + DPRINT("Bus: %lu MaxBus: %lu\n", PortConfig->SystemIoBusNumber, MaxBus); + if (PortConfig->SystemIoBusNumber >= MaxBus) + { + DPRINT1("Scanned all buses!\n"); + break; + } + } + + ExFreePool(PortConfig->AccessRanges); + ExFreePool(PseudoDeviceExtension); + + DPRINT1("ScsiPortInitialize() done!\n"); + return(STATUS_SUCCESS); } @@ -314,19 +575,460 @@ ScsiPortValidateRange(IN PVOID HwDeviceExtension, } -/* internal functions ******/ +/* INTERNAL FUNCTIONS ********************************************************/ +/********************************************************************** + * NAME INTERNAL + * ScsiPortCreateClose + * + * DESCRIPTION + * Answer requests for Create/Close calls: a null operation. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DeviceObject + * Pointer to a device object. + * + * Irp + * Pointer to an IRP. + * + * ... + Additional output data (see printf()). + * + * RETURN VALUE + * Status. + */ static NTSTATUS STDCALL ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + DPRINT("ScsiPortCreateClose()\n"); + Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; + return(STATUS_SUCCESS); } +// ScsiPortDispatchScsi +// +// DESCRIPTION: +// Answer requests for SCSI calls +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("ScsiPortDispatchScsi()\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +// ScsiPortDeviceControl +// +// DESCRIPTION: +// Answer requests for device control calls +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + + DPRINT("ScsiPortDeviceControl()\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = DeviceObject->DeviceExtension; + + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_SCSI_EXECUTE_IN: + { + DPRINT1(" IOCTL_SCSI_EXECUTE_IN\n"); + } + break; + + case IOCTL_SCSI_EXECUTE_OUT: + { + DPRINT1(" IOCTL_SCSI_EXECUTE_OUT\n"); + } + break; + + case IOCTL_SCSI_EXECUTE_NONE: + { + DPRINT1(" IOCTL_SCSI_EXECUTE_NONE\n"); + } + break; + + case IOCTL_SCSI_GET_CAPABILITIES: + { + PIO_SCSI_CAPABILITIES Capabilities; + + DPRINT1(" IOCTL_SCSI_GET_CAPABILITIES\n"); + + Capabilities = (PIO_SCSI_CAPABILITIES)Irp->AssociatedIrp.SystemBuffer; + Capabilities->Length = sizeof(IO_SCSI_CAPABILITIES); + Capabilities->MaximumTransferLength = + DeviceExtension->PortConfig.MaximumTransferLength; + Capabilities->MaximumPhysicalPages = 1; + Capabilities->SupportedAsynchronousEvents = 0; + Capabilities->AlignmentMask = + DeviceExtension->PortConfig.AlignmentMask; + Capabilities->TaggedQueuing = + DeviceExtension->PortConfig.TaggedQueuing; + Capabilities->AdapterScansDown = + DeviceExtension->PortConfig.AdapterScansDown; + Capabilities->AdapterUsesPio = TRUE; + + Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES); + } + break; + + case IOCTL_SCSI_GET_INQUIRY_DATA: + { + PSCSI_ADAPTER_BUS_INFO AdapterInfo; + PSCSI_INQUIRY_DATA UnitInfo, PrevUnit; + SCSI_REQUEST_BLOCK Srb; + ULONG Bus; + ULONG Target; + ULONG UnitCount; + BOOLEAN Result; + + DPRINT1(" IOCTL_SCSI_GET_INQUIRY_DATA\n"); + + AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)Irp->AssociatedIrp.SystemBuffer; + AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses; + + UnitInfo = (PSCSI_INQUIRY_DATA) + ((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) + + (sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1))); + + Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256); + RtlZeroMemory(&Srb, + sizeof(SCSI_REQUEST_BLOCK)); + Srb.Function = SRB_FUNCTION_EXECUTE_SCSI; + Srb.DataTransferLength = 256; + Srb.Cdb[0] = SCSIOP_INQUIRY; + + for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++) + { + Srb.PathId = Bus; + + AdapterInfo->BusData[Bus].InitiatorBusId = 0; /* ? */ + AdapterInfo->BusData[Bus].InquiryDataOffset = + (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo); + + PrevUnit = NULL; + UnitCount = 0; + + for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++) + { + Srb.TargetId = Target; + Srb.Lun = 0; + + Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension, + &Srb); + if (Result == TRUE) + { + UnitInfo->PathId = Bus; + UnitInfo->TargetId = Target; + UnitInfo->Lun = 0; + UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE; + memcpy(&UnitInfo->InquiryData, + Srb.DataBuffer, + INQUIRYDATABUFFERSIZE); + if (PrevUnit != NULL) + PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo); + PrevUnit = UnitInfo; + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1); + UnitCount++; + } + } + AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount; + } + + ExFreePool(Srb.DataBuffer); + DPRINT1("BufferSize: %lu\n",(ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo)); + Irp->IoStatus.Information = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo); + } + break; + + default: + DPRINT1(" unknown ioctl code: 0x%lX\n", + Stack->Parameters.DeviceIoControl.IoControlCode); + break; + } + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +static VOID STDCALL +ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpStack; + + DPRINT("ScsiPortStartIo() called!\n"); + + IrpStack = IoGetCurrentIrpStackLocation(Irp); +// DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + + // FIXME: implement the supported functions + + switch (IrpStack->MajorFunction) + { + + default: + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; +// KeBugCheck((ULONG)Irp); + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject, + FALSE); + break; + } + DPRINT("ScsiPortStartIo() finished!\n"); +} + + +static NTSTATUS +ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, + IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension, + IN ULONG PortNumber) +{ + PSCSI_PORT_CONTROLLER_EXTENSION ControllerExtension; + PCONTROLLER_OBJECT ControllerObject; + PSCSI_PORT_DEVICE_EXTENSION PortDeviceExtension; + PDEVICE_OBJECT PortDeviceObject; + WCHAR NameBuffer[80]; + UNICODE_STRING DeviceName; + WCHAR DosNameBuffer[80]; + UNICODE_STRING DosDeviceName; + NTSTATUS Status; + ULONG AccessRangeSize; + + ULONG MappedIrq; + KIRQL Dirql; + KAFFINITY Affinity; + + DPRINT("ScsiPortCreatePortDevice() called\n"); + + MappedIrq = HalGetInterruptVector(PseudoDeviceExtension->PortConfig.AdapterInterfaceType, + PseudoDeviceExtension->PortConfig.SystemIoBusNumber, + 0, + PseudoDeviceExtension->PortConfig.BusInterruptLevel, + &Dirql, + &Affinity); + + ControllerObject = IoCreateController(sizeof(SCSI_PORT_CONTROLLER_EXTENSION)); + if (ControllerObject == NULL) + { + DbgPrint("Could not create controller object for port %d\n", + PortNumber); + return(STATUS_NO_SUCH_DEVICE); + } + + /* Fill out Controller extension data */ + ControllerExtension = (PSCSI_PORT_CONTROLLER_EXTENSION) + ControllerObject->ControllerExtension; + ControllerExtension->Number = PortNumber; + ControllerExtension->Vector = PseudoDeviceExtension->PortConfig.BusInterruptVector; + ControllerExtension->DMASupported = FALSE; + ControllerExtension->ControllerInterruptBug = FALSE; + ControllerExtension->OperationInProgress = FALSE; + + /* Initialize the spin lock in the controller extension */ + KeInitializeSpinLock(&ControllerExtension->SpinLock); + + /* Register an interrupt handler for this controller */ + Status = IoConnectInterrupt(&ControllerExtension->Interrupt, + ScsiPortIsr, + ControllerExtension, + &ControllerExtension->SpinLock, + MappedIrq, + Dirql, + Dirql, + PseudoDeviceExtension->PortConfig.InterruptMode, + FALSE, + Affinity, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not Connect Interrupt %d\n", + ControllerExtension->Vector); + IoDeleteController (ControllerObject); + return(Status); + } + + /* Create a unicode device name */ + swprintf(NameBuffer, + L"\\Device\\ScsiPort%lu", + PortNumber); + RtlInitUnicodeString(&DeviceName, + NameBuffer); + + DPRINT("Creating device: %wZ\n", &DeviceName); + + /* Create the port device */ + Status = IoCreateDevice(DriverObject, + PseudoDeviceExtension->Length, + &DeviceName, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &PortDeviceObject); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IoCreateDevice call failed! (Status 0x%lX)\n", Status); + IoDisconnectInterrupt(ControllerExtension->Interrupt); + IoDeleteController(ControllerObject); + return(Status); + } + + DPRINT("Created device: %wZ\n", &DeviceName); + + /* Set the buffering strategy here... */ + PortDeviceObject->Flags |= DO_DIRECT_IO; + PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; + + PortDeviceExtension = PortDeviceObject->DeviceExtension; + + ControllerExtension->PortDeviceObject = PortDeviceObject; + + /* Initialize the DPC object here */ + IoInitializeDpcRequest(ControllerExtension->PortDeviceObject, + ScsiPortDpcForIsr); + + /* + * Initialize the controller timer here + * (since it has to be tied to a device) + */ + ControllerExtension->TimerState = IDETimerIdle; + ControllerExtension->TimerCount = 0; + IoInitializeTimer(ControllerExtension->PortDeviceObject, + ScsiPortIoTimer, + ControllerExtension); + + /* Copy port configuration in device extension */ + memcpy(PortDeviceExtension, + PseudoDeviceExtension, + PseudoDeviceExtension->Length); + + /* Copy access ranges */ + AccessRangeSize = + sizeof(ACCESS_RANGE) * PseudoDeviceExtension->PortConfig.NumberOfAccessRanges; + PortDeviceExtension->PortConfig.AccessRanges = ExAllocatePool(NonPagedPool, + AccessRangeSize); + memcpy(PortDeviceExtension->PortConfig.AccessRanges, + PseudoDeviceExtension->PortConfig.AccessRanges, + AccessRangeSize); + + /* FIXME: Copy or configure any more? */ + + /* Create the dos device */ + swprintf(DosNameBuffer, + L"\\??\\Scsi%lu:", + PortNumber); + RtlInitUnicodeString(&DosDeviceName, + DosNameBuffer); + + IoCreateSymbolicLink(&DosDeviceName, + &DeviceName); + + return(STATUS_SUCCESS); +} + + + +static BOOLEAN STDCALL +ScsiPortIsr(IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext) +{ + DPRINT1("ScsiPortIsr() called!\n"); + + return(TRUE); +} + + +// ScsiPortDpcForIsr +// DESCRIPTION: +// +// RUN LEVEL: +// +// ARGUMENTS: +// IN PKDPC Dpc +// IN PDEVICE_OBJECT DpcDeviceObject +// IN PIRP DpcIrp +// IN PVOID DpcContext +// +static VOID +ScsiPortDpcForIsr(IN PKDPC Dpc, + IN PDEVICE_OBJECT DpcDeviceObject, + IN PIRP DpcIrp, + IN PVOID DpcContext) +{ + DPRINT("ScsiPortDpcForIsr()\n"); +// IDEFinishOperation((PIDE_CONTROLLER_EXTENSION) DpcContext); +} + + +// ScsiPortIoTimer +// DESCRIPTION: +// This function handles timeouts and other time delayed processing +// +// RUN LEVEL: +// +// ARGUMENTS: +// IN PDEVICE_OBJECT DeviceObject Device object registered with timer +// IN PVOID Context the Controller extension for the +// controller the device is on +// +static VOID STDCALL +ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject, + PVOID Context) +{ + DPRINT("ScsiPortIoTimer()\n"); +} + /* EOF */