diff --git a/reactos/drivers/storage/atapi/atapi.c b/reactos/drivers/storage/atapi/atapi.c index 352f9ac72b7..4713cdd8193 100644 --- a/reactos/drivers/storage/atapi/atapi.c +++ b/reactos/drivers/storage/atapi/atapi.c @@ -1,4 +1,4 @@ -/* $Id: atapi.c,v 1.4 2002/01/27 01:24:44 ekohl Exp $ +/* $Id: atapi.c,v 1.5 2002/01/31 14:57:37 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS ATAPI miniport driver @@ -18,7 +18,8 @@ /* * TODO: - * - Use scsiport driver. + * - implement sending of atapi commands + * - handle removable atapi non-cdrom drives */ // ------------------------------------------------------------------------- @@ -30,7 +31,6 @@ #include "../include/ntddscsi.h" #include "atapi.h" -#include "partitio.h" #define NDEBUG #include @@ -52,9 +52,16 @@ typedef struct _ATAPI_MINIPORT_EXTENSION { - IDE_DRIVE_IDENTIFY DeviceParms[2]; + IDE_DRIVE_IDENTIFY DeviceParams[2]; BOOLEAN DevicePresent[2]; BOOLEAN DeviceAtapi[2]; + + ULONG CommandPortBase; + ULONG ControlPortBase; + + BOOLEAN ExpectingInterrupt; + + PUSHORT DataBuffer; } ATAPI_MINIPORT_EXTENSION, *PATAPI_MINIPORT_EXTENSION; @@ -64,34 +71,6 @@ typedef struct _UNIT_EXTENSION } UNIT_EXTENSION, *PUNIT_EXTENSION; -typedef struct _IDE_CONTROLLER_PARAMETERS -{ - int CommandPortBase; - int CommandPortSpan; - int ControlPortBase; - int ControlPortSpan; - int Vector; - int IrqL; - int SynchronizeIrqL; - KINTERRUPT_MODE InterruptMode; - KAFFINITY Affinity; -} IDE_CONTROLLER_PARAMETERS, *PIDE_CONTROLLER_PARAMETERS; - -// NOTE: Do not increase max drives above 2 - -#define IDE_MAX_DRIVES 2 - -#define IDE_MAX_CONTROLLERS 2 -IDE_CONTROLLER_PARAMETERS Controllers[IDE_MAX_CONTROLLERS] = -{ - {0x01f0, 8, 0x03f6, 1, 14, 14, 15, LevelSensitive, 0xffff}, - {0x0170, 8, 0x0376, 1, 15, 15, 15, LevelSensitive, 0xffff} - /*{0x01E8, 8, 0x03ee, 1, 11, 11, 15, LevelSensitive, 0xffff}, - {0x0168, 8, 0x036e, 1, 10, 10, 15, LevelSensitive, 0xffff}*/ -}; - -static BOOLEAN IDEInitialized = FALSE; - // ----------------------------------------------- Discardable Declarations #ifdef ALLOC_PRAGMA @@ -172,60 +151,34 @@ 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); +AtapiPolledRead(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 -IDEDispatchReadWrite(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -static VOID STDCALL -IDEStartIo(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -static IO_ALLOCATION_ACTION STDCALL -IDEAllocateController(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID MapRegisterBase, - IN PVOID Ccontext); - -static BOOLEAN STDCALL -IDEStartController(IN OUT PVOID Context); - -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 ULONG AtapiExecuteScsi(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb); +static ULONG +AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +static ULONG +AtapiReadCapacity(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +static ULONG +AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); // ---------------------------------------------------------------- Inlines @@ -449,10 +402,14 @@ AtapiFindCompatiblePciController(PVOID DeviceExtension, if (ConfigInfo->AtdiskPrimaryClaimed == FALSE) { - /* both channels unclaimed: claim primary channel */ + /* Both channels unclaimed: Claim primary channel */ DPRINT1("Primary channel!\n"); + DevExt->CommandPortBase = 0x01F0; + DevExt->ControlPortBase = 0x03F6; + ConfigInfo->BusInterruptLevel = 14; + ConfigInfo->BusInterruptVector = 14; ConfigInfo->InterruptMode = LevelSensitive; ConfigInfo->AccessRanges[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x01F0); @@ -469,10 +426,14 @@ AtapiFindCompatiblePciController(PVOID DeviceExtension, } else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE) { - /* primary channel claimed: claim secondary channel */ + /* Primary channel already claimed: claim secondary channel */ DPRINT1("Secondary channel!\n"); + DevExt->CommandPortBase = 0x0170; + DevExt->ControlPortBase = 0x0376; + ConfigInfo->BusInterruptLevel = 15; + ConfigInfo->BusInterruptVector = 15; ConfigInfo->InterruptMode = LevelSensitive; ConfigInfo->AccessRanges[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x0170); @@ -579,7 +540,7 @@ AtapiStartIo(IN PVOID DeviceExtension, PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; ULONG Result; - DPRINT1("AtapiStartIo() called\n"); + DPRINT("AtapiStartIo() called\n"); switch (Srb->Function) { @@ -601,6 +562,8 @@ AtapiStartIo(IN PVOID DeviceExtension, static BOOLEAN STDCALL AtapiInterrupt(IN PVOID DeviceExtension) { + DPRINT("AtapiInterrupt() called!\n"); + return(TRUE); } @@ -673,7 +636,7 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension, { if (AtapiIdentifyATAPIDevice(CommandPortBase, UnitNumber, - &DeviceExtension->DeviceParms[UnitNumber])) + &DeviceExtension->DeviceParams[UnitNumber])) { DPRINT(" ATAPI drive found!\n"); DeviceExtension->DevicePresent[UnitNumber] = TRUE; @@ -689,7 +652,7 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension, { if (AtapiIdentifyATADevice(CommandPortBase, UnitNumber, - &DeviceExtension->DeviceParms[UnitNumber])) + &DeviceExtension->DeviceParams[UnitNumber])) { DPRINT(" IDE drive found!\n"); DeviceExtension->DevicePresent[UnitNumber] = TRUE; @@ -709,7 +672,7 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension, } -// IDEResetController +// AtapiResetController // // DESCRIPTION: // Reset the controller and report completion status @@ -725,8 +688,8 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension, // static BOOLEAN -IDEResetController(IN WORD CommandPort, - IN WORD ControlPort) +AtapiResetController(IN WORD CommandPort, + IN WORD ControlPort) { int Retries; @@ -786,8 +749,15 @@ AtapiIdentifyATADevice(IN ULONG CommandPort, 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_ATA_DRV, (BYTE *)DrvParms) != 0) + if (AtapiPolledRead((WORD)CommandPort, + 0, + 1, + 0, + 0, + 0, + (DriveNum ? IDE_DH_DRV1 : 0), + IDE_CMD_IDENT_ATA_DRV, + (BYTE *)DrvParms) != 0) { return FALSE; } @@ -831,7 +801,7 @@ AtapiIdentifyATADevice(IN ULONG CommandPort, DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector); if (DrvParms->BytesPerSector == 0) - DrvParms->BytesPerSector = 512; /* FIXME !!!*/ + DrvParms->BytesPerSector = 512; return TRUE; } @@ -842,8 +812,15 @@ AtapiIdentifyATAPIDevice(IN ULONG CommandPort, 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 */ + if (AtapiPolledRead((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; @@ -892,7 +869,7 @@ AtapiIdentifyATAPIDevice(IN ULONG CommandPort, } -// IDEPolledRead +// AtapiPolledRead // // DESCRIPTION: // Read a sector of data from the drive in a polled fashion. @@ -916,15 +893,15 @@ AtapiIdentifyATAPIDevice(IN ULONG CommandPort, // 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) +AtapiPolledRead(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) { ULONG SectorCount = 0; ULONG RetryCount; @@ -1076,842 +1053,6 @@ IDEPolledRead(IN WORD Address, // ------------------------------------------- Nondiscardable statics -// IDEDispatchReadWrite -// -// DESCRIPTION: -// Answer requests for reads and writes -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// Standard dispatch arguments -// -// RETURNS: -// NTSTATUS -// - -static NTSTATUS STDCALL -IDEDispatchReadWrite(IN PDEVICE_OBJECT pDO, - IN PIRP Irp) -{ - ULONG IrpInsertKey; - LARGE_INTEGER AdjustedOffset, AdjustedExtent, PartitionExtent, InsertKeyLI; - PIO_STACK_LOCATION IrpStack; - PIDE_DEVICE_EXTENSION DeviceExtension; - - IrpStack = IoGetCurrentIrpStackLocation(Irp); - DeviceExtension = (PIDE_DEVICE_EXTENSION)pDO->DeviceExtension; - - // Validate operation parameters - AdjustedOffset = RtlEnlargedIntegerMultiply(DeviceExtension->Offset, - DeviceExtension->BytesPerSector); -DPRINT("Offset:%ld * BytesPerSector:%ld = AdjOffset:%ld:%ld\n", - DeviceExtension->Offset, - DeviceExtension->BytesPerSector, - (unsigned long) AdjustedOffset.u.HighPart, - (unsigned long) AdjustedOffset.u.LowPart); -DPRINT("AdjOffset:%ld:%ld + ByteOffset:%ld:%ld\n", - (unsigned long) AdjustedOffset.u.HighPart, - (unsigned long) AdjustedOffset.u.LowPart, - (unsigned long) IrpStack->Parameters.Read.ByteOffset.u.HighPart, - (unsigned long) IrpStack->Parameters.Read.ByteOffset.u.LowPart); - AdjustedOffset = RtlLargeIntegerAdd(AdjustedOffset, - IrpStack->Parameters.Read.ByteOffset); -DPRINT(" = AdjOffset:%ld:%ld\n", - (unsigned long) AdjustedOffset.u.HighPart, - (unsigned long) AdjustedOffset.u.LowPart); - AdjustedExtent = RtlLargeIntegerAdd(AdjustedOffset, - RtlConvertLongToLargeInteger(IrpStack->Parameters.Read.Length)); -DPRINT("AdjOffset:%ld:%ld + Length:%ld = AdjExtent:%ld:%ld\n", - (unsigned long) AdjustedOffset.u.HighPart, - (unsigned long) AdjustedOffset.u.LowPart, - IrpStack->Parameters.Read.Length, - (unsigned long) AdjustedExtent.u.HighPart, - (unsigned long) AdjustedExtent.u.LowPart); - /*FIXME: this assumption will fail on drives bigger than 1TB */ - PartitionExtent.QuadPart = DeviceExtension->Offset + DeviceExtension->Size; - PartitionExtent = RtlExtendedIntegerMultiply(PartitionExtent, - DeviceExtension->BytesPerSector); - if ((AdjustedExtent.QuadPart > PartitionExtent.QuadPart) || - (IrpStack->Parameters.Read.Length & (DeviceExtension->BytesPerSector - 1))) - { - DPRINT("Request failed on bad parameters\n",0); - DPRINT("AdjustedExtent=%d:%d PartitionExtent=%d:%d ReadLength=%d\n", - (unsigned int) AdjustedExtent.u.HighPart, - (unsigned int) AdjustedExtent.u.LowPart, - (unsigned int) PartitionExtent.u.HighPart, - (unsigned int) PartitionExtent.u.LowPart, - IrpStack->Parameters.Read.Length); - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INVALID_PARAMETER; - } - - // Adjust operation to absolute sector offset - IrpStack->Parameters.Read.ByteOffset = AdjustedOffset; - - // Start the packet and insert the request in order of sector offset - assert(DeviceExtension->BytesPerSector == 512); - InsertKeyLI = RtlLargeIntegerShiftRight(IrpStack->Parameters.Read.ByteOffset, 9); - IrpInsertKey = InsertKeyLI.u.LowPart; - IoStartPacket(DeviceExtension->DeviceObject, Irp, &IrpInsertKey, NULL); - - DPRINT("Returning STATUS_PENDING\n"); - return STATUS_PENDING; -} - - -// IDEStartIo -// -// DESCRIPTION: -// Get the next requested I/O packet started -// -// RUN LEVEL: -// DISPATCH_LEVEL -// -// ARGUMENTS: -// Dispatch routine standard arguments -// -// RETURNS: -// NTSTATUS -// - -static VOID STDCALL -IDEStartIo(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - LARGE_INTEGER SectorLI; - PIO_STACK_LOCATION IrpStack; - PIDE_DEVICE_EXTENSION DeviceExtension; - KIRQL OldIrql; - - DPRINT("IDEStartIo() called!\n"); - - IrpStack = IoGetCurrentIrpStackLocation(Irp); - DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension; - - // FIXME: implement the supported functions - - switch (IrpStack->MajorFunction) - { - case IRP_MJ_READ: - case IRP_MJ_WRITE: - DeviceExtension->Operation = IrpStack->MajorFunction; - DeviceExtension->BytesRequested = IrpStack->Parameters.Read.Length; - assert(DeviceExtension->BytesPerSector == 512); - SectorLI = RtlLargeIntegerShiftRight(IrpStack->Parameters.Read.ByteOffset, 9); - DeviceExtension->StartingSector = SectorLI.u.LowPart; - if (DeviceExtension->BytesRequested > DeviceExtension->BytesPerSector * - IDE_MAX_SECTORS_PER_XFER) - { - DeviceExtension->BytesToTransfer = DeviceExtension->BytesPerSector * - IDE_MAX_SECTORS_PER_XFER; - } - else - { - DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested; - } - DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; - DeviceExtension->SectorsTransferred = 0; - DeviceExtension->TargetAddress = (BYTE *)MmGetSystemAddressForMdl(Irp->MdlAddress); - KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); - IoAllocateController(DeviceExtension->ControllerObject, - DeviceObject, - IDEAllocateController, - NULL); - KeLowerIrql(OldIrql); - break; - - default: - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - Irp->IoStatus.Information = 0; - KeBugCheck((ULONG)Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - IoStartNextPacket(DeviceObject, FALSE); - break; - } - DPRINT("IDEStartIo() finished!\n"); -} - -// IDEAllocateController - -static IO_ALLOCATION_ACTION STDCALL -IDEAllocateController(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID MapRegisterBase, - IN PVOID Ccontext) -{ - PIDE_DEVICE_EXTENSION DeviceExtension; - PIDE_CONTROLLER_EXTENSION ControllerExtension; - - DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension; - ControllerExtension = (PIDE_CONTROLLER_EXTENSION) - DeviceExtension->ControllerObject->ControllerExtension; - ControllerExtension->CurrentIrp = Irp; - ControllerExtension->Retries = 0; - return KeSynchronizeExecution(ControllerExtension->Interrupt, - IDEStartController, - DeviceExtension) ? KeepObject : - DeallocateObject; -} - -// IDEStartController - -static BOOLEAN STDCALL -IDEStartController(IN OUT PVOID Context) -{ - BYTE SectorCnt, SectorNum, CylinderLow, CylinderHigh; - BYTE DrvHead, Command; - BYTE Status; - int Retries; - ULONG StartingSector; - PIDE_DEVICE_EXTENSION DeviceExtension; - PIDE_CONTROLLER_EXTENSION ControllerExtension; - PIRP Irp; - - DeviceExtension = (PIDE_DEVICE_EXTENSION) Context; - ControllerExtension = (PIDE_CONTROLLER_EXTENSION) - DeviceExtension->ControllerObject->ControllerExtension; - ControllerExtension->OperationInProgress = TRUE; - ControllerExtension->DeviceForOperation = DeviceExtension; - - // Write controller registers to start opteration - StartingSector = DeviceExtension->StartingSector; - SectorCnt = DeviceExtension->BytesToTransfer / - DeviceExtension->BytesPerSector; - if (DeviceExtension->LBASupported) - { - SectorNum = StartingSector & 0xff; - CylinderLow = (StartingSector >> 8) & 0xff; - CylinderHigh = (StartingSector >> 16) & 0xff; - DrvHead = ((StartingSector >> 24) & 0x0f) | - (DeviceExtension->UnitNumber ? IDE_DH_DRV1 : 0) | - IDE_DH_LBA; - } - else - { - SectorNum = (StartingSector % DeviceExtension->SectorsPerLogTrk) + 1; - StartingSector /= DeviceExtension->SectorsPerLogTrk; - DrvHead = (StartingSector % DeviceExtension->LogicalHeads) | - (DeviceExtension->UnitNumber ? IDE_DH_DRV1 : 0); - StartingSector /= DeviceExtension->LogicalHeads; - CylinderLow = StartingSector & 0xff; - CylinderHigh = StartingSector >> 8; - } - Command = DeviceExtension->Operation == IRP_MJ_READ ? - IDE_CMD_READ : IDE_CMD_WRITE; - if (DrvHead & IDE_DH_LBA) - { - DPRINT("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n", - DeviceExtension->Operation == IRP_MJ_READ ? "READ" : "WRITE", - ControllerExtension->CommandPortBase, - DrvHead & IDE_DH_DRV1 ? 1 : 0, - ((DrvHead & 0x0f) << 24) + - (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum, - SectorCnt, - Command); - } - else - { - DPRINT("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n", - DeviceExtension->Operation == IRP_MJ_READ ? "READ" : "WRITE", - ControllerExtension->CommandPortBase, - DrvHead & IDE_DH_DRV1 ? 1 : 0, - CylinderHigh, - CylinderLow, - DrvHead & 0x0f, - SectorNum, - SectorCnt, - Command); - } - - /* wait for BUSY to clear */ - for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) - { - Status = IDEReadStatus(ControllerExtension->CommandPortBase); - if (!(Status & IDE_SR_BUSY)) - { - break; - } - ScsiPortStallExecution(10); - } - DPRINT ("status=%02x\n", Status); - DPRINT ("waited %ld usecs for busy to clear\n", Retries * 10); - if (Retries >= IDE_MAX_BUSY_RETRIES) - { - DPRINT ("Drive is BUSY for too long\n"); - if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES) - { - DbgPrint ("Max Retries on Drive reset reached, returning failure\n"); - Irp = ControllerExtension->CurrentIrp; - Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; - Irp->IoStatus.Information = 0; - - return FALSE; - } - else - { - DPRINT ("Beginning drive reset sequence\n"); - IDEBeginControllerReset(ControllerExtension); - - return TRUE; - } - } - - /* Select the desired drive */ - IDEWriteDriveHead(ControllerExtension->CommandPortBase, IDE_DH_FIXED | DrvHead); - - /* wait for BUSY to clear and DRDY to assert */ - for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) - { - Status = IDEReadStatus(ControllerExtension->CommandPortBase); - if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY)) - { - break; - } - ScsiPortStallExecution(10); - } - DPRINT ("waited %ld usecs for busy to clear after drive select\n", Retries * 10); - if (Retries >= IDE_MAX_BUSY_RETRIES) - { - DPRINT ("Drive is BUSY for too long after drive select\n"); - if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES) - { - DbgPrint ("Max Retries on Drive reset reached, returning failure\n"); - Irp = ControllerExtension->CurrentIrp; - Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; - Irp->IoStatus.Information = 0; - - return FALSE; - } - else - { - DPRINT ("Beginning drive reset sequence\n"); - IDEBeginControllerReset(ControllerExtension); - - return TRUE; - } - } - - /* Setup command parameters */ - IDEWritePrecomp(ControllerExtension->CommandPortBase, 0); - IDEWriteSectorCount(ControllerExtension->CommandPortBase, SectorCnt); - IDEWriteSectorNum(ControllerExtension->CommandPortBase, SectorNum); - IDEWriteCylinderHigh(ControllerExtension->CommandPortBase, CylinderHigh); - IDEWriteCylinderLow(ControllerExtension->CommandPortBase, CylinderLow); - IDEWriteDriveHead(ControllerExtension->CommandPortBase, IDE_DH_FIXED | DrvHead); - - /* Issue command to drive */ - IDEWriteCommand(ControllerExtension->CommandPortBase, Command); - ControllerExtension->TimerState = IDETimerCmdWait; - ControllerExtension->TimerCount = IDE_CMD_TIMEOUT; - - if (DeviceExtension->Operation == IRP_MJ_WRITE) - { - - // Wait for controller ready - for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++) - { - BYTE Status = IDEReadStatus(ControllerExtension->CommandPortBase); - if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR)) - { - break; - } - ScsiPortStallExecution(10); - } - if (Retries >= IDE_MAX_BUSY_RETRIES) - { - if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES) - { - Irp = ControllerExtension->CurrentIrp; - Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; - Irp->IoStatus.Information = 0; - - return FALSE; - } - else - { - IDEBeginControllerReset(ControllerExtension); - - return TRUE; - } - } - - // Load the first sector of data into the controller - IDEWriteBlock(ControllerExtension->CommandPortBase, - DeviceExtension->TargetAddress, - IDE_SECTOR_BUF_SZ); - DeviceExtension->TargetAddress += IDE_SECTOR_BUF_SZ; - DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector; - DeviceExtension->SectorsTransferred++; - } - DPRINT ("Command issued to drive, IDEStartController done\n"); - - return TRUE; -} - -// IDEBeginControllerReset - -VOID -IDEBeginControllerReset(PIDE_CONTROLLER_EXTENSION ControllerExtension) -{ - int Retries; - - DPRINT("Controller Reset initiated on %04x\n", - ControllerExtension->ControlPortBase); - - /* Assert drive reset line */ - DPRINT("Asserting reset line\n"); - IDEWriteDriveControl(ControllerExtension->ControlPortBase, IDE_DC_SRST); - - /* Wait for BSY assertion */ - DPRINT("Waiting for BSY assertion\n"); - for (Retries = 0; Retries < IDE_MAX_RESET_RETRIES; Retries++) - { - BYTE Status = IDEReadStatus(ControllerExtension->CommandPortBase); - if ((Status & IDE_SR_BUSY)) - { - break; - } - ScsiPortStallExecution(10); - } - if (Retries == IDE_MAX_RESET_RETRIES) - { - DPRINT("Timeout on BSY assertion\n"); - } - - /* Negate drive reset line */ - DPRINT("Negating reset line\n"); - IDEWriteDriveControl(ControllerExtension->ControlPortBase, 0); - - // FIXME: handle case of no device 0 - - /* Set timer to check for end of reset */ - ControllerExtension->TimerState = IDETimerResetWaitForBusyNegate; - ControllerExtension->TimerCount = IDE_RESET_BUSY_TIMEOUT; -} - -// IDEIsr -// -// DESCIPTION: -// Handle interrupts for IDE devices -// -// RUN LEVEL: -// DIRQL -// -// ARGUMENTS: -// IN PKINTERRUPT Interrupt The interrupt level in effect -// IN PVOID ServiceContext The driver supplied context -// (the controller extension) -// RETURNS: -// TRUE This ISR handled the interrupt -// FALSE Another ISR must handle this interrupt - -static BOOLEAN STDCALL -IDEIsr(IN PKINTERRUPT Interrupt, - IN PVOID ServiceContext) -{ - BOOLEAN IsLastBlock, AnErrorOccured, RequestIsComplete; - BYTE *TargetAddress; - int Retries; - NTSTATUS ErrorStatus; - ULONG ErrorInformation; - PIRP Irp; - PIDE_DEVICE_EXTENSION DeviceExtension; - PIDE_CONTROLLER_EXTENSION ControllerExtension; - - if (IDEInitialized == FALSE) - { - return FALSE; - } - DPRINT ("IDEIsr called\n"); - - ControllerExtension = (PIDE_CONTROLLER_EXTENSION) ServiceContext; - - // Read the status port to clear the interrtupt (even if it's not ours). - ControllerExtension->DeviceStatus = IDEReadStatus(ControllerExtension->CommandPortBase); - - // If the interrupt is not ours, get the heck outta dodge. - if (!ControllerExtension->OperationInProgress) - { - return FALSE; - } - - DeviceExtension = ControllerExtension->DeviceForOperation; - IsLastBlock = FALSE; - AnErrorOccured = FALSE; - RequestIsComplete = FALSE; - ErrorStatus = STATUS_SUCCESS; - ErrorInformation = 0; - - // Handle error condition if it exists - if (ControllerExtension->DeviceStatus & IDE_SR_ERR) - { - BYTE ErrorReg, SectorCount, SectorNum, CylinderLow, CylinderHigh; - BYTE DriveHead; - - // Log the error - ErrorReg = IDEReadError(ControllerExtension->CommandPortBase); - CylinderLow = IDEReadCylinderLow(ControllerExtension->CommandPortBase); - CylinderHigh = IDEReadCylinderHigh(ControllerExtension->CommandPortBase); - DriveHead = IDEReadDriveHead(ControllerExtension->CommandPortBase); - SectorCount = IDEReadSectorCount(ControllerExtension->CommandPortBase); - SectorNum = IDEReadSectorNum(ControllerExtension->CommandPortBase); - // FIXME: should use the NT error logging facility - DbgPrint ("IDE Error: OP:%02x STAT:%02x ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n", - DeviceExtension->Operation, - ControllerExtension->DeviceStatus, - ErrorReg, - CylinderLow, - CylinderHigh, - SectorCount, - SectorNum); - - // FIXME: should retry the command and perhaps recalibrate the drive - - // Set error status information - AnErrorOccured = TRUE; - ErrorStatus = STATUS_DISK_OPERATION_FAILED; - ErrorInformation = - (((((((CylinderHigh << 8) + CylinderLow) * - DeviceExtension->LogicalHeads) + - (DriveHead % DeviceExtension->LogicalHeads)) * - DeviceExtension->SectorsPerLogTrk) + SectorNum - 1) - - DeviceExtension->StartingSector) * DeviceExtension->BytesPerSector; - } - else - { - - // Check controller and setup for next transfer - switch (DeviceExtension->Operation) - { - case IRP_MJ_READ: - - // Update controller/device state variables - TargetAddress = DeviceExtension->TargetAddress; - DeviceExtension->TargetAddress += DeviceExtension->BytesPerSector; - DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector; - DeviceExtension->SectorsTransferred++; - - // Remember whether DRQ should be low at end (last block read) - IsLastBlock = DeviceExtension->BytesToTransfer == 0; - - // Wait for DRQ assertion - for (Retries = 0; Retries < IDE_MAX_DRQ_RETRIES && - !(IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ); - Retries++) - { - ScsiPortStallExecution(10); - } - - // Copy the block of data - IDEReadBlock(ControllerExtension->CommandPortBase, - TargetAddress, - IDE_SECTOR_BUF_SZ); - - // check DRQ - if (IsLastBlock) - { - for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES && - (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_BUSY); - Retries++) - { - ScsiPortStallExecution(10); - } - - // Check for data overrun - if (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ) - { - AnErrorOccured = TRUE; - ErrorStatus = STATUS_DATA_OVERRUN; - ErrorInformation = 0; - } - else - { - - // Setup next transfer or set RequestIsComplete - if (DeviceExtension->BytesRequested > - DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER) - { - DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred; - DeviceExtension->SectorsTransferred = 0; - DeviceExtension->BytesToTransfer = - DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER; - DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; - } - else if (DeviceExtension->BytesRequested > 0) - { - DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred; - DeviceExtension->SectorsTransferred = 0; - DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested; - DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; - } - else - { - RequestIsComplete = TRUE; - } - } - } - break; - - case IRP_MJ_WRITE: - - // check DRQ - if (DeviceExtension->BytesToTransfer == 0) - { - for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES && - (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_BUSY); - Retries++) - { - ScsiPortStallExecution(10); - } - - // Check for data overrun - if (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ) - { - AnErrorOccured = TRUE; - ErrorStatus = STATUS_DATA_OVERRUN; - ErrorInformation = 0; - } - else - { - - // Setup next transfer or set RequestIsComplete - IsLastBlock = TRUE; - if (DeviceExtension->BytesRequested > - DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER) - { - DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred; - DeviceExtension->SectorsTransferred = 0; - DeviceExtension->BytesToTransfer = - DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER; - DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; - } - else if (DeviceExtension->BytesRequested > 0) - { - DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred; - DeviceExtension->SectorsTransferred = 0; - DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested; - DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; - } - else - { - RequestIsComplete = TRUE; - } - } - } - else - { - - // Update controller/device state variables - TargetAddress = DeviceExtension->TargetAddress; - DeviceExtension->TargetAddress += DeviceExtension->BytesPerSector; - DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector; - DeviceExtension->SectorsTransferred++; - - // Write block to controller - IDEWriteBlock(ControllerExtension->CommandPortBase, - TargetAddress, - IDE_SECTOR_BUF_SZ); - } - break; - } - } - - // If there was an error or the request is done, complete the packet - if (AnErrorOccured || RequestIsComplete) - { - // Set the return status and info values - Irp = ControllerExtension->CurrentIrp; - Irp->IoStatus.Status = ErrorStatus; - Irp->IoStatus.Information = ErrorInformation; - - // Clear out controller fields - ControllerExtension->OperationInProgress = FALSE; - ControllerExtension->DeviceStatus = 0; - - // Queue the Dpc to finish up - IoRequestDpc(DeviceExtension->DeviceObject, - Irp, - ControllerExtension); - } - else if (IsLastBlock) - { - // Else more data is needed, setup next device I/O - IDEStartController((PVOID)DeviceExtension); - } - - return TRUE; -} - -// IDEDpcForIsr -// DESCRIPTION: -// -// RUN LEVEL: -// -// ARGUMENTS: -// IN PKDPC Dpc -// IN PDEVICE_OBJECT DpcDeviceObject -// IN PIRP DpcIrp -// IN PVOID DpcContext -// -static VOID -IDEDpcForIsr(IN PKDPC Dpc, - IN PDEVICE_OBJECT DpcDeviceObject, - IN PIRP DpcIrp, - IN PVOID DpcContext) -{ - DPRINT("IDEDpcForIsr()\n"); - IDEFinishOperation((PIDE_CONTROLLER_EXTENSION) DpcContext); -} - -// IDEFinishOperation - -static VOID -IDEFinishOperation(PIDE_CONTROLLER_EXTENSION ControllerExtension) -{ - PIDE_DEVICE_EXTENSION DeviceExtension; - PIRP Irp; - ULONG Operation; - - DeviceExtension = ControllerExtension->DeviceForOperation; - Irp = ControllerExtension->CurrentIrp; - Operation = DeviceExtension->Operation; - ControllerExtension->OperationInProgress = FALSE; - ControllerExtension->DeviceForOperation = 0; - ControllerExtension->CurrentIrp = 0; - - // Deallocate the controller - IoFreeController(DeviceExtension->ControllerObject); - - // Start the next packet - IoStartNextPacketByKey(DeviceExtension->DeviceObject, - FALSE, - DeviceExtension->StartingSector); - - // Issue completion of the current packet - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - - // Flush cache if necessary - if (Operation == IRP_MJ_READ) - { - KeFlushIoBuffers(Irp->MdlAddress, TRUE, FALSE); - } -} - -// IDEIoTimer -// 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 -IDEIoTimer(PDEVICE_OBJECT DeviceObject, - PVOID Context) -{ - PIDE_CONTROLLER_EXTENSION ControllerExtension; - - // Setup Extension pointer - ControllerExtension = (PIDE_CONTROLLER_EXTENSION) Context; - DPRINT("Timer activated for %04lx\n", ControllerExtension->CommandPortBase); - - // Handle state change if necessary - switch (ControllerExtension->TimerState) - { - case IDETimerResetWaitForBusyNegate: - if (!(IDEReadStatus(ControllerExtension->CommandPortBase) & - IDE_SR_BUSY)) - { - DPRINT("Busy line has negated, waiting for DRDY assert\n"); - ControllerExtension->TimerState = IDETimerResetWaitForDrdyAssert; - ControllerExtension->TimerCount = IDE_RESET_DRDY_TIMEOUT; - return; - } - break; - - case IDETimerResetWaitForDrdyAssert: - if (IDEReadStatus(ControllerExtension->CommandPortBase) & - IDE_SR_DRQ) - { - DPRINT("DRDY has asserted, reset complete\n"); - ControllerExtension->TimerState = IDETimerIdle; - ControllerExtension->TimerCount = 0; - - // FIXME: get diagnostic code from drive 0 - - /* Start current packet command again */ - if (!KeSynchronizeExecution(ControllerExtension->Interrupt, - IDEStartController, - ControllerExtension->DeviceForOperation)) - { - IDEFinishOperation(ControllerExtension); - } - return; - } - break; - - default: - break; - } - - // If we're counting down, then count. - if (ControllerExtension->TimerCount > 0) - { - ControllerExtension->TimerCount--; - - // Else we'll check the state and process if necessary - } - else - { - switch (ControllerExtension->TimerState) - { - case IDETimerIdle: - break; - - case IDETimerCmdWait: - /* Command timed out, reset drive and try again or fail */ - DPRINT("Timeout waiting for command completion\n"); - if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES) - { - if (ControllerExtension->CurrentIrp != NULL) - { - DbgPrint ("Max retries has been reached, IRP finished with error\n"); - ControllerExtension->CurrentIrp->IoStatus.Status = STATUS_IO_TIMEOUT; - ControllerExtension->CurrentIrp->IoStatus.Information = 0; - IDEFinishOperation(ControllerExtension); - } - ControllerExtension->TimerState = IDETimerIdle; - ControllerExtension->TimerCount = 0; - } - else - { - IDEBeginControllerReset(ControllerExtension); - } - break; - - case IDETimerResetWaitForBusyNegate: - case IDETimerResetWaitForDrdyAssert: - if (ControllerExtension->CurrentIrp != NULL) - { - DbgPrint ("Timeout waiting for drive reset, giving up on IRP\n"); - ControllerExtension->CurrentIrp->IoStatus.Status = - STATUS_IO_TIMEOUT; - ControllerExtension->CurrentIrp->IoStatus.Information = 0; - IDEFinishOperation(ControllerExtension); - } - ControllerExtension->TimerState = IDETimerIdle; - ControllerExtension->TimerCount = 0; - break; - } - } -} - static ULONG AtapiExecuteScsi(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, @@ -1929,78 +1070,33 @@ AtapiExecuteScsi(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, 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; - } + SrbStatus = AtapiInquiry(DeviceExtension, + Srb); break; - case SCSIOP_MODE_SENSE: + case SCSIOP_READ_CAPACITY: + SrbStatus = AtapiReadCapacity(DeviceExtension, + Srb); break; + case SCSIOP_READ: + case SCSIOP_WRITE: + SrbStatus = AtapiReadWrite(DeviceExtension, + Srb); + break; + + case SCSIOP_MODE_SENSE: + case SCSIOP_TEST_UNIT_READY: + case SCSIOP_VERIFY: + case SCSIOP_START_STOP_UNIT: + case SCSIOP_REQUEST_SENSE: + break; + + default: + DPRINT1("AtapiExecuteScsi():unknown command %x\n", + Srb->Cdb[0]); + SrbStatus = SRB_STATUS_INVALID_REQUEST; + break; } DPRINT1("AtapiExecuteScsi() done!\n"); @@ -2009,4 +1105,339 @@ AtapiExecuteScsi(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, } +static ULONG +AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PIDE_DRIVE_IDENTIFY DeviceParams; + PINQUIRYDATA InquiryData; + ULONG i; + + DPRINT("SCSIOP_INQUIRY: TargetId: %lu\n", Srb->TargetId); + + if ((Srb->PathId != 0) || + (Srb->TargetId > 1) || + (Srb->Lun != 0) || + (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)) + { + return(SRB_STATUS_SELECTION_TIMEOUT); + } + + InquiryData = Srb->DataBuffer; + DeviceParams = &DeviceExtension->DeviceParams[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; + } + + DPRINT("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]; + } + + return(SRB_STATUS_SUCCESS); +} + + +static ULONG +AtapiReadCapacity(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PREAD_CAPACITY_DATA CapacityData; + PIDE_DRIVE_IDENTIFY DeviceParams; + ULONG LastSector; + + DPRINT("SCSIOP_READ_CAPACITY: TargetId: %lu\n", Srb->TargetId); + + if ((Srb->PathId != 0) || + (Srb->TargetId > 1) || + (Srb->Lun != 0) || + (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)) + { + return(SRB_STATUS_SELECTION_TIMEOUT); + } + + + CapacityData = (PREAD_CAPACITY_DATA)Srb->DataBuffer; + DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId]; + + /* Set sector (block) size to 512 bytes (big-endian). */ + CapacityData->BytesPerBlock = 0x20000; + + /* Calculate last sector (big-endian). */ + if (DeviceParams->Capabilities & IDE_DRID_LBA_SUPPORTED) + { + LastSector = (ULONG)((DeviceParams->TMSectorCountHi << 16) + + DeviceParams->TMSectorCountLo) - 1; + } + else + { + LastSector = (ULONG)(DeviceParams->LogicalCyls * + DeviceParams->LogicalHeads * + DeviceParams->SectorsPerTrack)-1; + } + + CapacityData->LogicalBlockAddress = (((PUCHAR)&LastSector)[0] << 24) | + (((PUCHAR)&LastSector)[1] << 16) | + (((PUCHAR)&LastSector)[2] << 8) | + ((PUCHAR)&LastSector)[3]; + + DPRINT("LastCount: %lu (%08lx / %08lx)\n", + LastSector, + LastSector, + CapacityData->LogicalBlockAddress); + + return(SRB_STATUS_SUCCESS); +} + + +static ULONG +AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PIDE_DRIVE_IDENTIFY DeviceParams; + + ULONG StartingSector,i; + ULONG SectorCount; + UCHAR CylinderHigh; + UCHAR CylinderLow; + UCHAR DrvHead; + UCHAR SectorNumber; + UCHAR Command; + ULONG Retries; + UCHAR Status; + + + DPRINT1("AtapiReadWrite() called!\n"); + + if ((Srb->PathId != 0) || + (Srb->TargetId > 1) || + (Srb->Lun != 0) || + (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)) + { + return(SRB_STATUS_SELECTION_TIMEOUT); + } + + DPRINT1("SCSIOP_WRITE: TargetId: %lu\n", + Srb->TargetId); + + DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId]; + + /* Get starting sector number from CDB. */ + StartingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 | + ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 | + ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 | + ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24; + + SectorCount = (Srb->DataTransferLength + DeviceParams->BytesPerSector - 1) / + DeviceParams->BytesPerSector; + + DPRINT1("Starting sector %lu Number of bytes %lu Sectors %lu\n", + StartingSector, + Srb->DataTransferLength, + SectorCount); + + if (DeviceParams->Capabilities & IDE_DRID_LBA_SUPPORTED) + { + SectorNumber = StartingSector & 0xff; + CylinderLow = (StartingSector >> 8) & 0xff; + CylinderHigh = (StartingSector >> 16) & 0xff; + DrvHead = ((StartingSector >> 24) & 0x0f) | + (Srb->TargetId ? IDE_DH_DRV1 : 0) | + IDE_DH_LBA; + } + else + { + SectorNumber = (StartingSector % DeviceParams->SectorsPerTrack) + 1; + StartingSector /= DeviceParams->SectorsPerTrack; + DrvHead = (StartingSector % DeviceParams->LogicalHeads) | + (Srb->TargetId ? IDE_DH_DRV1 : 0); + StartingSector /= DeviceParams->LogicalHeads; + CylinderLow = StartingSector & 0xff; + CylinderHigh = StartingSector >> 8; + } + + + if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) + { + Command = IDE_CMD_READ; + } + else + { + Command = IDE_CMD_WRITE; + } + + if (DrvHead & IDE_DH_LBA) + { + DPRINT1("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n", + (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE", + DeviceExtension->CommandPortBase, + DrvHead & IDE_DH_DRV1 ? 1 : 0, + ((DrvHead & 0x0f) << 24) + + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNumber, + SectorCount, + Command); + } + else + { + DPRINT1("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n", + (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE", + DeviceExtension->CommandPortBase, + DrvHead & IDE_DH_DRV1 ? 1 : 0, + CylinderHigh, + CylinderLow, + DrvHead & 0x0f, + SectorNumber, + SectorCount, + Command); + } + + /* Set pointer to data buffer. */ + DeviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer; + + + + + /* wait for BUSY to clear */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(DeviceExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY)) + { + break; + } + ScsiPortStallExecution(10); + } + DPRINT ("status=%02x\n", Status); + DPRINT ("waited %ld usecs for busy to clear\n", Retries * 10); + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT ("Drive is BUSY for too long\n"); + return(SRB_STATUS_BUSY); +#if 0 + if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES) + { + DbgPrint ("Max Retries on Drive reset reached, returning failure\n"); + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; + Irp->IoStatus.Information = 0; + + return FALSE; + } + else + { + DPRINT ("Beginning drive reset sequence\n"); + IDEBeginControllerReset(ControllerExtension); + + return TRUE; + } +#endif + } + + /* Select the desired drive */ + IDEWriteDriveHead(DeviceExtension->CommandPortBase, + IDE_DH_FIXED | DrvHead); + + /* wait for BUSY to clear and DRDY to assert */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(DeviceExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY)) + { + break; + } + ScsiPortStallExecution(10); + } + DPRINT ("waited %ld usecs for busy to clear after drive select\n", Retries * 10); + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT ("Drive is BUSY for too long after drive select\n"); + return(SRB_STATUS_BUSY); +#if 0 + if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES) + { + DbgPrint ("Max Retries on Drive reset reached, returning failure\n"); + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; + Irp->IoStatus.Information = 0; + + return FALSE; + } + else + { + DPRINT ("Beginning drive reset sequence\n"); + IDEBeginControllerReset(ControllerExtension); + + return TRUE; + } +#endif + } + + /* Indicate expecting an interrupt. */ + DeviceExtension->ExpectingInterrupt = TRUE; + + /* Setup command parameters */ + IDEWritePrecomp(DeviceExtension->CommandPortBase, 0); + IDEWriteSectorCount(DeviceExtension->CommandPortBase, SectorCount); + IDEWriteSectorNum(DeviceExtension->CommandPortBase, SectorNumber); + IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, CylinderHigh); + IDEWriteCylinderLow(DeviceExtension->CommandPortBase, CylinderLow); + IDEWriteDriveHead(DeviceExtension->CommandPortBase, IDE_DH_FIXED | DrvHead); + + /* Issue command to drive */ + IDEWriteCommand(DeviceExtension->CommandPortBase, Command); +// ControllerExtension->TimerState = IDETimerCmdWait; +// ControllerExtension->TimerCount = IDE_CMD_TIMEOUT; + + + + if (Srb->SrbFlags & SRB_FLAGS_DATA_IN == 0) + { + DPRINT1("Write not implemented yet!\n"); + } + + DPRINT1("AtapiReadWrite() done!\n"); + + /* Wait for interrupt. */ + return(SRB_STATUS_PENDING); +} + /* EOF */ diff --git a/reactos/drivers/storage/atapi/partitio.h b/reactos/drivers/storage/atapi/partitio.h deleted file mode 100644 index 06841ee39fa..00000000000 --- a/reactos/drivers/storage/atapi/partitio.h +++ /dev/null @@ -1,41 +0,0 @@ -/** -*** Partition.h - defines and structs for harddrive partition info -*** -*** 05/30/98 RJJ Created -**/ - -#ifndef __PARTITION_H -#define __PARTITION_H - -#define PARTITION_MAGIC 0xaa55 -#define PART_MAGIC_OFFSET 0x01fe -#define PARTITION_OFFSET 0x01be -#define PARTITION_TBL_SIZE 4 -#define PTCHSToLBA(c, h, s, scnt, hcnt) ((s) & 0x3f) + \ - (scnt) * ( (h) + (hcnt) * ((c) | (((s) & 0xc0) << 2))) -#define PTLBAToCHS(lba, c, h, s, scnt, hcnt) ( \ - (s) = (lba) % (scnt) + 1, \ - (lba) /= (scnt), \ - (h) = (lba) % (hcnt), \ - (lba) /= (heads), \ - (c) = (lba) & 0xff, \ - (s) |= ((lba) >> 2) & 0xc0) - - -typedef struct Partition { - unsigned char BootFlags; - unsigned char StartingHead; - unsigned char StartingSector; - unsigned char StartingCylinder; - unsigned char PartitionType; - unsigned char EndingHead; - unsigned char EndingSector; - unsigned char EndingCylinder; - unsigned int StartingBlock; - unsigned int SectorCount; - -} PARTITION; - -#endif // PARTITION_H - - diff --git a/reactos/drivers/storage/class2/class2.c b/reactos/drivers/storage/class2/class2.c index 297647c707b..0ea7816f151 100644 --- a/reactos/drivers/storage/class2/class2.c +++ b/reactos/drivers/storage/class2/class2.c @@ -1,4 +1,4 @@ -/* $Id: class2.c,v 1.3 2002/01/27 01:25:01 ekohl Exp $ +/* $Id: class2.c,v 1.4 2002/01/31 14:57:58 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -9,8 +9,7 @@ /* * TODO: - * - ScsiClassClaimDevice() must send a claim/unclaim request to - * scsiport.sys. + * - a lot ;-) */ /* INCLUDES *****************************************************************/ @@ -111,7 +110,199 @@ VOID STDCALL ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp) { - UNIMPLEMENTED; + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); + PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); + LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; + LARGE_INTEGER startingBlock; + PSCSI_REQUEST_BLOCK Srb; + PCDB Cdb; + ULONG logicalBlockAddress; + USHORT transferBlocks; + + // + // Calculate relative sector address. + // + +// logicalBlockAddress = (ULONG)(Int64ShrlMod32(startingOffset.QuadPart, deviceExtension->SectorShift)); + + startingBlock.QuadPart = startingOffset.QuadPart >> deviceExtension->SectorShift; + logicalBlockAddress = (ULONG)startingBlock.u.LowPart; + + // + // Allocate an Srb. + // + +// Srb = ExAllocateFromNPagedLookasideList(&deviceExtension->SrbLookasideListHead); + Srb = ExAllocatePool(NonPagedPool, + sizeof(SCSI_REQUEST_BLOCK)); + + + Srb->SrbFlags = 0; + + // + // Write length to SRB. + // + + Srb->Length = sizeof(SCSI_REQUEST_BLOCK); //SCSI_REQUEST_BLOCK_SIZE; + + // + // Set up IRP Address. + // + + Srb->OriginalRequest = Irp; + + // + // Set up target ID and logical unit number. + // + + Srb->PathId = deviceExtension->PathId; + Srb->TargetId = deviceExtension->TargetId; + Srb->Lun = deviceExtension->Lun; + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + Srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); + + // + // Save byte count of transfer in SRB Extension. + // + + Srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; + + // + // Initialize the queue actions field. + // + + Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; + + // + // Queue sort key is Relative Block Address. + // + + Srb->QueueSortKey = logicalBlockAddress; + + // + // Indicate auto request sense by specifying buffer and size. + // + + Srb->SenseInfoBuffer = deviceExtension->SenseData; + Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; + + // + // Set timeout value of one unit per 64k bytes of data. + // + + Srb->TimeOutValue = ((Srb->DataTransferLength + 0xFFFF) >> 16) * + deviceExtension->TimeOutValue; + + // + // Zero statuses. + // + + Srb->SrbStatus = 0; + Srb->ScsiStatus = 0; + Srb->NextSrb = 0; + + // + // Indicate that 10-byte CDB's will be used. + // + + Srb->CdbLength = 10; + + // + // Fill in CDB fields. + // + + Cdb = (PCDB)Srb->Cdb; + + // + // Zero 12 bytes for Atapi Packets + // + + RtlZeroMemory(Cdb, + MAXIMUM_CDB_SIZE); + + Cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; + transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift); + + // + // Move little endian values into CDB in big endian format. + // + + Cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; + Cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; + Cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; + Cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; + + Cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1; + Cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0; + + // + // Set transfer direction flag and Cdb command. + // + + if (currentIrpStack->MajorFunction == IRP_MJ_READ) + { + DPRINT1("ScsiClassBuildRequest: Read Command\n"); + + Srb->SrbFlags |= SRB_FLAGS_DATA_IN; + Cdb->CDB10.OperationCode = SCSIOP_READ; + } + else + { + DPRINT("ScsiClassBuildRequest: Write Command\n"); + + Srb->SrbFlags |= SRB_FLAGS_DATA_OUT; + Cdb->CDB10.OperationCode = SCSIOP_WRITE; + } + + // + // If this is not a write-through request, then allow caching. + // + +#if 0 + if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) + { + Srb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE; + } + else + { + /* If write caching is enable then force media access in the cdb. */ + if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) + { + Cdb->CDB10.ForceUnitAccess = TRUE; + } + } +#endif + + /* Or in the default flags from the device object. */ + Srb->SrbFlags |= deviceExtension->SrbFlags; + + // + // Set up major SCSI function. + // + + nextIrpStack->MajorFunction = IRP_MJ_SCSI; + + // + // Save SRB address in next stack for port driver. + // + + nextIrpStack->Parameters.Scsi.Srb = Srb; + + // + // Save retry count in current IRP stack. + // +#if 0 + currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; +#endif + + /* Set up IoCompletion routine address. */ + IoSetCompletionRoutine(Irp, + ScsiClassIoComplete, + Srb, + TRUE, + TRUE, + TRUE); } @@ -121,6 +312,11 @@ ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject, BOOLEAN Release, PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL) { + PIO_STACK_LOCATION IoStack; + IO_STATUS_BLOCK IoStatusBlock; + SCSI_REQUEST_BLOCK Srb; + KEVENT Event; + PIRP Irp; NTSTATUS Status; DPRINT1("ScsiClassClaimDevice() called\n"); @@ -128,19 +324,70 @@ ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject, if (NewPortDeviceObject != NULL) *NewPortDeviceObject = NULL; + /* Initialize an SRB */ + RtlZeroMemory(&Srb, + sizeof(SCSI_REQUEST_BLOCK)); + Srb.Length = SCSI_REQUEST_BLOCK_SIZE; + Srb.PathId = LunInfo->PathId; + Srb.TargetId = LunInfo->TargetId; + Srb.Lun = LunInfo->Lun; + Srb.Function = + (Release == TRUE) ? SRB_FUNCTION_RELEASE_DEVICE : SRB_FUNCTION_CLAIM_DEVICE; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE, + PortDeviceObject, + NULL, + 0, + NULL, + 0, + TRUE, + &Event, + &IoStatusBlock); + if (Irp == NULL) + { + DPRINT1("Failed to allocate Irp!\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Link Srb and Irp */ + IoStack = IoGetNextIrpStackLocation(Irp); + IoStack->Parameters.Scsi.Srb = &Srb; + Srb.OriginalRequest = Irp; + + /* Call SCSI port driver */ + Status = IoCallDriver(PortDeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Suspended, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + if (Release == TRUE) { ObDereferenceObject(PortDeviceObject); return(STATUS_SUCCESS); } - ObReferenceObjectByPointer(PortDeviceObject, - 0, - NULL, - KernelMode); +// Status = ObReferenceObjectByPointer(Srb.DataBuffer, + Status = ObReferenceObjectByPointer(PortDeviceObject, + 0, + NULL, + KernelMode); if (NewPortDeviceObject != NULL) - *NewPortDeviceObject = PortDeviceObject; + { +// *NewPortDeviceObject = Srb.DataBuffer; + *NewPortDeviceObject = PortDeviceObject; + } return(STATUS_SUCCESS); } @@ -153,20 +400,65 @@ ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, IN OUT PDEVICE_OBJECT *DeviceObject, IN PCLASS_INIT_DATA InitializationData) { + PDEVICE_OBJECT InternalDeviceObject; + PDEVICE_EXTENSION DeviceExtension; + ANSI_STRING AnsiName; + UNICODE_STRING DeviceName; + NTSTATUS Status; + DPRINT1("ScsiClassCreateDeviceObject() called\n"); -#if 0 + *DeviceObject = NULL; + + RtlInitAnsiString(&AnsiName, + ObjectNameBuffer); + + Status = RtlAnsiStringToUnicodeString(&DeviceName, + &AnsiName, + TRUE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT1("Device name: '%wZ'\n", &DeviceName); + Status = IoCreateDevice(DriverObject, InitializationData->DeviceExtensionSize, - &UnicodeName, + &DeviceName, InitializationData->DeviceType, InitializationData->DeviceCharacteristics, FALSE, &InternalDeviceObject); -#endif + if (NT_SUCCESS(Status)) + { + PDEVICE_EXTENSION deviceExtension = InternalDeviceObject->DeviceExtension; + DeviceExtension->ClassError = InitializationData->ClassError; + DeviceExtension->ClassReadWriteVerification = InitializationData->ClassReadWriteVerification; + DeviceExtension->ClassFindDevices = InitializationData->ClassFindDevices; + DeviceExtension->ClassDeviceControl = InitializationData->ClassDeviceControl; + DeviceExtension->ClassShutdownFlush = InitializationData->ClassShutdownFlush; + DeviceExtension->ClassCreateClose = InitializationData->ClassCreateClose; + DeviceExtension->ClassStartIo = InitializationData->ClassStartIo; - return(STATUS_SUCCESS); + DeviceExtension->MediaChangeCount = 0; + + if (PhysicalDeviceObject != NULL) + { + DeviceExtension->PhysicalDevice = PhysicalDeviceObject; + } + else + { + DeviceExtension->PhysicalDevice = InternalDeviceObject; + } + + *DeviceObject = InternalDeviceObject; + } + + RtlFreeUnicodeString(&DeviceName); + + return(Status); } @@ -458,7 +750,14 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) { - UNIMPLEMENTED; + DPRINT1("ScsiClassIoComplete() called\n"); + + if (Irp->PendingReturned) + { + IoMarkIrpPending(Irp); + } + + return(Irp->IoStatus.Status); } @@ -491,7 +790,81 @@ ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath) NTSTATUS STDCALL ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject) { - UNIMPLEMENTED; + PDEVICE_EXTENSION DeviceExtension; + PREAD_CAPACITY_DATA CapacityBuffer; + SCSI_REQUEST_BLOCK Srb; + PCDB Cdb; + NTSTATUS Status; + ULONG LastSector; + ULONG SectorSize; + + DPRINT1("ScsiClassReadDriveCapacity() called\n"); + + DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + CapacityBuffer = ExAllocatePool(NonPagedPool, //NonPagedPoolCacheAligned, + sizeof(READ_CAPACITY_DATA)); + if (CapacityBuffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK)); + + Srb.CdbLength = 10; + Srb.TimeOutValue = DeviceExtension->TimeOutValue; + + Cdb = (PCDB)Srb.Cdb; + Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; + + + Status = ScsiClassSendSrbSynchronous(DeviceObject, + &Srb, + CapacityBuffer, + sizeof(READ_CAPACITY_DATA), + FALSE); + DPRINT("Status: %lx\n", Status); + DPRINT("Srb: %p\n", &Srb); + if (NT_SUCCESS(Status)) + { + SectorSize = (((PUCHAR)&CapacityBuffer->BytesPerBlock)[0] << 24) | + (((PUCHAR)&CapacityBuffer->BytesPerBlock)[1] << 16) | + (((PUCHAR)&CapacityBuffer->BytesPerBlock)[2] << 8) | + ((PUCHAR)&CapacityBuffer->BytesPerBlock)[3]; + + + LastSector = (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[0] << 24) | + (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[1] << 16) | + (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[2] << 8) | + ((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[3]; + + DeviceExtension->DiskGeometry->BytesPerSector = SectorSize; + + DeviceExtension->PartitionLength.QuadPart = (LONGLONG)(LastSector + 1); + WHICH_BIT(DeviceExtension->DiskGeometry->BytesPerSector, DeviceExtension->SectorShift); + DeviceExtension->PartitionLength.QuadPart = + (DeviceExtension->PartitionLength.QuadPart << DeviceExtension->SectorShift); + + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + { + DeviceExtension->DiskGeometry->MediaType = RemovableMedia; + } + else + { + DeviceExtension->DiskGeometry->MediaType = FixedMedia; + } + DeviceExtension->DiskGeometry->Cylinders.QuadPart = (LONGLONG)((LastSector + 1)/(32 * 64)); + DeviceExtension->DiskGeometry->SectorsPerTrack = 32; + DeviceExtension->DiskGeometry->TracksPerCylinder = 64; + + DPRINT1("SectorSize: %lu SectorCount: %lu\n", SectorSize, LastSector + 1); + } + + ExFreePool(CapacityBuffer); + + DPRINT1("ScsiClassReadDriveCapacity() done\n"); + + return(Status); } @@ -521,7 +894,103 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, ULONG BufferLength, BOOLEAN WriteToDevice) { - UNIMPLEMENTED; + PDEVICE_EXTENSION DeviceExtension; + IO_STATUS_BLOCK IoStatusBlock; + PIO_STACK_LOCATION IoStack; + ULONG RequestType; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + + + DPRINT1("ScsiClassSendSrbSynchronous() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + + Srb->PathId = DeviceExtension->PathId; + Srb->TargetId = DeviceExtension->TargetId; + Srb->Lun = DeviceExtension->Lun; + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + + /* FIXME: more srb initialization required? */ + + + if (BufferAddress == NULL) + { + BufferLength = 0; + RequestType = IOCTL_SCSI_EXECUTE_NONE; + Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER; + } + else + { + if (WriteToDevice == TRUE) + { + RequestType = IOCTL_SCSI_EXECUTE_OUT; + Srb->SrbFlags = SRB_FLAGS_DATA_OUT; + } + else + { + RequestType = IOCTL_SCSI_EXECUTE_IN; + Srb->SrbFlags = SRB_FLAGS_DATA_IN; + } + } + + Srb->DataTransferLength = BufferLength; + Srb->DataBuffer = BufferAddress; + + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildDeviceIoControlRequest(RequestType, + DeviceExtension->PortDeviceObject, + NULL, + 0, + BufferAddress, + BufferLength, + TRUE, + &Event, + &IoStatusBlock); + if (Irp == NULL) + { + DPRINT("IoBuildDeviceIoControlRequest() failed\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* FIXME: more irp initialization required? */ + + + /* Attach Srb to the Irp */ + IoStack = IoGetNextIrpStackLocation(Irp); + IoStack->Parameters.Scsi.Srb = Srb; + Srb->OriginalRequest = Irp; + + + /* Call the SCSI port driver */ + Status = IoCallDriver(DeviceExtension->PortDeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Suspended, + KernelMode, + FALSE, + NULL); + } + + if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) + { + + } + else + { + Status = STATUS_SUCCESS; + } + + DPRINT1("ScsiClassSendSrbSynchronous() done\n"); + + return(Status); } @@ -540,10 +1009,15 @@ static NTSTATUS STDCALL ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { -// PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PDEVICE_EXTENSION DeviceExtension; -// if (deviceExtension->ClassCreateClose) -// return(deviceExtension->ClassCreateClose(DeviceObject, Irp)); + DPRINT("ScsiClassCreateClose() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + + if (DeviceExtension->ClassCreateClose) + return(DeviceExtension->ClassCreateClose(DeviceObject, + Irp)); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; @@ -557,11 +1031,98 @@ static NTSTATUS STDCALL ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + ULONG TransferLength; + ULONG TransferPages; + NTSTATUS Status; - return(STATUS_SUCCESS); + DPRINT1("ScsiClassReadWrite() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + TransferLength = IrpStack->Parameters.Read.Length; + + + + if ((DeviceObject->Flags & DO_VERIFY_VOLUME) && + !(IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) + { + IoSetHardErrorOrVerifyDevice(Irp, + DeviceObject); + + Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(STATUS_VERIFY_REQUIRED); + } + +#if 0 + /* let the class driver perform its verification */ + Status = DeviceExtension->ClassReadWriteVerification(DeviceObject, + Irp); + if (!NT_SUCCESS(Status)) + { + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(Status); + } + else if (Status == STATUS_PENDING) + { + IoMarkIrpPending(Irp); + return(STATUS_PENDING); + } +#endif + + /* Finish a zero-byte transfer. */ + if (TransferLength == 0) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(STATUS_SUCCESS); + } + + if (DeviceExtension->ClassStartIo != NULL) + { + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject, + Irp, + NULL, + NULL); + + return(STATUS_PENDING); + } + + IoMarkIrpPending(Irp); + + /* Adjust partition-relative starting offset to absolute offset */ + IrpStack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->StartingOffset.QuadPart; + + /* Calculate number of pages in this transfer. */ + TransferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), + IrpStack->Parameters.Read.Length); + +#if 0 + if (IrpStack->Parameters.Read.Length > maximumTransferLength || + TransferPages > DeviceExtension->PortCapabilities->MaximumPhysicalPages) + { + + } +#endif + + ScsiClassBuildRequest(DeviceObject, + Irp); + + DPRINT1("ScsiClassReadWrite() done\n"); + + /* Call the port driver */ + return(IoCallDriver(DeviceExtension->PortDeviceObject, + Irp)); } @@ -569,6 +1130,8 @@ static NTSTATUS STDCALL ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + DPRINT1("ScsiClassScsiDispatch() called\n"); + Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -581,6 +1144,8 @@ static NTSTATUS STDCALL ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + DPRINT1("ScsiClassDeviceDispatch() called\n"); + Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -593,6 +1158,8 @@ static NTSTATUS STDCALL ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + DPRINT1("ScsiClassShutdownFlush() called\n"); + Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); diff --git a/reactos/drivers/storage/disk/disk.c b/reactos/drivers/storage/disk/disk.c index 847640cfdd6..9c44fb4769f 100644 --- a/reactos/drivers/storage/disk/disk.c +++ b/reactos/drivers/storage/disk/disk.c @@ -1,4 +1,4 @@ -/* $Id: disk.c,v 1.3 2002/01/27 01:25:15 ekohl Exp $ +/* $Id: disk.c,v 1.4 2002/01/31 14:58:12 ekohl Exp $ * */ @@ -33,6 +33,10 @@ DiskClassFindDevices(PDRIVER_OBJECT DriverObject, BOOLEAN STDCALL DiskClassCheckDevice(IN PINQUIRYDATA InquiryData); +NTSTATUS STDCALL +DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + static NTSTATUS DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, @@ -40,7 +44,7 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PortDeviceObject, IN ULONG PortNumber, IN ULONG DiskNumber, - IN PIO_SCSI_CAPABILITIES Capabilities, /* what's this used for? */ + IN PIO_SCSI_CAPABILITIES Capabilities, IN PSCSI_INQUIRY_DATA InquiryData, IN PCLASS_INIT_DATA InitializationData); @@ -90,12 +94,12 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, sizeof(CLASS_INIT_DATA)); InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA); - InitData.DeviceExtensionSize = sizeof(DISK_DEVICE_EXTENSION); + InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DEVICE_EXTENSION); InitData.DeviceType = FILE_DEVICE_DISK; InitData.DeviceCharacteristics = 0; InitData.ClassError = NULL; // DiskClassProcessError; - InitData.ClassReadWriteVerification = NULL; // DiskClassReadWriteCheck; + InitData.ClassReadWriteVerification = DiskClassCheckReadWrite; InitData.ClassFindDeviceCallBack = DiskClassCheckDevice; InitData.ClassFindDevices = DiskClassFindDevices; InitData.ClassDeviceControl = DiskClassDeviceControl; @@ -275,8 +279,17 @@ DiskClassCheckDevice(IN PINQUIRYDATA InquiryData) } +NTSTATUS STDCALL +DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT1("DiskClassCheckReadWrite() called\n"); -// IDECreateDevices + return(STATUS_SUCCESS); +} + + +// DiskClassCreateDeviceObject // // DESCRIPTION: // Create the raw device and any partition devices on this drive @@ -306,27 +319,26 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PortDeviceObject, IN ULONG PortNumber, IN ULONG DiskNumber, - IN PIO_SCSI_CAPABILITIES Capabilities, /* what's this used for? */ + IN PIO_SCSI_CAPABILITIES Capabilities, IN PSCSI_INQUIRY_DATA InquiryData, - IN PCLASS_INIT_DATA InitializationData) /* what's this used for? */ + IN PCLASS_INIT_DATA InitializationData) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeDeviceDirName; WCHAR NameBuffer[80]; CHAR NameBuffer2[80]; PDEVICE_OBJECT DiskDeviceObject; + PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */ + PDRIVE_LAYOUT_INFORMATION PartitionList = NULL; HANDLE Handle; #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; + PPARTITION_INFORMATION PartitionEntry; + ULONG PartitionNumber; NTSTATUS Status; DPRINT1("DiskClassCreateDeviceObjects() called\n"); @@ -380,42 +392,138 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, { DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status); + /* Release (unclaim) the disk */ ScsiClassClaimDevice(PortDeviceObject, InquiryData, TRUE, NULL); + + /* Delete the harddisk device directory */ ZwMakeTemporaryObject(Handle); ZwClose(Handle); return(Status); } - -#if 0 - /* Read partition table */ - Status = IoReadPartitionTable(DiskDeviceObject, - DrvParms.BytesPerSector, - TRUE, - &PartitionList); - if (!NT_SUCCESS(Status)) + DiskDeviceObject->Flags |= DO_DIRECT_IO; + if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia) { - DbgPrint("IoReadPartitionTable() failed\n"); - return FALSE; + DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; + } + DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1; + + if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement) + { + DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement; } - DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount); - for (i=0;i < PartitionList->PartitionCount; i++) + DiskDeviceExtension = DiskDeviceObject->DeviceExtension; + + DiskDeviceExtension->LockCount = 0; + DiskDeviceExtension->DeviceNumber = DiskNumber; + DiskDeviceExtension->PortDeviceObject = PortDeviceObject; + + /* FIXME: Not yet! Will cause pointer corruption! */ +// DiskDeviceExtension->PortCapabilities = PortCapabilities; + + DiskDeviceExtension->StartingOffset.QuadPart = 0; + DiskDeviceExtension->PortNumber = (UCHAR)PortNumber; + DiskDeviceExtension->PathId = InquiryData->PathId; + DiskDeviceExtension->TargetId = InquiryData->TargetId; + DiskDeviceExtension->Lun = InquiryData->Lun; + + + /* Get disk geometry */ + DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool, + sizeof(DISK_GEOMETRY)); + if (DiskDeviceExtension->DiskGeometry == NULL) { - PartitionEntry = &PartitionList->PartitionEntry[i]; + DPRINT1("Failed to allocate geometry buffer!\n"); - 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*/); + IoDeleteDevice(DiskDeviceObject); + /* Release (unclaim) the disk */ + ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + TRUE, + NULL); + + /* Delete the harddisk device directory */ + ZwMakeTemporaryObject(Handle); + ZwClose(Handle); + + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Read the drive's capacity */ + Status = ScsiClassReadDriveCapacity(DiskDeviceObject); + if (!NT_SUCCESS(Status) && + (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0) + { + DPRINT1("Failed to retrieve drive capacity!\n"); + return(STATUS_SUCCESS); + } + else + { + /* Clear the verify flag for non-removable media drives. */ + DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME; + } + + DPRINT1("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector); + + /* Read partition table */ + Status = IoReadPartitionTable(DiskDeviceObject, + DiskDeviceExtension->DiskGeometry->BytesPerSector, + TRUE, + &PartitionList); + + DPRINT1("IoReadPartitionTable(): Status: %lx\n", Status); + + if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) && + DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + { + if (!NT_SUCCESS(Status)) + { + /* Drive is not ready. */ +// diskData->DriveNotReady = TRUE; + } + else + { + ExFreePool(PartitionList); + } + + /* Allocate a partition list for a single entry. */ + PartitionList = ExAllocatePool(NonPagedPool, + sizeof(DRIVE_LAYOUT_INFORMATION)); + if (PartitionList != NULL) + { + RtlZeroMemory(PartitionList, + sizeof(DRIVE_LAYOUT_INFORMATION)); + PartitionList->PartitionCount = 1; + + Status = STATUS_SUCCESS; + } + } + + if (NT_SUCCESS(Status)) + { + DPRINT1("Read partition table!\n"); + + DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount); + + for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++) + { + PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber]; + + DPRINT1("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n", + PartitionNumber, + PartitionEntry->PartitionNumber, + PartitionEntry->BootIndicator, + PartitionEntry->PartitionType, + PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/, + PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/); + +#if 0 /* Create device for partition */ Status = IDECreateDevice(DriverObject, &PartitionDeviceObject, @@ -432,14 +540,15 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, break; } - /* Initialize pointer to disk device extension */ - PartitionDeviceExtension = (PIDE_DEVICE_EXTENSION)PartitionDeviceObject->DeviceExtension; - PartitionDeviceExtension->DiskExtension = (PVOID)DiskDeviceExtension; - } - - if (PartitionList != NULL) - ExFreePool(PartitionList); + /* Initialize pointer to disk device extension */ + PartitionDeviceExtension = (PIDE_DEVICE_EXTENSION)PartitionDeviceObject->DeviceExtension; + PartitionDeviceExtension->DiskExtension = (PVOID)DiskDeviceExtension; #endif + } + + + ExFreePool(PartitionList); + } DPRINT1("DiskClassCreateDeviceObjects() done\n"); diff --git a/reactos/drivers/storage/include/class2.h b/reactos/drivers/storage/include/class2.h index 86377a683fa..073d33af993 100644 --- a/reactos/drivers/storage/include/class2.h +++ b/reactos/drivers/storage/include/class2.h @@ -1,4 +1,4 @@ -/* $Id: class2.h,v 1.2 2002/01/14 01:44:18 ekohl Exp $ +/* $Id: class2.h,v 1.3 2002/01/31 14:58:34 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -151,7 +151,63 @@ ScsiClassInitialize(IN PVOID Argument1, IN PVOID Argument2, IN PCLASS_INIT_DATA InitializationData); +VOID STDCALL +ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension, + ULONG NumberElements); +NTSTATUS STDCALL +ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +BOOLEAN STDCALL +ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + UCHAR MajorFunctionCode, + ULONG IoDeviceCode, + ULONG RetryCount, + NTSTATUS *Status); + +NTSTATUS STDCALL +ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +NTSTATUS STDCALL +ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +ULONG STDCALL +ScsiClassModeSense(PDEVICE_OBJECT DeviceObject, + CHAR ModeSenseBuffer, + ULONG Length, + UCHAR PageMode); + +ULONG STDCALL +ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath); + +NTSTATUS STDCALL +ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject); + +NTSTATUS STDCALL +ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + PIRP Irp, + PVOID BufferAddress, + ULONG BufferLength, + BOOLEAN WriteToDevice); + +NTSTATUS STDCALL +ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + PVOID BufferAddress, + ULONG BufferLength, + BOOLEAN WriteToDevice); + +VOID STDCALL +ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + ULONG MaximumBytes); #endif /* __STORAGE_INCLUDE_CLASS2_H */ diff --git a/reactos/drivers/storage/include/scsi.h b/reactos/drivers/storage/include/scsi.h index 62f1a8e1c03..7d3b60c6ca3 100644 --- a/reactos/drivers/storage/include/scsi.h +++ b/reactos/drivers/storage/include/scsi.h @@ -1,4 +1,4 @@ -/* $Id: scsi.h,v 1.3 2002/01/27 01:25:33 ekohl Exp $ +/* $Id: scsi.h,v 1.4 2002/01/31 14:58:34 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -147,301 +147,299 @@ typedef union _CDB struct _READ_CD { UCHAR OperationCode; - UCHAR Reserved0 : 2; - UCHAR ExpectedSectorType : 3; - UCHAR Reserved1 : 3; + 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 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; - // - // Plextor Read CD-DA - // - - struct _PLXTR_READ_CDDA { - UCHAR OperationCode; - UCHAR Reserved0 : 5; - UCHAR LogicalUnitNumber :3; - UCHAR LogicalBlockByte0; - UCHAR LogicalBlockByte1; - UCHAR LogicalBlockByte2; - UCHAR LogicalBlockByte3; - UCHAR TransferBlockByte0; - UCHAR TransferBlockByte1; - UCHAR TransferBlockByte2; - UCHAR TransferBlockByte3; - UCHAR SubCode; - UCHAR Control; + /* Plextor Read CD-DA */ + struct _PLXTR_READ_CDDA + { + UCHAR OperationCode; + UCHAR Reserved0:5; + UCHAR LogicalUnitNumber:3; + UCHAR LogicalBlockByte0; + UCHAR LogicalBlockByte1; + UCHAR LogicalBlockByte2; + UCHAR LogicalBlockByte3; + UCHAR TransferBlockByte0; + UCHAR TransferBlockByte1; + UCHAR TransferBlockByte2; + UCHAR TransferBlockByte3; + UCHAR SubCode; + UCHAR Control; } PLXTR_READ_CDDA, *PPLXTR_READ_CDDA; - // - // NEC Read CD-DA - // - - struct _NEC_READ_CDDA { - UCHAR OperationCode; - UCHAR Reserved0; - UCHAR LogicalBlockByte0; - UCHAR LogicalBlockByte1; - UCHAR LogicalBlockByte2; - UCHAR LogicalBlockByte3; - UCHAR Reserved1; - UCHAR TransferBlockByte0; - UCHAR TransferBlockByte1; - UCHAR Control; + /* NEC Read CD-DA */ + struct _NEC_READ_CDDA + { + UCHAR OperationCode; + UCHAR Reserved0; + UCHAR LogicalBlockByte0; + UCHAR LogicalBlockByte1; + UCHAR LogicalBlockByte2; + UCHAR LogicalBlockByte3; + UCHAR Reserved1; + UCHAR TransferBlockByte0; + UCHAR TransferBlockByte1; + UCHAR Control; } NEC_READ_CDDA, *PNEC_READ_CDDA; - // - // Mode sense - // - - struct _MODE_SENSE { - UCHAR OperationCode; - UCHAR Reserved1 : 3; - UCHAR Dbd : 1; - UCHAR Reserved2 : 1; - UCHAR LogicalUnitNumber : 3; - UCHAR PageCode : 6; - UCHAR Pc : 2; - UCHAR Reserved3; - UCHAR AllocationLength; - UCHAR Control; + /* Mode sense */ + struct _MODE_SENSE + { + UCHAR OperationCode; + UCHAR Reserved1:3; + UCHAR Dbd:1; + UCHAR Reserved2:1; + UCHAR LogicalUnitNumber:3; + UCHAR PageCode:6; + UCHAR Pc:2; + UCHAR Reserved3; + UCHAR AllocationLength; + UCHAR Control; } MODE_SENSE, *PMODE_SENSE; - struct _MODE_SENSE10 { - UCHAR OperationCode; - UCHAR Reserved1 : 3; - UCHAR Dbd : 1; - UCHAR Reserved2 : 1; - UCHAR LogicalUnitNumber : 3; - UCHAR PageCode : 6; - UCHAR Pc : 2; - UCHAR Reserved3[4]; - UCHAR AllocationLength[2]; - UCHAR Control; + struct _MODE_SENSE10 + { + UCHAR OperationCode; + UCHAR Reserved1:3; + UCHAR Dbd:1; + UCHAR Reserved2:1; + UCHAR LogicalUnitNumber:3; + UCHAR PageCode:6; + UCHAR Pc:2; + UCHAR Reserved3[4]; + UCHAR AllocationLength[2]; + UCHAR Control; } MODE_SENSE10, *PMODE_SENSE10; - // - // Mode select - // - - struct _MODE_SELECT { - UCHAR OperationCode; - UCHAR SPBit : 1; - UCHAR Reserved1 : 3; - UCHAR PFBit : 1; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2[2]; - UCHAR ParameterListLength; - UCHAR Control; + /* Mode select */ + struct _MODE_SELECT + { + UCHAR OperationCode; + UCHAR SPBit:1; + UCHAR Reserved1:3; + UCHAR PFBit:1; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[2]; + UCHAR ParameterListLength; + UCHAR Control; } MODE_SELECT, *PMODE_SELECT; - struct _MODE_SELECT10 { - UCHAR OperationCode; - UCHAR SPBit : 1; - UCHAR Reserved1 : 3; - UCHAR PFBit : 1; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2[5]; - UCHAR ParameterListLength[2]; - UCHAR Control; + struct _MODE_SELECT10 + { + UCHAR OperationCode; + UCHAR SPBit:1; + UCHAR Reserved1:3; + UCHAR PFBit:1; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[5]; + UCHAR ParameterListLength[2]; + UCHAR Control; } MODE_SELECT10, *PMODE_SELECT10; - struct _LOCATE { - UCHAR OperationCode; - UCHAR Immediate : 1; - UCHAR CPBit : 1; - UCHAR BTBit : 1; - UCHAR Reserved1 : 2; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved3; - UCHAR LogicalBlockAddress[4]; - UCHAR Reserved4; - UCHAR Partition; - UCHAR Control; + struct _LOCATE + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR CPBit:1; + UCHAR BTBit:1; + UCHAR Reserved1:2; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved3; + UCHAR LogicalBlockAddress[4]; + UCHAR Reserved4; + UCHAR Partition; + UCHAR Control; } LOCATE, *PLOCATE; - struct _LOGSENSE { - UCHAR OperationCode; - UCHAR SPBit : 1; - UCHAR PPCBit : 1; - UCHAR Reserved1 : 3; - UCHAR LogicalUnitNumber : 3; - UCHAR PageCode : 6; - UCHAR PCBit : 2; - UCHAR Reserved2; - UCHAR Reserved3; - UCHAR ParameterPointer[2]; // [0]=MSB, [1]=LSB - UCHAR AllocationLength[2]; // [0]=MSB, [1]=LSB - UCHAR Control; + struct _LOGSENSE + { + UCHAR OperationCode; + UCHAR SPBit:1; + UCHAR PPCBit:1; + UCHAR Reserved1:3; + UCHAR LogicalUnitNumber:3; + UCHAR PageCode:6; + UCHAR PCBit:2; + UCHAR Reserved2; + UCHAR Reserved3; + UCHAR ParameterPointer[2]; /* [0]=MSB, [1]=LSB */ + UCHAR AllocationLength[2]; /* [0]=MSB, [1]=LSB */ + UCHAR Control; } LOGSENSE, *PLOGSENSE; - struct _PRINT { - UCHAR OperationCode; - UCHAR Reserved : 5; - UCHAR LogicalUnitNumber : 3; - UCHAR TransferLength[3]; - UCHAR Control; + struct _PRINT + { + UCHAR OperationCode; + UCHAR Reserved:5; + UCHAR LogicalUnitNumber:3; + UCHAR TransferLength[3]; + UCHAR Control; } PRINT, *PPRINT; - struct _SEEK { - UCHAR OperationCode; - UCHAR Reserved1 : 5; - UCHAR LogicalUnitNumber : 3; - UCHAR LogicalBlockAddress[4]; - UCHAR Reserved2[3]; - UCHAR Control; + struct _SEEK + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR LogicalBlockAddress[4]; + UCHAR Reserved2[3]; + UCHAR Control; } SEEK, *PSEEK; - struct _ERASE { - UCHAR OperationCode; - UCHAR Long : 1; - UCHAR Immediate : 1; - UCHAR Reserved1 : 3; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2[3]; - UCHAR Control; + struct _ERASE + { + UCHAR OperationCode; + UCHAR Long:1; + UCHAR Immediate:1; + UCHAR Reserved1:3; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[3]; + UCHAR Control; } ERASE, *PERASE; struct _START_STOP - { - UCHAR OperationCode; - UCHAR Immediate: 1; - UCHAR Reserved1 : 4; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2[2]; - UCHAR Start : 1; - UCHAR LoadEject : 1; - UCHAR Reserved3 : 6; - UCHAR Control; + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR Reserved1:4; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[2]; + UCHAR Start:1; + UCHAR LoadEject:1; + UCHAR Reserved3:6; + UCHAR Control; } START_STOP, *PSTART_STOP; - struct _MEDIA_REMOVAL { - UCHAR OperationCode; - UCHAR Reserved1 : 5; - UCHAR LogicalUnitNumber : 3; - UCHAR Reserved2[2]; - UCHAR Prevent; - UCHAR Control; + struct _MEDIA_REMOVAL + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[2]; + UCHAR Prevent; + UCHAR Control; } MEDIA_REMOVAL, *PMEDIA_REMOVAL; - // - // Tape CDBs - // - - struct _SEEK_BLOCK { - UCHAR OperationCode; - UCHAR Immediate : 1; - UCHAR Reserved1 : 7; - UCHAR BlockAddress[3]; - UCHAR Link : 1; - UCHAR Flag : 1; - UCHAR Reserved2 : 4; - UCHAR VendorUnique : 2; + /* Tape CDBs */ + struct _SEEK_BLOCK + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR Reserved1:7; + UCHAR BlockAddress[3]; + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved2:4; + UCHAR VendorUnique:2; } SEEK_BLOCK, *PSEEK_BLOCK; - struct _REQUEST_BLOCK_ADDRESS { - UCHAR OperationCode; - UCHAR Reserved1[3]; - UCHAR AllocationLength; - UCHAR Link : 1; - UCHAR Flag : 1; - UCHAR Reserved2 : 4; - UCHAR VendorUnique : 2; + struct _REQUEST_BLOCK_ADDRESS + { + UCHAR OperationCode; + UCHAR Reserved1[3]; + UCHAR AllocationLength; + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved2:4; + UCHAR VendorUnique:2; } REQUEST_BLOCK_ADDRESS, *PREQUEST_BLOCK_ADDRESS; - struct _PARTITION { - UCHAR OperationCode; - UCHAR Immediate : 1; - UCHAR Sel: 1; - UCHAR PartitionSelect : 6; - UCHAR Reserved1[3]; - UCHAR Control; + struct _PARTITION + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR Sel:1; + UCHAR PartitionSelect:6; + UCHAR Reserved1[3]; + UCHAR Control; } PARTITION, *PPARTITION; - struct _WRITE_TAPE_MARKS { - UCHAR OperationCode; - UCHAR Immediate : 1; - UCHAR WriteSetMarks: 1; - UCHAR Reserved : 3; - UCHAR LogicalUnitNumber : 3; - UCHAR TransferLength[3]; - UCHAR Control; + struct _WRITE_TAPE_MARKS + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR WriteSetMarks:1; + UCHAR Reserved:3; + UCHAR LogicalUnitNumber:3; + UCHAR TransferLength[3]; + UCHAR Control; } WRITE_TAPE_MARKS, *PWRITE_TAPE_MARKS; - struct _SPACE_TAPE_MARKS { - UCHAR OperationCode; - UCHAR Code : 3; - UCHAR Reserved : 2; - UCHAR LogicalUnitNumber : 3; - UCHAR NumMarksMSB ; - UCHAR NumMarks; - UCHAR NumMarksLSB; - union { - UCHAR value; - struct { - UCHAR Link : 1; - UCHAR Flag : 1; - UCHAR Reserved : 4; - UCHAR VendorUnique : 2; - } Fields; - } Byte6; + struct _SPACE_TAPE_MARKS + { + UCHAR OperationCode; + UCHAR Code:3; + UCHAR Reserved:2; + UCHAR LogicalUnitNumber:3; + UCHAR NumMarksMSB ; + UCHAR NumMarks; + UCHAR NumMarksLSB; + union + { + UCHAR value; + struct + { + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved:4; + UCHAR VendorUnique:2; + } Fields; + } Byte6; } SPACE_TAPE_MARKS, *PSPACE_TAPE_MARKS; - // - // Read tape position - // - - struct _READ_POSITION { - UCHAR Operation; - UCHAR BlockType:1; - UCHAR Reserved1:4; - UCHAR Lun:3; - UCHAR Reserved2[7]; - UCHAR Control; + /* Read tape position */ + struct _READ_POSITION + { + UCHAR Operation; + UCHAR BlockType:1; + UCHAR Reserved1:4; + UCHAR Lun:3; + UCHAR Reserved2[7]; + UCHAR Control; } READ_POSITION, *PREAD_POSITION; - // - // ReadWrite for Tape - // - - struct _CDB6READWRITETAPE { - UCHAR OperationCode; - UCHAR VendorSpecific : 5; - UCHAR Reserved : 3; - UCHAR TransferLenMSB; - UCHAR TransferLen; - UCHAR TransferLenLSB; - UCHAR Link : 1; - UCHAR Flag : 1; - UCHAR Reserved1 : 4; - UCHAR VendorUnique : 2; + /* ReadWrite for Tape */ + struct _CDB6READWRITETAPE + { + UCHAR OperationCode; + UCHAR VendorSpecific:5; + UCHAR Reserved:3; + UCHAR TransferLenMSB; + UCHAR TransferLen; + UCHAR TransferLenLSB; + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved1:4; + UCHAR VendorUnique:2; } CDB6READWRITETAPE, *PCDB6READWRITETAPE; - // - // Atapi 2.5 Changer 12-byte CDBs - // - - struct _LOAD_UNLOAD { - UCHAR OperationCode; - UCHAR Immediate : 1; - UCHAR Reserved1 : 7; - UCHAR Reserved2[2]; - UCHAR Start : 1; - UCHAR LoadEject : 1; - UCHAR Reserved3: 6; - UCHAR Reserved4[3]; - UCHAR Slot; - UCHAR Reserved5[3]; + /* Atapi 2.5 Changer 12-byte CDBs */ + struct _LOAD_UNLOAD + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR Reserved1:7; + UCHAR Reserved2[2]; + UCHAR Start:1; + UCHAR LoadEject:1; + UCHAR Reserved3:6; + UCHAR Reserved4[3]; + UCHAR Slot; + UCHAR Reserved5[3]; } LOAD_UNLOAD, *PLOAD_UNLOAD; struct _MECH_STATUS @@ -455,6 +453,7 @@ typedef union _CDB /* Command Descriptor Block constants */ + #define CDB6GENERIC_LENGTH 6 #define CDB10GENERIC_LENGTH 10 #define CDB12GENERIC_LENGTH 12 @@ -462,7 +461,9 @@ typedef union _CDB #define SETBITON 1 #define SETBITOFF 0 + /* Mode Sense/Select page constants */ + #define MODE_PAGE_ERROR_RECOVERY 0x01 #define MODE_PAGE_DISCONNECT 0x02 #define MODE_PAGE_FORMAT_DEVICE 0x03 @@ -484,9 +485,8 @@ typedef union _CDB #define MODE_PAGE_DATA_COMPRESS 0x0f #define MODE_PAGE_CAPABILITIES 0x2A -// -// SCSI CDB operation codes -// + +/* SCSI CDB operation codes */ #define SCSIOP_TEST_UNIT_READY 0x00 #define SCSIOP_REZERO_UNIT 0x01 @@ -569,7 +569,6 @@ typedef union _CDB #define CDB_RETURN_ON_COMPLETION 0 #define CDB_RETURN_IMMEDIATE 1 -// end_ntminitape // // CDB Force media access used in extended read and write commands. @@ -637,31 +636,34 @@ typedef union _CDB // #pragma pack (1) -typedef struct _SCSI_EXTENDED_MESSAGE { - UCHAR InitialMessageCode; - UCHAR MessageLength; - UCHAR MessageType; - union _EXTENDED_ARGUMENTS { +typedef struct _SCSI_EXTENDED_MESSAGE +{ + UCHAR InitialMessageCode; + UCHAR MessageLength; + UCHAR MessageType; + union _EXTENDED_ARGUMENTS + { + struct + { + UCHAR Modifier[4]; + } Modify; - struct { - UCHAR Modifier[4]; - } Modify; + struct + { + UCHAR TransferPeriod; + UCHAR ReqAckOffset; + } Synchronous; - struct { - UCHAR TransferPeriod; - UCHAR ReqAckOffset; - } Synchronous; - - struct{ - UCHAR Width; - } Wide; - }ExtendedArguments; + struct + { + UCHAR Width; + } Wide; + } ExtendedArguments; }SCSI_EXTENDED_MESSAGE, *PSCSI_EXTENDED_MESSAGE; #pragma pack () -// -// SCSI bus status codes. -// + +/* SCSI bus status codes */ #define SCSISTAT_GOOD 0x00 #define SCSISTAT_CHECK_CONDITION 0x02 @@ -691,7 +693,7 @@ typedef struct _SCSI_EXTENDED_MESSAGE { #define START_UNIT_CODE 0x01 #define STOP_UNIT_CODE 0x00 -// begin_ntminitape + // // Inquiry buffer structure. This is the data returned from the target @@ -863,14 +865,13 @@ typedef struct _SENSE_DATA #define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES ((FILE_DEVICE_SCSI << 16) + 0x0508) #define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS ((FILE_DEVICE_SCSI << 16) + 0x0509) -// -// Read Capacity Data - returned in Big Endian format -// + +/* Read Capacity Data - returned in Big Endian format */ typedef struct _READ_CAPACITY_DATA { ULONG LogicalBlockAddress; - ULONG BytesPerBlock; + ULONG BytesPerBlock; } READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA; @@ -880,10 +881,11 @@ typedef struct _READ_CAPACITY_DATA // size for a TAPE device. // -typedef struct _READ_BLOCK_LIMITS { - UCHAR Reserved; - UCHAR BlockMaximumSize[3]; - UCHAR BlockMinimumSize[2]; +typedef struct _READ_BLOCK_LIMITS +{ + UCHAR Reserved; + UCHAR BlockMaximumSize[3]; + UCHAR BlockMinimumSize[2]; } READ_BLOCK_LIMITS_DATA, *PREAD_BLOCK_LIMITS_DATA; @@ -895,19 +897,21 @@ typedef struct _READ_BLOCK_LIMITS { // Define Mode parameter header. // -typedef struct _MODE_PARAMETER_HEADER { - UCHAR ModeDataLength; - UCHAR MediumType; - UCHAR DeviceSpecificParameter; - UCHAR BlockDescriptorLength; +typedef struct _MODE_PARAMETER_HEADER +{ + UCHAR ModeDataLength; + UCHAR MediumType; + UCHAR DeviceSpecificParameter; + UCHAR BlockDescriptorLength; }MODE_PARAMETER_HEADER, *PMODE_PARAMETER_HEADER; -typedef struct _MODE_PARAMETER_HEADER10 { - UCHAR ModeDataLength[2]; - UCHAR MediumType; - UCHAR DeviceSpecificParameter; - UCHAR Reserved[2]; - UCHAR BlockDescriptorLength[2]; +typedef struct _MODE_PARAMETER_HEADER10 +{ + UCHAR ModeDataLength[2]; + UCHAR MediumType; + UCHAR DeviceSpecificParameter; + UCHAR Reserved[2]; + UCHAR BlockDescriptorLength[2]; }MODE_PARAMETER_HEADER10, *PMODE_PARAMETER_HEADER10; #define MODE_FD_SINGLE_SIDE 0x01 @@ -920,11 +924,12 @@ typedef struct _MODE_PARAMETER_HEADER10 { // Define the mode parameter block. // -typedef struct _MODE_PARAMETER_BLOCK { - UCHAR DensityCode; - UCHAR NumberOfBlocks[3]; - UCHAR Reserved; - UCHAR BlockLength[3]; +typedef struct _MODE_PARAMETER_BLOCK +{ + UCHAR DensityCode; + UCHAR NumberOfBlocks[3]; + UCHAR Reserved; + UCHAR BlockLength[3]; }MODE_PARAMETER_BLOCK, *PMODE_PARAMETER_BLOCK; @@ -949,178 +954,181 @@ typedef struct _MODE_DISCONNECT_PAGE // Define mode caching page. // -typedef struct _MODE_CACHING_PAGE { - UCHAR PageCode : 6; - UCHAR Reserved : 1; - UCHAR PageSavable : 1; - UCHAR PageLength; - UCHAR ReadDisableCache : 1; - UCHAR MultiplicationFactor : 1; - UCHAR WriteCacheEnable : 1; - UCHAR Reserved2 : 5; - UCHAR WriteRetensionPriority : 4; - UCHAR ReadRetensionPriority : 4; - UCHAR DisablePrefetchTransfer[2]; - UCHAR MinimumPrefetch[2]; - UCHAR MaximumPrefetch[2]; - UCHAR MaximumPrefetchCeiling[2]; +typedef struct _MODE_CACHING_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR ReadDisableCache:1; + UCHAR MultiplicationFactor:1; + UCHAR WriteCacheEnable:1; + UCHAR Reserved2:5; + UCHAR WriteRetensionPriority:4; + UCHAR ReadRetensionPriority:4; + UCHAR DisablePrefetchTransfer[2]; + UCHAR MinimumPrefetch[2]; + UCHAR MaximumPrefetch[2]; + UCHAR MaximumPrefetchCeiling[2]; }MODE_CACHING_PAGE, *PMODE_CACHING_PAGE; // // Define mode flexible disk page. // -typedef struct _MODE_FLEXIBLE_DISK_PAGE { - UCHAR PageCode : 6; - UCHAR Reserved : 1; - UCHAR PageSavable : 1; - UCHAR PageLength; - UCHAR TransferRate[2]; - UCHAR NumberOfHeads; - UCHAR SectorsPerTrack; - UCHAR BytesPerSector[2]; - UCHAR NumberOfCylinders[2]; - UCHAR StartWritePrecom[2]; - UCHAR StartReducedCurrent[2]; - UCHAR StepRate[2]; - UCHAR StepPluseWidth; - UCHAR HeadSettleDelay[2]; - UCHAR MotorOnDelay; - UCHAR MotorOffDelay; - UCHAR Reserved2 : 5; - UCHAR MotorOnAsserted : 1; - UCHAR StartSectorNumber : 1; - UCHAR TrueReadySignal : 1; - UCHAR StepPlusePerCyclynder : 4; - UCHAR Reserved3 : 4; - UCHAR WriteCompenstation; - UCHAR HeadLoadDelay; - UCHAR HeadUnloadDelay; - UCHAR Pin2Usage : 4; - UCHAR Pin34Usage : 4; - UCHAR Pin1Usage : 4; - UCHAR Pin4Usage : 4; - UCHAR MediumRotationRate[2]; - UCHAR Reserved4[2]; +typedef struct _MODE_FLEXIBLE_DISK_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR TransferRate[2]; + UCHAR NumberOfHeads; + UCHAR SectorsPerTrack; + UCHAR BytesPerSector[2]; + UCHAR NumberOfCylinders[2]; + UCHAR StartWritePrecom[2]; + UCHAR StartReducedCurrent[2]; + UCHAR StepRate[2]; + UCHAR StepPluseWidth; + UCHAR HeadSettleDelay[2]; + UCHAR MotorOnDelay; + UCHAR MotorOffDelay; + UCHAR Reserved2:5; + UCHAR MotorOnAsserted:1; + UCHAR StartSectorNumber:1; + UCHAR TrueReadySignal:1; + UCHAR StepPlusePerCyclynder:4; + UCHAR Reserved3:4; + UCHAR WriteCompenstation; + UCHAR HeadLoadDelay; + UCHAR HeadUnloadDelay; + UCHAR Pin2Usage:4; + UCHAR Pin34Usage:4; + UCHAR Pin1Usage:4; + UCHAR Pin4Usage:4; + UCHAR MediumRotationRate[2]; + UCHAR Reserved4[2]; }MODE_FLEXIBLE_DISK_PAGE, *PMODE_FLEXIBLE_DISK_PAGE; // // Define mode format page. // -typedef struct _MODE_FORMAT_PAGE { - UCHAR PageCode : 6; - UCHAR Reserved : 1; - UCHAR PageSavable : 1; - UCHAR PageLength; - UCHAR TracksPerZone[2]; - UCHAR AlternateSectorsPerZone[2]; - UCHAR AlternateTracksPerZone[2]; - UCHAR AlternateTracksPerLogicalUnit[2]; - UCHAR SectorsPerTrack[2]; - UCHAR BytesPerPhysicalSector[2]; - UCHAR Interleave[2]; - UCHAR TrackSkewFactor[2]; - UCHAR CylinderSkewFactor[2]; - UCHAR Reserved2 : 4; - UCHAR SurfaceFirst : 1; - UCHAR RemovableMedia : 1; - UCHAR HardSectorFormating : 1; - UCHAR SoftSectorFormating : 1; - UCHAR Reserved3[2]; +typedef struct _MODE_FORMAT_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR TracksPerZone[2]; + UCHAR AlternateSectorsPerZone[2]; + UCHAR AlternateTracksPerZone[2]; + UCHAR AlternateTracksPerLogicalUnit[2]; + UCHAR SectorsPerTrack[2]; + UCHAR BytesPerPhysicalSector[2]; + UCHAR Interleave[2]; + UCHAR TrackSkewFactor[2]; + UCHAR CylinderSkewFactor[2]; + UCHAR Reserved2:4; + UCHAR SurfaceFirst:1; + UCHAR RemovableMedia:1; + UCHAR HardSectorFormating:1; + UCHAR SoftSectorFormating:1; + UCHAR Reserved3[2]; }MODE_FORMAT_PAGE, *PMODE_FORMAT_PAGE; // // Define rigid disk driver geometry page. // -typedef struct _MODE_RIGID_GEOMETRY_PAGE { - UCHAR PageCode : 6; - UCHAR Reserved : 1; - UCHAR PageSavable : 1; - UCHAR PageLength; - UCHAR NumberOfCylinders[2]; - UCHAR NumberOfHeads; - UCHAR StartWritePrecom[2]; - UCHAR StartReducedCurrent[2]; - UCHAR DriveStepRate[2]; - UCHAR LandZoneCyclinder[2]; - UCHAR RotationalPositionLock : 2; - UCHAR Reserved2 : 6; - UCHAR RotationOffset; - UCHAR Reserved3; - UCHAR RoataionRate[2]; - UCHAR Reserved4[2]; +typedef struct _MODE_RIGID_GEOMETRY_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR NumberOfCylinders[2]; + UCHAR NumberOfHeads; + UCHAR StartWritePrecom[2]; + UCHAR StartReducedCurrent[2]; + UCHAR DriveStepRate[2]; + UCHAR LandZoneCyclinder[2]; + UCHAR RotationalPositionLock:2; + UCHAR Reserved2:6; + UCHAR RotationOffset; + UCHAR Reserved3; + UCHAR RoataionRate[2]; + UCHAR Reserved4[2]; }MODE_RIGID_GEOMETRY_PAGE, *PMODE_RIGID_GEOMETRY_PAGE; // // Define read write recovery page // -typedef struct _MODE_READ_WRITE_RECOVERY_PAGE { - - UCHAR PageCode : 6; - UCHAR Reserved1 : 1; - UCHAR PSBit : 1; - UCHAR PageLength; - UCHAR DCRBit : 1; - UCHAR DTEBit : 1; - UCHAR PERBit : 1; - UCHAR EERBit : 1; - UCHAR RCBit : 1; - UCHAR TBBit : 1; - UCHAR ARRE : 1; - UCHAR AWRE : 1; - UCHAR ReadRetryCount; - UCHAR Reserved4[4]; - UCHAR WriteRetryCount; - UCHAR Reserved5[3]; - +typedef struct _MODE_READ_WRITE_RECOVERY_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved1:1; + UCHAR PSBit:1; + UCHAR PageLength; + UCHAR DCRBit:1; + UCHAR DTEBit:1; + UCHAR PERBit:1; + UCHAR EERBit:1; + UCHAR RCBit:1; + UCHAR TBBit:1; + UCHAR ARRE:1; + UCHAR AWRE:1; + UCHAR ReadRetryCount; + UCHAR Reserved4[4]; + UCHAR WriteRetryCount; + UCHAR Reserved5[3]; } MODE_READ_WRITE_RECOVERY_PAGE, *PMODE_READ_WRITE_RECOVERY_PAGE; // // Define read recovery page - cdrom // -typedef struct _MODE_READ_RECOVERY_PAGE { - - UCHAR PageCode : 6; - UCHAR Reserved1 : 1; - UCHAR PSBit : 1; - UCHAR PageLength; - UCHAR DCRBit : 1; - UCHAR DTEBit : 1; - UCHAR PERBit : 1; - UCHAR Reserved2 : 1; - UCHAR RCBit : 1; - UCHAR TBBit : 1; - UCHAR Reserved3 : 2; - UCHAR ReadRetryCount; - UCHAR Reserved4[4]; - +typedef struct _MODE_READ_RECOVERY_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved1:1; + UCHAR PSBit:1; + UCHAR PageLength; + UCHAR DCRBit:1; + UCHAR DTEBit:1; + UCHAR PERBit:1; + UCHAR Reserved2:1; + UCHAR RCBit:1; + UCHAR TBBit:1; + UCHAR Reserved3:2; + UCHAR ReadRetryCount; + UCHAR Reserved4[4]; } MODE_READ_RECOVERY_PAGE, *PMODE_READ_RECOVERY_PAGE; // // Define CD-ROM Capabilities and Mechanical Status Page. // -typedef struct _MODE_CAPABILITIES_PAGE2 { - UCHAR PageCode : 6; - UCHAR Reserved1 : 1; - UCHAR PSBit : 1; - UCHAR PageLength; - UCHAR Reserved2[2]; - UCHAR Capabilities[4]; - UCHAR MaximumSpeedSupported[2]; - UCHAR Reserved3; - UCHAR NumberVolumeLevels; - UCHAR BufferSize[2]; - UCHAR CurrentSpeed[2]; - UCHAR Reserved4; - UCHAR Reserved5 : 1; - UCHAR DigitalOutput : 4; - UCHAR Reserved6 : 3; - UCHAR Reserved7[2]; +typedef struct _MODE_CAPABILITIES_PAGE2 +{ + UCHAR PageCode:6; + UCHAR Reserved1:1; + UCHAR PSBit:1; + UCHAR PageLength; + UCHAR Reserved2[2]; + UCHAR Capabilities[4]; + UCHAR MaximumSpeedSupported[2]; + UCHAR Reserved3; + UCHAR NumberVolumeLevels; + UCHAR BufferSize[2]; + UCHAR CurrentSpeed[2]; + UCHAR Reserved4; + UCHAR Reserved5:1; + UCHAR DigitalOutput:4; + UCHAR Reserved6:3; + UCHAR Reserved7[2]; } MODE_CAPABILITIES_PAGE2, *PMODE_CAPABILITIES_PAGE2; // @@ -1150,14 +1158,12 @@ typedef struct _MODE_CAPABILITIES_PAGE2 { #define MODE_HEADER_LENGTH 4 #define MODE_HEADER_LENGTH10 8 -typedef struct _MODE_PARM_READ_WRITE { - - MODE_PARAMETER_HEADER ParameterListHeader; // List Header Format - MODE_PARAMETER_BLOCK ParameterListBlock; // List Block Descriptor - +typedef struct _MODE_PARM_READ_WRITE +{ + MODE_PARAMETER_HEADER ParameterListHeader; /* List Header Format */ + MODE_PARAMETER_BLOCK ParameterListBlock; /* List Block Descriptor */ } MODE_PARM_READ_WRITE_DATA, *PMODE_PARM_READ_WRITE_DATA; -// end_ntminitape // // CDROM audio control (0x0E) @@ -1181,9 +1187,10 @@ typedef struct _MODE_PARM_READ_WRITE { #define CDB_USE_MSF 0x01 -typedef struct _PORT_OUTPUT { - UCHAR ChannelSelection; - UCHAR Volume; +typedef struct _PORT_OUTPUT +{ + UCHAR ChannelSelection; + UCHAR Volume; } PORT_OUTPUT, *PPORT_OUTPUT; typedef struct _AUDIO_OUTPUT @@ -1197,9 +1204,8 @@ typedef struct _AUDIO_OUTPUT PORT_OUTPUT PortOutput[4]; } AUDIO_OUTPUT, *PAUDIO_OUTPUT; -// -// Multisession CDROM -// + +/* Multisession CDROM */ #define GET_LAST_SESSION 0x01 #define GET_SESSION_DATA 0x02; @@ -1209,11 +1215,11 @@ typedef struct _AUDIO_OUTPUT typedef struct _MECHANICAL_STATUS_INFORMATION_HEADER { - UCHAR CurrentSlot : 5; - UCHAR ChangerState : 2; - UCHAR Fault : 1; - UCHAR Reserved : 5; - UCHAR MechanismState : 3; + UCHAR CurrentSlot:5; + UCHAR ChangerState:2; + UCHAR Fault:1; + UCHAR Reserved:5; + UCHAR MechanismState:3; UCHAR CurrentLogicalBlockAddress[3]; UCHAR NumberAvailableSlots; UCHAR SlotTableLength[2]; @@ -1221,9 +1227,9 @@ typedef struct _MECHANICAL_STATUS_INFORMATION_HEADER typedef struct _SLOT_TABLE_INFORMATION { - UCHAR DiscChanged : 1; - UCHAR Reserved : 6; - UCHAR DiscPresent : 1; + UCHAR DiscChanged:1; + UCHAR Reserved:6; + UCHAR DiscPresent:1; UCHAR Reserved2[3]; } SLOT_TABLE_INFORMATION, *PSLOT_TABLE_INFORMATION; diff --git a/reactos/drivers/storage/include/srb.h b/reactos/drivers/storage/include/srb.h index 3bba5d7b19e..efbec59e8b0 100644 --- a/reactos/drivers/storage/include/srb.h +++ b/reactos/drivers/storage/include/srb.h @@ -1,4 +1,4 @@ -/* $Id: srb.h,v 1.3 2002/01/27 01:25:34 ekohl Exp $ +/* $Id: srb.h,v 1.4 2002/01/31 14:58:35 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -10,9 +10,8 @@ #ifndef __STORAGE_INCLUDE_SRB_H #define __STORAGE_INCLUDE_SRB_H -// -// Define SCSI maximum configuration parameters. -// + +/* Define SCSI maximum configuration parameters. */ #define SCSI_MAXIMUM_LOGICAL_UNITS 8 #define SCSI_MAXIMUM_TARGETS_PER_BUS 32 @@ -20,14 +19,11 @@ #define SCSI_MINIMUM_PHYSICAL_BREAKS 16 #define SCSI_MAXIMUM_PHYSICAL_BREAKS 255 -// -// This constant is for backward compatibility. -// This use to be the maximum number of targets supported. -// + +/* Obsolete. For backward compatibility only. */ #define SCSI_MAXIMUM_TARGETS 8 -// begin_ntminitape #define MAXIMUM_CDB_SIZE 12 @@ -125,9 +121,8 @@ typedef struct _SCSI_REQUEST_BLOCK #define SCSI_REQUEST_BLOCK_SIZE sizeof(SCSI_REQUEST_BLOCK) -// -// SRB Functions -// + +/* SRB Functions */ #define SRB_FUNCTION_EXECUTE_SCSI 0x00 #define SRB_FUNCTION_CLAIM_DEVICE 0x01 @@ -146,9 +141,8 @@ typedef struct _SCSI_REQUEST_BLOCK #define SRB_FUNCTION_FLUSH_QUEUE 0x15 #define SRB_FUNCTION_REMOVE_DEVICE 0x16 -// -// SRB Status -// + +/* SRB Status */ #define SRB_STATUS_PENDING 0x00 #define SRB_STATUS_SUCCESS 0x01 @@ -177,18 +171,16 @@ typedef struct _SCSI_REQUEST_BLOCK #define SRB_STATUS_BAD_FUNCTION 0x22 #define SRB_STATUS_ERROR_RECOVERY 0x23 -// -// SRB Status Masks -// + +/* SRB Status Masks */ #define SRB_STATUS_QUEUE_FROZEN 0x40 #define SRB_STATUS_AUTOSENSE_VALID 0x80 #define SRB_STATUS(Status) (Status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) -// -// SRB Flag Bits -// + +/* SRB Flag Bits */ #define SRB_FLAGS_QUEUE_ACTION_ENABLE 0x00000002 #define SRB_FLAGS_DISABLE_DISCONNECT 0x00000004 @@ -205,18 +197,15 @@ typedef struct _SCSI_REQUEST_BLOCK #define SRB_FLAGS_ALLOCATED_FROM_ZONE 0x00020000 #define SRB_FLAGS_SGLIST_FROM_POOL 0x00040000 -// -// Queue Action -// + +/* Queue Action */ #define SRB_SIMPLE_TAG_REQUEST 0x20 #define SRB_HEAD_OF_QUEUE_TAG_REQUEST 0x21 #define SRB_ORDERED_QUEUE_TAG_REQUEST 0x22 -// -// Port driver error codes -// +/* Port driver error codes */ #define SP_BUS_PARITY_ERROR 0x0001 #define SP_UNEXPECTED_DISCONNECT 0x0002 @@ -229,9 +218,8 @@ typedef struct _SCSI_REQUEST_BLOCK #define SP_BAD_FW_WARNING 0x0009 #define SP_BAD_FW_ERROR 0x000a -// -// Return values for SCSI_HW_FIND_ADAPTER. -// + +/* Return values for SCSI_HW_FIND_ADAPTER. */ #define SP_RETURN_NOT_FOUND 0 #define SP_RETURN_FOUND 1 diff --git a/reactos/drivers/storage/scsiport/scsiport.c b/reactos/drivers/storage/scsiport/scsiport.c index 7bdb281d9d1..85439173f07 100644 --- a/reactos/drivers/storage/scsiport/scsiport.c +++ b/reactos/drivers/storage/scsiport/scsiport.c @@ -16,7 +16,7 @@ * 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 $ +/* $Id: scsiport.c,v 1.4 2002/01/31 14:58:52 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -55,7 +55,13 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION ULONG MiniPortExtensionSize; PORT_CONFIGURATION_INFORMATION PortConfig; + ULONG PortBusInfoSize; + PSCSI_ADAPTER_BUS_INFO PortBusInfo; + + PCONTROLLER_OBJECT ControllerObject; + PHW_STARTIO HwStartIo; + PHW_INTERRUPT HwInterrupt; UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */ } SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION; @@ -126,10 +132,23 @@ static NTSTATUS STDCALL ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +static NTSTATUS STDCALL +ScsiPortReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + static VOID STDCALL ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +static IO_ALLOCATION_ACTION STDCALL +ScsiPortAllocateController(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context); + +static BOOLEAN STDCALL +ScsiPortStartController(IN OUT PVOID Context); + static NTSTATUS ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension, @@ -139,7 +158,7 @@ static BOOLEAN STDCALL ScsiPortIsr(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); -static VOID +static VOID STDCALL ScsiPortDpcForIsr(IN PKDPC Dpc, IN PDEVICE_OBJECT DpcDeviceObject, IN PIRP DpcIrp, @@ -150,6 +169,7 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject, PVOID Context); + /* FUNCTIONS *****************************************************************/ /********************************************************************** @@ -363,6 +383,33 @@ ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension, } +/********************************************************************** + * NAME EXPORTED + * ScsiPortInitialize + * + * DESCRIPTION + * Initializes SCSI port driver specific data. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * Argument1 + * Pointer to the miniport driver's driver object. + * + * Argument2 + * Pointer to the miniport driver's registry path. + * + * HwInitializationData + * Pointer to port driver specific configuration data. + * + * HwContext + Miniport driver specific context. + * + * RETURN VALUE + * Status. + */ + ULONG STDCALL ScsiPortInitialize(IN PVOID Argument1, IN PVOID Argument2, @@ -396,9 +443,9 @@ ScsiPortInitialize(IN PVOID Argument1, DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl; DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi; +// DriverObject->MajorFunction[IRP_MJ_READ] = ScsiPortReadWrite; +// DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiPortReadWrite; -// 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; @@ -416,6 +463,7 @@ ScsiPortInitialize(IN PVOID Argument1, PseudoDeviceExtension->Length = ExtensionSize; PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize; PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo; + PseudoDeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt; PortConfig = &PseudoDeviceExtension->PortConfig; @@ -616,68 +664,40 @@ ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject, } -// ScsiPortDispatchScsi -// -// DESCRIPTION: -// Answer requests for SCSI calls -// -// RUN LEVEL: -// PASSIVE_LEVEL -// -// ARGUMENTS: -// Standard dispatch arguments -// -// RETURNS: -// NTSTATUS -// +/********************************************************************** + * NAME INTERNAL + * 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; + PIO_STACK_LOCATION Stack; + PSCSI_REQUEST_BLOCK Srb; + NTSTATUS Status = STATUS_SUCCESS; + ULONG DataSize = 0; - Stack = IoGetCurrentIrpStackLocation(Irp); + DPRINT1("ScsiPortDispatchScsi()\n"); + DeviceExtension = DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); - switch (Stack->Parameters.DeviceIoControl.IoControlCode) + switch(Stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_SCSI_EXECUTE_IN: { @@ -696,6 +716,170 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject, DPRINT1(" IOCTL_SCSI_EXECUTE_NONE\n"); } break; + } + + Srb = Stack->Parameters.Scsi.Srb; + if (Srb == NULL) + { + + Status = STATUS_UNSUCCESSFUL; + + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); + } + + DPRINT("Srb: %p\n", Srb); + DPRINT("Srb->Function: %lu\n", Srb->Function); + + switch (Srb->Function) + { + case SRB_FUNCTION_EXECUTE_SCSI: + DPRINT1(" SRB_FUNCTION_EXECUTE_SCSI\n"); + + switch (Srb->Cdb[0]) + { + case SCSIOP_INQUIRY: + case SCSIOP_READ_CAPACITY: + Status = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension, + Srb); + break; + + + default: + IoStartPacket(DeviceObject, Irp, NULL, NULL); + DPRINT1("Returning STATUS_PENDING\n"); + return(STATUS_PENDING); + } + break; + + case SRB_FUNCTION_CLAIM_DEVICE: + { + PSCSI_ADAPTER_BUS_INFO AdapterInfo; + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; + + DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n"); + + if (DeviceExtension->PortBusInfo != NULL) + { + AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo; + + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + + AdapterInfo->BusData[Srb->PathId].InquiryDataOffset); + + while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + if ((UnitInfo->TargetId == Srb->TargetId) && + (UnitInfo->Lun == Srb->Lun) && + (UnitInfo->DeviceClaimed == FALSE)) + { + UnitInfo->DeviceClaimed = TRUE; + DPRINT("Claimed device!\n"); + break; + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset); + } + } + + /* FIXME: Hack!!!!! */ + Srb->DataBuffer = DeviceObject; + } + break; + + case SRB_FUNCTION_RELEASE_DEVICE: + { + PSCSI_ADAPTER_BUS_INFO AdapterInfo; + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; + + DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n"); + + if (DeviceExtension->PortBusInfo != NULL) + { + AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo; + + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + + AdapterInfo->BusData[Srb->PathId].InquiryDataOffset); + + + while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + if ((UnitInfo->TargetId == Srb->TargetId) && + (UnitInfo->Lun == Srb->Lun) && + (UnitInfo->DeviceClaimed == TRUE)) + { + UnitInfo->DeviceClaimed = FALSE; + DPRINT("Released device!\n"); + break; + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset); + } + } + } + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = DataSize; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + + +/********************************************************************** + * NAME INTERNAL + * 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; + + DPRINT1("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_GET_CAPABILITIES: { @@ -729,64 +913,85 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject, ULONG Bus; ULONG Target; ULONG UnitCount; + ULONG DataSize; BOOLEAN Result; - DPRINT1(" IOCTL_SCSI_GET_INQUIRY_DATA\n"); + DPRINT(" 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++) + /* Copy inquiry data to the port device extension */ + if (DeviceExtension->PortBusInfo == NULL) { - Srb.PathId = Bus; + AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)Irp->AssociatedIrp.SystemBuffer; + AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses; - AdapterInfo->BusData[Bus].InitiatorBusId = 0; /* ? */ - AdapterInfo->BusData[Bus].InquiryDataOffset = - (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo); + UnitInfo = (PSCSI_INQUIRY_DATA) + ((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) + + (sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1))); - PrevUnit = NULL; - UnitCount = 0; + 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 (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++) + for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++) { - Srb.TargetId = Target; - Srb.Lun = 0; + Srb.PathId = Bus; - Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension, - &Srb); - if (Result == TRUE) + 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++) { - 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++; + 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; } - AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount; + DataSize = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo); + + ExFreePool(Srb.DataBuffer); + + /* copy inquiry data to the port driver's device extension */ + DeviceExtension->PortBusInfoSize = DataSize; + DeviceExtension->PortBusInfo = ExAllocatePool(NonPagedPool, + DataSize); + memcpy(DeviceExtension->PortBusInfo, + AdapterInfo, + DataSize); + } + else + { + memcpy(Irp->AssociatedIrp.SystemBuffer, + DeviceExtension->PortBusInfo, + DeviceExtension->PortBusInfoSize); } - ExFreePool(Srb.DataBuffer); - DPRINT1("BufferSize: %lu\n",(ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo)); - Irp->IoStatus.Information = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo); + DPRINT("BufferSize: %lu\n", DeviceExtension->PortBusInfoSize); + Irp->IoStatus.Information = DeviceExtension->PortBusInfoSize; } break; @@ -802,36 +1007,172 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject, } +static NTSTATUS STDCALL +ScsiPortReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + NTSTATUS Status; + + DPRINT1("ScsiPortReadWrite() called!\n"); + + Status = STATUS_SUCCESS; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + + + + static VOID STDCALL ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; PIO_STACK_LOCATION IrpStack; - - DPRINT("ScsiPortStartIo() called!\n"); - + KIRQL OldIrql; + + DPRINT1("ScsiPortStartIo() called!\n"); + + DeviceExtension = DeviceObject->DeviceExtension; IrpStack = IoGetCurrentIrpStackLocation(Irp); -// DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension; // FIXME: implement the supported functions switch (IrpStack->MajorFunction) { + case IRP_MJ_SCSI: + { + BOOLEAN Result; + PSCSI_REQUEST_BLOCK Srb; + + DPRINT1("IRP_MJ_SCSI\n"); + + Srb = IrpStack->Parameters.Scsi.Srb; + +// Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension, +// Srb); + + /* FIXME: Needs error handling! */ +// if (Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_EXECUTE_OUT) +// DataSize = Srb->DataTransferLength; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Srb->DataTransferLength; + IoMarkIrpPending(Irp); + +CHECKPOINT1; + KeRaiseIrql(DISPATCH_LEVEL, + &OldIrql); +CHECKPOINT1; + IoAllocateController(DeviceExtension->ControllerObject, + DeviceObject, + ScsiPortAllocateController, + Irp); +CHECKPOINT1; + KeLowerIrql(OldIrql); +CHECKPOINT1; + +#if 0 + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Srb->DataTransferLength; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject, + FALSE); +#endif + } + break; 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"); + DPRINT1("ScsiPortStartIo() done\n"); } +static IO_ALLOCATION_ACTION STDCALL +ScsiPortAllocateController(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context) +{ + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + PSCSI_PORT_CONTROLLER_EXTENSION ControllerExtension; + + DPRINT1("ScsiPortAllocateController() called\n"); + + DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + ControllerExtension = (PSCSI_PORT_CONTROLLER_EXTENSION) + DeviceExtension->ControllerObject->ControllerExtension; + + ControllerExtension->CurrentIrp = Irp; + ControllerExtension->Retries = 0; + return(KeSynchronizeExecution(ControllerExtension->Interrupt, + ScsiPortStartController, + DeviceExtension) ? KeepObject : + DeallocateObject); +} + + +static BOOLEAN STDCALL +ScsiPortStartController(IN OUT PVOID Context) +{ + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + PSCSI_PORT_CONTROLLER_EXTENSION ControllerExtension; + PIO_STACK_LOCATION IrpStack; + PSCSI_REQUEST_BLOCK Srb; + + DPRINT1("ScsiPortStartController() called\n"); + + DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION) Context; + ControllerExtension = (PSCSI_PORT_CONTROLLER_EXTENSION) + DeviceExtension->ControllerObject->ControllerExtension; + ControllerExtension->OperationInProgress = TRUE; + ControllerExtension->DeviceForOperation = DeviceExtension; + + IrpStack = IoGetCurrentIrpStackLocation(ControllerExtension->CurrentIrp); + Srb = IrpStack->Parameters.Scsi.Srb; + + return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension, + Srb)); +} + + +/********************************************************************** + * NAME INTERNAL + * ScsiPortCreatePortDevice + * + * DESCRIPTION + * Creates and initializes a SCSI port device object. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * ... + * + * PseudoDeviceExtension + * ... + * + * PortNumber + * ... + * + * RETURNS + * NTSTATUS + */ + static NTSTATUS ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension, @@ -848,12 +1189,15 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, NTSTATUS Status; ULONG AccessRangeSize; +#if 0 ULONG MappedIrq; KIRQL Dirql; KAFFINITY Affinity; +#endif DPRINT("ScsiPortCreatePortDevice() called\n"); +#if 0 MappedIrq = HalGetInterruptVector(PseudoDeviceExtension->PortConfig.AdapterInterfaceType, PseudoDeviceExtension->PortConfig.SystemIoBusNumber, 0, @@ -868,6 +1212,7 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, PortNumber); return(STATUS_NO_SUCH_DEVICE); } +#endif /* Fill out Controller extension data */ ControllerExtension = (PSCSI_PORT_CONTROLLER_EXTENSION) @@ -886,12 +1231,12 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, ScsiPortIsr, ControllerExtension, &ControllerExtension->SpinLock, - MappedIrq, - Dirql, - Dirql, + PseudoDeviceExtension->PortConfig.BusInterruptVector, // MappedIrq, + PseudoDeviceExtension->PortConfig.BusInterruptLevel, // Dirql, + 15, //Dirql, PseudoDeviceExtension->PortConfig.InterruptMode, FALSE, - Affinity, + 0xFFFF, //Affinity, FALSE); if (!NT_SUCCESS(Status)) { @@ -933,6 +1278,7 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; PortDeviceExtension = PortDeviceObject->DeviceExtension; + PortDeviceExtension->ControllerObject = ControllerObject; ControllerExtension->PortDeviceObject = PortDeviceObject; @@ -964,7 +1310,11 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, PseudoDeviceExtension->PortConfig.AccessRanges, AccessRangeSize); - /* FIXME: Copy or configure any more? */ + /* Initialize inquiry data */ + PortDeviceExtension->PortBusInfoSize = 0; + PortDeviceExtension->PortBusInfo = NULL; + + /* FIXME: Copy more configuration data? */ /* Create the dos device */ swprintf(DosNameBuffer, @@ -980,13 +1330,21 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, } - static BOOLEAN STDCALL ScsiPortIsr(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext) { + PSCSI_PORT_CONTROLLER_EXTENSION ControllerExtension; + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + DPRINT1("ScsiPortIsr() called!\n"); + ControllerExtension = (PSCSI_PORT_CONTROLLER_EXTENSION)ServiceContext; + DeviceExtension = ControllerExtension->DeviceForOperation; + + + + return(TRUE); } @@ -1002,7 +1360,7 @@ ScsiPortIsr(IN PKINTERRUPT Interrupt, // IN PIRP DpcIrp // IN PVOID DpcContext // -static VOID +static VOID STDCALL ScsiPortDpcForIsr(IN PKDPC Dpc, IN PDEVICE_OBJECT DpcDeviceObject, IN PIRP DpcIrp,