mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
Implemented SMART commands for ide devices.
svn path=/trunk/; revision=18496
This commit is contained in:
parent
c7baaf3eb2
commit
abb25bef4f
3 changed files with 753 additions and 59 deletions
|
@ -220,6 +220,9 @@ AtapiNoDataInterrupt(PATAPI_MINIPORT_EXTENSION DevExt);
|
||||||
static BOOLEAN FASTCALL
|
static BOOLEAN FASTCALL
|
||||||
AtapiPacketInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
|
AtapiPacketInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
|
||||||
|
|
||||||
|
static BOOLEAN FASTCALL
|
||||||
|
AtapiSmartInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
|
||||||
|
|
||||||
static BOOLEAN FASTCALL
|
static BOOLEAN FASTCALL
|
||||||
AtapiReadInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
|
AtapiReadInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
|
||||||
|
|
||||||
|
@ -265,6 +268,10 @@ static ULONG
|
||||||
AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
IN PSCSI_REQUEST_BLOCK Srb);
|
IN PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
|
||||||
|
static ULONG
|
||||||
|
AtapiSendSmartCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
|
||||||
static ULONG
|
static ULONG
|
||||||
AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
IN PSCSI_REQUEST_BLOCK Srb);
|
IN PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
@ -941,6 +948,13 @@ AtapiStartIo(IN PVOID DeviceExtension,
|
||||||
case SRB_FUNCTION_IO_CONTROL:
|
case SRB_FUNCTION_IO_CONTROL:
|
||||||
{
|
{
|
||||||
PSRB_IO_CONTROL SrbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;
|
PSRB_IO_CONTROL SrbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;
|
||||||
|
if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) ||
|
||||||
|
Srb->DataTransferLength < SrbIoControl->Length + sizeof(SRB_IO_CONTROL))
|
||||||
|
{
|
||||||
|
Result = SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (!_strnicmp((char*)SrbIoControl->Signature, "ScsiDisk", 8))
|
if (!_strnicmp((char*)SrbIoControl->Signature, "ScsiDisk", 8))
|
||||||
{
|
{
|
||||||
switch (SrbIoControl->ControlCode)
|
switch (SrbIoControl->ControlCode)
|
||||||
|
@ -949,37 +963,103 @@ AtapiStartIo(IN PVOID DeviceExtension,
|
||||||
Result = SRB_STATUS_INVALID_REQUEST;
|
Result = SRB_STATUS_INVALID_REQUEST;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
|
||||||
|
case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
|
||||||
|
case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
|
||||||
|
case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
|
||||||
|
case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
|
||||||
|
case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
|
||||||
|
case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
|
||||||
|
case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
|
||||||
|
case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
|
||||||
|
#if 0
|
||||||
|
case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
|
||||||
|
#endif
|
||||||
|
Result = AtapiSendSmartCommand(DevExt, Srb);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_SMART_VERSION:
|
||||||
|
{
|
||||||
|
GETVERSIONINPARAMS Version;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_SMART_VERSION\n");
|
||||||
|
|
||||||
|
RtlZeroMemory(&Version, sizeof(GETVERSIONINPARAMS));
|
||||||
|
Version.bVersion = 1;
|
||||||
|
Version.bRevision = 1;
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
switch (DevExt->DeviceFlags[i] & (DEVICE_PRESENT|DEVICE_ATAPI))
|
||||||
|
{
|
||||||
|
case DEVICE_PRESENT:
|
||||||
|
Version.bIDEDeviceMap |= 0x01 << i;
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
case DEVICE_PRESENT|DEVICE_ATAPI:
|
||||||
|
Version.bIDEDeviceMap |= 0x11 << i;
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Version.fCapabilities = CAP_ATA_ID_CMD/*|CAP_ATAPI_ID_CMD|CAP_SMART_CMD*/;
|
||||||
|
SrbIoControl->Length = min(sizeof(GETVERSIONINPARAMS), Srb->DataTransferLength - sizeof(SRB_IO_CONTROL));
|
||||||
|
memcpy(SrbIoControl + 1, &Version, SrbIoControl->Length);
|
||||||
|
Result = SRB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case IOCTL_SCSI_MINIPORT_IDENTIFY:
|
case IOCTL_SCSI_MINIPORT_IDENTIFY:
|
||||||
{
|
{
|
||||||
PSENDCMDOUTPARAMS OutParams = (PSENDCMDOUTPARAMS)((ULONG_PTR)Srb->DataBuffer + sizeof(SRB_IO_CONTROL));
|
SENDCMDOUTPARAMS OutParams;
|
||||||
SENDCMDINPARAMS InParams = *(PSENDCMDINPARAMS)OutParams;
|
SENDCMDINPARAMS InParams = *(PSENDCMDINPARAMS)(SrbIoControl + 1);
|
||||||
|
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_IDENTIFY\n");
|
||||||
|
|
||||||
RtlZeroMemory(OutParams, Srb->DataTransferLength - sizeof(SRB_IO_CONTROL));
|
if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1)
|
||||||
|
|
||||||
if (InParams.irDriveRegs.bCommandReg != IDE_CMD_IDENT_ATA_DRV)
|
|
||||||
{
|
{
|
||||||
DPRINT1("bCommandReg: %x\n", InParams.irDriveRegs.bCommandReg);
|
|
||||||
OutParams->DriverStatus.bIDEError = 1;
|
|
||||||
Result = SRB_STATUS_INVALID_REQUEST;
|
Result = SRB_STATUS_INVALID_REQUEST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InParams.bDriveNumber > 1 ||
|
RtlZeroMemory(&OutParams, sizeof(SENDCMDOUTPARAMS));
|
||||||
|
|
||||||
|
if (InParams.irDriveRegs.bCommandReg != IDE_CMD_IDENT_ATA_DRV)
|
||||||
|
{
|
||||||
|
DPRINT("bCommandReg: %x\n", InParams.irDriveRegs.bCommandReg);
|
||||||
|
OutParams.DriverStatus.bIDEError = 1;
|
||||||
|
Result = SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
else if (InParams.bDriveNumber > 1 ||
|
||||||
(DevExt->DeviceFlags[InParams.bDriveNumber] & (DEVICE_PRESENT|DEVICE_ATAPI)) != DEVICE_PRESENT)
|
(DevExt->DeviceFlags[InParams.bDriveNumber] & (DEVICE_PRESENT|DEVICE_ATAPI)) != DEVICE_PRESENT)
|
||||||
{
|
{
|
||||||
OutParams->DriverStatus.bIDEError = 1;
|
OutParams.DriverStatus.bIDEError = 1;
|
||||||
Result = SRB_STATUS_NO_DEVICE;
|
Result = SRB_STATUS_NO_DEVICE;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (Srb->DataTransferLength > sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1)
|
|
||||||
{
|
{
|
||||||
OutParams->cBufferSize = min(IDENTIFY_BUFFER_SIZE, Srb->DataTransferLength - (sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1));
|
Result = SRB_STATUS_SUCCESS;
|
||||||
RtlCopyMemory(OutParams->bBuffer, &DevExt->DeviceParams[InParams.bDriveNumber], OutParams->cBufferSize);
|
}
|
||||||
|
if (Result == SRB_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
SrbIoControl->Length = min(sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE, Srb->DataTransferLength - sizeof(SRB_IO_CONTROL));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SrbIoControl->Length = min(sizeof(SENDCMDOUTPARAMS) - 1, Srb->DataTransferLength - sizeof(SRB_IO_CONTROL));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = SRB_STATUS_SUCCESS;
|
if (SrbIoControl->Length >= sizeof(SENDCMDOUTPARAMS) - 1)
|
||||||
|
{
|
||||||
|
OutParams.cBufferSize = min(SrbIoControl->Length, IDENTIFY_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(SrbIoControl + 1, &OutParams, min (SrbIoControl->Length, sizeof(SENDCMDOUTPARAMS) - 1));
|
||||||
|
|
||||||
|
if (SrbIoControl->Length > sizeof(SENDCMDOUTPARAMS) - 1)
|
||||||
|
{
|
||||||
|
RtlCopyMemory((PVOID)((ULONG_PTR)(SrbIoControl + 1) + sizeof(SENDCMDOUTPARAMS) - 1), &DevExt->DeviceParams[InParams.bDriveNumber], OutParams.cBufferSize);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -987,8 +1067,9 @@ AtapiStartIo(IN PVOID DeviceExtension,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Result = SRB_STATUS_INVALID_REQUEST;
|
Result = SRB_STATUS_INVALID_REQUEST;
|
||||||
|
SrbIoControl->Length = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1685,6 +1766,219 @@ AtapiPolledRead(IN ULONG CommandPort,
|
||||||
|
|
||||||
// ------------------------------------------- Nondiscardable statics
|
// ------------------------------------------- Nondiscardable statics
|
||||||
|
|
||||||
|
static ULONG
|
||||||
|
AtapiSendSmartCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
{
|
||||||
|
PSRB_IO_CONTROL SrbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;
|
||||||
|
SENDCMDINPARAMS InParams;
|
||||||
|
PSENDCMDOUTPARAMS OutParams = (PSENDCMDOUTPARAMS)(SrbIoControl + 1);
|
||||||
|
ULONG Retries;
|
||||||
|
UCHAR Status;
|
||||||
|
|
||||||
|
if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 ||
|
||||||
|
SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams = *(PSENDCMDINPARAMS)(SrbIoControl + 1);
|
||||||
|
|
||||||
|
DPRINT("%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||||
|
InParams.irDriveRegs.bFeaturesReg,
|
||||||
|
InParams.irDriveRegs.bSectorCountReg,
|
||||||
|
InParams.irDriveRegs.bSectorNumberReg,
|
||||||
|
InParams.irDriveRegs.bCylLowReg,
|
||||||
|
InParams.irDriveRegs.bCylHighReg,
|
||||||
|
InParams.irDriveRegs.bDriveHeadReg,
|
||||||
|
InParams.irDriveRegs.bCommandReg,
|
||||||
|
InParams.irDriveRegs.bReserved);
|
||||||
|
|
||||||
|
if (InParams.bDriveNumber > 1 ||
|
||||||
|
(DeviceExtension->DeviceFlags[InParams.bDriveNumber] & (DEVICE_PRESENT|DEVICE_ATAPI)) != DEVICE_PRESENT)
|
||||||
|
{
|
||||||
|
RtlZeroMemory(&OutParams, sizeof(SENDCMDOUTPARAMS));
|
||||||
|
OutParams->DriverStatus.bIDEError = 1;
|
||||||
|
return SRB_STATUS_NO_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceExtension->DataTransferLength = 0;
|
||||||
|
|
||||||
|
switch (SrbIoControl->ControlCode)
|
||||||
|
{
|
||||||
|
case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS\n");
|
||||||
|
|
||||||
|
if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE ||
|
||||||
|
SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE ||
|
||||||
|
InParams.irDriveRegs.bFeaturesReg != READ_ATTRIBUTES ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams.irDriveRegs.bSectorCountReg = 0;
|
||||||
|
InParams.irDriveRegs.bSectorNumberReg = 0;
|
||||||
|
DeviceExtension->DataTransferLength = READ_ATTRIBUTE_BUFFER_SIZE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS\n");
|
||||||
|
|
||||||
|
if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE ||
|
||||||
|
SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE ||
|
||||||
|
InParams.irDriveRegs.bFeaturesReg != READ_THRESHOLDS ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams.irDriveRegs.bSectorCountReg = 0;
|
||||||
|
InParams.irDriveRegs.bSectorNumberReg = 0;
|
||||||
|
DeviceExtension->DataTransferLength = READ_THRESHOLD_BUFFER_SIZE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_LOG\n");
|
||||||
|
|
||||||
|
if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE ||
|
||||||
|
SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE ||
|
||||||
|
InParams.irDriveRegs.bFeaturesReg != SMART_READ_LOG ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
DeviceExtension->DataTransferLength = max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE\n");
|
||||||
|
|
||||||
|
if (InParams.irDriveRegs.bFeaturesReg != ENABLE_DISABLE_AUTOSAVE ||
|
||||||
|
(InParams.irDriveRegs.bSectorCountReg != 0 && InParams.irDriveRegs.bSectorCountReg != 1) ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams.irDriveRegs.bSectorNumberReg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES\n");
|
||||||
|
|
||||||
|
if (InParams.irDriveRegs.bFeaturesReg != SAVE_ATTRIBUTE_VALUES ||
|
||||||
|
(InParams.irDriveRegs.bSectorCountReg != 0 && InParams.irDriveRegs.bSectorCountReg != 0xf1) ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams.irDriveRegs.bSectorNumberReg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");
|
||||||
|
|
||||||
|
if (InParams.irDriveRegs.bFeaturesReg != EXECUTE_OFFLINE_DIAGS ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams.irDriveRegs.bSectorCountReg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_SMART\n");
|
||||||
|
|
||||||
|
if (InParams.irDriveRegs.bFeaturesReg != ENABLE_SMART ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams.irDriveRegs.bSectorCountReg = 0;
|
||||||
|
InParams.irDriveRegs.bSectorNumberReg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_DISABLE_SMART\n");
|
||||||
|
|
||||||
|
if (InParams.irDriveRegs.bFeaturesReg != DISABLE_SMART ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams.irDriveRegs.bSectorCountReg = 0;
|
||||||
|
InParams.irDriveRegs.bSectorNumberReg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_RETURN_STATUS\n");
|
||||||
|
|
||||||
|
if (InParams.irDriveRegs.bFeaturesReg != RETURN_SMART_STATUS ||
|
||||||
|
InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
|
||||||
|
InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
|
||||||
|
InParams.irDriveRegs.bCommandReg != SMART_CMD)
|
||||||
|
{
|
||||||
|
return SRB_STATUS_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
InParams.irDriveRegs.bSectorCountReg = 0;
|
||||||
|
InParams.irDriveRegs.bSectorNumberReg = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Srb->TargetId = InParams.bDriveNumber;
|
||||||
|
|
||||||
|
/* Set pointer to data buffer. */
|
||||||
|
DeviceExtension->DataBuffer = (PUCHAR)OutParams->bBuffer;
|
||||||
|
|
||||||
|
DeviceExtension->CurrentSrb = Srb;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
if (Retries >= IDE_MAX_BUSY_RETRIES)
|
||||||
|
{
|
||||||
|
DPRINT ("Drive is BUSY for too long\n");
|
||||||
|
return(SRB_STATUS_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select the desired drive */
|
||||||
|
InParams.irDriveRegs.bDriveHeadReg = (InParams.bDriveNumber ? IDE_DH_DRV1 : IDE_DH_DRV0) | IDE_DH_FIXED;
|
||||||
|
IDEWriteDriveHead(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bDriveHeadReg);
|
||||||
|
ScsiPortStallExecution(2);
|
||||||
|
|
||||||
|
IDEWritePrecomp(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bFeaturesReg);
|
||||||
|
IDEWriteSectorCount(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bSectorCountReg);
|
||||||
|
IDEWriteSectorNum(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bSectorNumberReg);
|
||||||
|
IDEWriteCylinderLow(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bCylLowReg);
|
||||||
|
IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bCylHighReg);
|
||||||
|
|
||||||
|
AtapiExecuteCommand(DeviceExtension, InParams.irDriveRegs.bCommandReg, AtapiSmartInterrupt);
|
||||||
|
|
||||||
|
/* Wait for interrupt. */
|
||||||
|
return SRB_STATUS_PENDING;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static ULONG
|
static ULONG
|
||||||
AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
IN PSCSI_REQUEST_BLOCK Srb)
|
IN PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
@ -2240,8 +2534,6 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
IDEWriteCylinderLow(DeviceExtension->CommandPortBase, CylinderLow[0]);
|
IDEWriteCylinderLow(DeviceExtension->CommandPortBase, CylinderLow[0]);
|
||||||
IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, CylinderHigh[0]);
|
IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, CylinderHigh[0]);
|
||||||
|
|
||||||
IDEWriteDriveHead(DeviceExtension->CommandPortBase, IDE_DH_FIXED | DrvHead);
|
|
||||||
|
|
||||||
#ifdef ENABLE_DMA
|
#ifdef ENABLE_DMA
|
||||||
if (DeviceExtension->PRDTable &&
|
if (DeviceExtension->PRDTable &&
|
||||||
DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_DMA_CMD)
|
DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_DMA_CMD)
|
||||||
|
@ -2939,6 +3231,79 @@ AtapiDmaInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static BOOLEAN FASTCALL
|
||||||
|
AtapiSmartInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
|
||||||
|
{
|
||||||
|
PSCSI_REQUEST_BLOCK Srb;
|
||||||
|
UCHAR DeviceStatus;
|
||||||
|
PSRB_IO_CONTROL SrbIoControl;
|
||||||
|
PSENDCMDOUTPARAMS OutParams;
|
||||||
|
PIDEREGS IdeRegs;
|
||||||
|
|
||||||
|
DPRINT("AtapiSmartInterrupt() called!\n");
|
||||||
|
|
||||||
|
Srb = DevExt->CurrentSrb;
|
||||||
|
|
||||||
|
|
||||||
|
DeviceStatus = IDEReadStatus(DevExt->CommandPortBase);
|
||||||
|
if ((DeviceStatus & (IDE_SR_DRQ|IDE_SR_BUSY|IDE_SR_ERR)) != (DevExt->DataTransferLength ? IDE_SR_DRQ : 0))
|
||||||
|
{
|
||||||
|
if (DeviceStatus & (IDE_SR_ERR|IDE_SR_DRQ))
|
||||||
|
{
|
||||||
|
AtapiCompleteRequest(DevExt, SRB_STATUS_ERROR);
|
||||||
|
DPRINT("AtapiSmartInterrupt() done!\n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
DPRINT("AtapiSmartInterrupt() done!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("CommandPortBase: %lx ControlPortBase: %lx\n", DevExt->CommandPortBase, DevExt->ControlPortBase);
|
||||||
|
|
||||||
|
if (DevExt->DataTransferLength)
|
||||||
|
{
|
||||||
|
IDEReadBlock(DevExt->CommandPortBase, DevExt->DataBuffer, 512);
|
||||||
|
DevExt->DataTransferLength -= 512;
|
||||||
|
DevExt->DataBuffer += 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DevExt->DataTransferLength == 0)
|
||||||
|
{
|
||||||
|
SrbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;
|
||||||
|
OutParams = (PSENDCMDOUTPARAMS)(SrbIoControl + 1);
|
||||||
|
|
||||||
|
OutParams->DriverStatus.bDriverError = 0;
|
||||||
|
OutParams->DriverStatus.bIDEError = 0;
|
||||||
|
|
||||||
|
if (SrbIoControl->ControlCode == IOCTL_SCSI_MINIPORT_RETURN_STATUS)
|
||||||
|
{
|
||||||
|
IdeRegs = (PIDEREGS)OutParams->bBuffer;
|
||||||
|
|
||||||
|
IdeRegs->bFeaturesReg = RETURN_SMART_STATUS;
|
||||||
|
IdeRegs->bSectorCountReg = IDEReadSectorCount(DevExt->CommandPortBase);
|
||||||
|
IdeRegs->bSectorNumberReg = IDEReadSectorNum(DevExt->CommandPortBase);
|
||||||
|
IdeRegs->bCylLowReg = IDEReadCylinderLow(DevExt->CommandPortBase);
|
||||||
|
IdeRegs->bCylHighReg = IDEReadCylinderHigh(DevExt->CommandPortBase);
|
||||||
|
IdeRegs->bDriveHeadReg = IDEReadDriveHead(DevExt->CommandPortBase);
|
||||||
|
IdeRegs->bCommandReg = SMART_CMD;
|
||||||
|
IdeRegs->bReserved = 0;
|
||||||
|
|
||||||
|
OutParams->cBufferSize = 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutParams->cBufferSize = DevExt->DataBuffer - OutParams->bBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
AtapiCompleteRequest(DevExt, SRB_STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("AtapiSmartInterrupt() done!\n");
|
||||||
|
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOLEAN FASTCALL
|
static BOOLEAN FASTCALL
|
||||||
AtapiReadInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
|
AtapiReadInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
|
||||||
{
|
{
|
||||||
|
|
|
@ -999,6 +999,11 @@ DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PDISK_DATA DiskData;
|
PDISK_DATA DiskData;
|
||||||
ULONG Information;
|
ULONG Information;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
KEVENT Event;
|
||||||
|
IO_STATUS_BLOCK IoSB;
|
||||||
|
PIRP LocalIrp;
|
||||||
|
PSRB_IO_CONTROL SrbIoControl;
|
||||||
|
PSENDCMDINPARAMS InParams;
|
||||||
|
|
||||||
DPRINT("DiskClassDeviceControl() called!\n");
|
DPRINT("DiskClassDeviceControl() called!\n");
|
||||||
|
|
||||||
|
@ -1251,6 +1256,338 @@ DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
Information = 0;
|
Information = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SMART_GET_VERSION:
|
||||||
|
{
|
||||||
|
PGETVERSIONINPARAMS Version;
|
||||||
|
DPRINT("SMART_GET_VERSION\n");
|
||||||
|
if (OutputLength < sizeof(GETVERSIONINPARAMS))
|
||||||
|
{
|
||||||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
Information = sizeof(GETVERSIONINPARAMS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));
|
||||||
|
if (SrbIoControl == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Version = (PGETVERSIONINPARAMS)(SrbIoControl + 1);
|
||||||
|
memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));
|
||||||
|
|
||||||
|
SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
|
||||||
|
memcpy(SrbIoControl->Signature, "ScsiDisk", 8);
|
||||||
|
SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
|
||||||
|
SrbIoControl->Length = sizeof(GETVERSIONINPARAMS);
|
||||||
|
SrbIoControl->ControlCode = IOCTL_SCSI_MINIPORT_SMART_VERSION;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
|
||||||
|
DeviceExtension->PortDeviceObject,
|
||||||
|
SrbIoControl,
|
||||||
|
sizeof(SRB_IO_CONTROL),
|
||||||
|
SrbIoControl,
|
||||||
|
sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
|
||||||
|
FALSE,
|
||||||
|
&Event,
|
||||||
|
&IoSB);
|
||||||
|
if (LocalIrp == NULL)
|
||||||
|
{
|
||||||
|
ExFreePool(SrbIoControl);
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = IoSB.Status;
|
||||||
|
}
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
memcpy(Irp->AssociatedIrp.SystemBuffer, Version, sizeof(GETVERSIONINPARAMS));
|
||||||
|
Information = sizeof(GETVERSIONINPARAMS);
|
||||||
|
}
|
||||||
|
ExFreePool(SrbIoControl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SMART_SEND_DRIVE_COMMAND:
|
||||||
|
{
|
||||||
|
DPRINT("SMART_SEND_DRIVE_COMMAND\n");
|
||||||
|
|
||||||
|
if (InputLength < sizeof(SENDCMDINPARAMS) - 1)
|
||||||
|
{
|
||||||
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
InParams = (PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
if (InParams->irDriveRegs.bCommandReg == SMART_CMD)
|
||||||
|
{
|
||||||
|
if (InParams->irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTOSAVE)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE;
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == SAVE_ATTRIBUTE_VALUES)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES;
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == EXECUTE_OFFLINE_DIAGS)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == SMART_WRITE_LOG)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG;
|
||||||
|
if (InputLength < sizeof(SENDCMDINPARAMS) - 1 + 512 * max(1, InParams->irDriveRegs.bSectorCountReg))
|
||||||
|
{
|
||||||
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == ENABLE_SMART)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_SMART\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == DISABLE_SMART)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_DISABLE_SMART\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_RETURN_STATUS\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTO_OFFLINE)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("%x\n", InParams->irDriveRegs.bFeaturesReg);
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (OutputLength < Information)
|
||||||
|
{
|
||||||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + max(Information, sizeof(SENDCMDINPARAMS) - 1));
|
||||||
|
if (SrbIoControl == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
Information = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + max(Information, sizeof(SENDCMDINPARAMS) - 1));
|
||||||
|
|
||||||
|
SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
|
||||||
|
memcpy(SrbIoControl->Signature, "SCSIDISK", 8);
|
||||||
|
SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
|
||||||
|
SrbIoControl->Length = Information;
|
||||||
|
SrbIoControl->ControlCode = ControlCode;
|
||||||
|
|
||||||
|
InParams = (PSENDCMDINPARAMS)(SrbIoControl + 1);
|
||||||
|
|
||||||
|
memcpy(InParams, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
|
||||||
|
|
||||||
|
InParams->bDriveNumber = DeviceExtension->TargetId;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
|
||||||
|
DeviceExtension->PortDeviceObject,
|
||||||
|
SrbIoControl,
|
||||||
|
sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
|
||||||
|
SrbIoControl,
|
||||||
|
sizeof(SRB_IO_CONTROL) + Information,
|
||||||
|
FALSE,
|
||||||
|
&Event,
|
||||||
|
&IoSB);
|
||||||
|
if (LocalIrp == NULL)
|
||||||
|
{
|
||||||
|
ExFreePool(SrbIoControl);
|
||||||
|
Information = 0;
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = IoSB.Status;
|
||||||
|
}
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Information = SrbIoControl->Length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
memcpy(Irp->AssociatedIrp.SystemBuffer, InParams, Information);
|
||||||
|
ExFreePool(SrbIoControl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SMART_RCV_DRIVE_DATA:
|
||||||
|
{
|
||||||
|
DPRINT("SMART_RCV_DRIVE_DATA\n");
|
||||||
|
|
||||||
|
if (InputLength < sizeof(SENDCMDINPARAMS) - 1)
|
||||||
|
{
|
||||||
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
InParams = (PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
if (InParams->irDriveRegs.bCommandReg == ID_CMD)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_IDENTIFY\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
|
||||||
|
Information = IDENTIFY_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bCommandReg == SMART_CMD)
|
||||||
|
{
|
||||||
|
if (InParams->irDriveRegs.bFeaturesReg == READ_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS;
|
||||||
|
Information = READ_ATTRIBUTE_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == READ_THRESHOLDS)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS;
|
||||||
|
Information = READ_THRESHOLD_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
|
||||||
|
}
|
||||||
|
else if (InParams->irDriveRegs.bFeaturesReg == SMART_READ_LOG)
|
||||||
|
{
|
||||||
|
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_LOG\n");
|
||||||
|
ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_LOG;
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) - 1 + 512 * max(1, InParams->irDriveRegs.bSectorCountReg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("%x\n", InParams->irDriveRegs.bFeaturesReg);
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("%x\n", InParams->irDriveRegs.bCommandReg);
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (OutputLength < Information)
|
||||||
|
{
|
||||||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + Information);
|
||||||
|
if (SrbIoControl == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
Information = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + Information);
|
||||||
|
|
||||||
|
SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
|
||||||
|
memcpy(SrbIoControl->Signature, "SCSIDISK", 8);
|
||||||
|
SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
|
||||||
|
SrbIoControl->Length = Information;
|
||||||
|
SrbIoControl->ControlCode = ControlCode;
|
||||||
|
|
||||||
|
InParams = (PSENDCMDINPARAMS)(SrbIoControl + 1);
|
||||||
|
|
||||||
|
memcpy(InParams, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
|
||||||
|
|
||||||
|
InParams->bDriveNumber = DeviceExtension->TargetId;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
|
||||||
|
DeviceExtension->PortDeviceObject,
|
||||||
|
SrbIoControl,
|
||||||
|
sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
|
||||||
|
SrbIoControl,
|
||||||
|
sizeof(SRB_IO_CONTROL) + Information,
|
||||||
|
FALSE,
|
||||||
|
&Event,
|
||||||
|
&IoSB);
|
||||||
|
if (LocalIrp == NULL)
|
||||||
|
{
|
||||||
|
ExFreePool(SrbIoControl);
|
||||||
|
Information = 0;
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = IoSB.Status;
|
||||||
|
}
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
CHAR Buffer[256];
|
||||||
|
ULONG i, j;
|
||||||
|
UCHAR sum = 0;
|
||||||
|
memset(Buffer, 0, sizeof(Buffer));
|
||||||
|
for (i = 0; i < 512; i += 16)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 16 && i + j < 512; j++)
|
||||||
|
{
|
||||||
|
sprintf(&Buffer[3*j], "%02x ", ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j]);
|
||||||
|
sum += ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j];
|
||||||
|
}
|
||||||
|
for (j = 0; j < 16 && i + j < 512; j++)
|
||||||
|
{
|
||||||
|
sprintf(&Buffer[3*16 + j], "%c", isprint(((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j]) ? ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j] : '.');
|
||||||
|
}
|
||||||
|
DPRINT1("%04x %s\n", i, Buffer);
|
||||||
|
}
|
||||||
|
DPRINT1("Sum %02x\n", sum);
|
||||||
|
#endif
|
||||||
|
Information = SrbIoControl->Length;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Information = sizeof(SENDCMDOUTPARAMS) -1;
|
||||||
|
}
|
||||||
|
memcpy(Irp->AssociatedIrp.SystemBuffer, InParams, Information);
|
||||||
|
ExFreePool(SrbIoControl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Call the common device control function */
|
/* Call the common device control function */
|
||||||
return(ScsiClassDeviceControl(DeviceObject, Irp));
|
return(ScsiClassDeviceControl(DeviceObject, Irp));
|
||||||
|
@ -1316,21 +1653,13 @@ DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
|
||||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize SRB */
|
|
||||||
RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
|
RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||||
Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
|
|
||||||
|
|
||||||
/* Set device IDs */
|
|
||||||
Srb->PathId = DeviceExtension->PathId;
|
|
||||||
Srb->TargetId = DeviceExtension->TargetId;
|
|
||||||
Srb->Lun = DeviceExtension->Lun;
|
|
||||||
|
|
||||||
/* Set timeout */
|
/* Set timeout */
|
||||||
Srb->TimeOutValue = DeviceExtension->TimeOutValue * 4;
|
Srb->TimeOutValue = DeviceExtension->TimeOutValue * 4;
|
||||||
|
|
||||||
/* Flush write cache */
|
/* Flush write cache */
|
||||||
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
|
|
||||||
Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
|
|
||||||
Srb->CdbLength = 10;
|
Srb->CdbLength = 10;
|
||||||
Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
|
Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
|
||||||
ScsiClassSendSrbSynchronous(DeviceObject,
|
ScsiClassSendSrbSynchronous(DeviceObject,
|
||||||
|
|
|
@ -1776,9 +1776,9 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_SCSI_MINIPORT:
|
case IOCTL_SCSI_MINIPORT:
|
||||||
DPRINT1(" IOCTL_SCSI_MINIPORT\n");
|
DPRINT(" IOCTL_SCSI_MINIPORT\n");
|
||||||
DPRINT1(" Signature: %.8s\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->Signature);
|
DPRINT(" Signature: %.8s\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->Signature);
|
||||||
DPRINT1(" ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->ControlCode);
|
DPRINT(" ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->ControlCode);
|
||||||
return SpiScsiMiniport(DeviceObject, Irp);
|
return SpiScsiMiniport(DeviceObject, Irp);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1869,7 +1869,7 @@ SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject,
|
||||||
SrbIoControl = (PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer;
|
SrbIoControl = (PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1)
|
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SRB_IO_CONTROL))
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
Loading…
Reference in a new issue