atapi.c
来自「一个类似windows」· C语言 代码 · 共 2,047 行 · 第 1/5 页
C
2,047 行
{
DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
DrvHead & IDE_DH_DRV1 ? 1 : 0,
((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
SectorCnt,
Command);
}
else
{
DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
DrvHead & IDE_DH_DRV1 ? 1 : 0,
CylinderHigh,
CylinderLow,
DrvHead & 0x0f,
SectorNum,
SectorCnt,
Command);
}
/* Setup command parameters */
IDEWritePrecomp(CommandPort, PreComp);
IDEWriteSectorCount(CommandPort, SectorCnt);
IDEWriteSectorNum(CommandPort, SectorNum);
IDEWriteCylinderHigh(CommandPort, CylinderHigh);
IDEWriteCylinderLow(CommandPort, CylinderLow);
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
/* Issue the command */
IDEWriteCommand(CommandPort, Command);
ScsiPortStallExecution(50);
/* wait for DRQ or error */
for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
{
Status = IDEReadStatus(CommandPort);
if (!(Status & IDE_SR_BUSY))
{
if (Status & IDE_SR_ERR)
{
IDEWriteDriveControl(ControlPort, 0);
ScsiPortStallExecution(50);
IDEReadStatus(CommandPort);
return FALSE;
}
if (Status & IDE_SR_DRQ)
{
break;
}
else
{
IDEWriteDriveControl(ControlPort, 0);
ScsiPortStallExecution(50);
IDEReadStatus(CommandPort);
return FALSE;
}
}
ScsiPortStallExecution(10);
}
/* timed out */
if (RetryCount >= IDE_MAX_POLL_RETRIES)
{
IDEWriteDriveControl(ControlPort, 0);
ScsiPortStallExecution(50);
IDEReadStatus(CommandPort);
return FALSE;
}
while (1)
{
/* Read data into buffer */
if (Junk == FALSE)
{
IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
Buffer += IDE_SECTOR_BUF_SZ;
}
else
{
UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
}
SectorCount++;
/* Check for error or more sectors to read */
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
{
Status = IDEReadStatus(CommandPort);
if (!(Status & IDE_SR_BUSY))
{
if (Status & IDE_SR_ERR)
{
IDEWriteDriveControl(ControlPort, 0);
ScsiPortStallExecution(50);
IDEReadStatus(CommandPort);
return FALSE;
}
if (Status & IDE_SR_DRQ)
{
if (SectorCount >= SectorCnt)
{
DPRINT("Buffer size exceeded!\n");
Junk = TRUE;
}
break;
}
else
{
if (SectorCount > SectorCnt)
{
DPRINT("Read %lu sectors of junk!\n",
SectorCount - SectorCnt);
}
IDEWriteDriveControl(ControlPort, 0);
ScsiPortStallExecution(50);
IDEReadStatus(CommandPort);
return TRUE;
}
}
}
}
}
// ------------------------------------------- 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
AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb)
{
UCHAR ByteCountHigh;
UCHAR ByteCountLow;
ULONG Retries;
ULONG CdbSize;
UCHAR Status;
DPRINT("AtapiSendAtapiCommand() called!\n");
if (Srb->PathId != 0)
{
Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
return(SRB_STATUS_INVALID_PATH_ID);
}
if (Srb->TargetId > 1)
{
Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
return(SRB_STATUS_INVALID_TARGET_ID);
}
if (Srb->Lun != 0)
{
Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
return(SRB_STATUS_INVALID_LUN);
}
if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
{
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
return(SRB_STATUS_NO_DEVICE);
}
if (Srb->Cdb[0] == SCSIOP_MODE_SENSE)
{
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
return (SRB_STATUS_INVALID_REQUEST);
}
DPRINT("AtapiSendAtapiCommand(): TargetId: %lu\n",
Srb->TargetId);
if (Srb->Cdb[0] == SCSIOP_INQUIRY)
return(AtapiInquiry(DeviceExtension,
Srb));
/* Set pointer to data buffer. */
DeviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
DeviceExtension->DataTransferLength = Srb->DataTransferLength;
DeviceExtension->CurrentSrb = Srb;
DPRINT("BufferAddress %x, BufferLength %d\n", Srb->DataBuffer, Srb->DataTransferLength);
/* Wait for BUSY to clear */
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
{
Status = IDEReadStatus(DeviceExtension->CommandPortBase);
if (!(Status & IDE_SR_BUSY))
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?