📄 atapi.c
字号:
}
WaitOnBusy(baseIoAddress2,statusByte);
}
if (i == 4 && j == 0) {
//
// Device didn't respond correctly. It will be given one more chances.
//
DebugPrint((1,
"IssueIdentify: DRQ never asserted (%x). Error reg (%x)\n",
statusByte,
ScsiPortReadPortUchar((PUCHAR)baseIoAddress1 + 1)));
AtapiSoftReset(baseIoAddress1,DeviceNumber);
GetStatus(baseIoAddress2,statusByte);
DebugPrint((1,
"IssueIdentify: Status after soft reset (%x)\n",
statusByte));
} else {
break;
}
}
//
// Check for error on really stupid master devices that assert random
// patterns of bits in the status register at the slave address.
//
if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
return FALSE;
}
DebugPrint((1,
"IssueIdentify: Status before read words %x\n",
statusByte));
//
// Suck out 256 words. After waiting for one model that asserts busy
// after receiving the Packet Identify command.
//
WaitOnBusy(baseIoAddress2,statusByte);
if (!(statusByte & IDE_STATUS_DRQ)) {
return FALSE;
}
ReadBuffer(baseIoAddress1,
(PUSHORT)&deviceExtension->FullIdentifyData,
256);
//
// Check out a few capabilities / limitations of the device.
//
if (deviceExtension->FullIdentifyData.SpecialFunctionsEnabled & 1) {
//
// Determine if this drive supports the MSN functions.
//
DebugPrint((2,"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
Channel * 2 + DeviceNumber,
deviceExtension->FullIdentifyData.SpecialFunctionsEnabled));
deviceExtension->DeviceFlags[(Channel * 2) + DeviceNumber] |= DFLAGS_REMOVABLE_DRIVE;
}
if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
//
// Determine max. block transfer for this device.
//
deviceExtension->MaximumBlockXfer[(Channel * 2) + DeviceNumber] =
(UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
}
ScsiPortMoveMemory(&deviceExtension->IdentifyData[(Channel * 2) + DeviceNumber],&deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
if (deviceExtension->IdentifyData[(Channel * 2) + DeviceNumber].GeneralConfiguration & 0x20 &&
Command != IDE_COMMAND_IDENTIFY) {
//
// This device interrupts with the assertion of DRQ after receiving
// Atapi Packet Command
//
deviceExtension->DeviceFlags[(Channel * 2) + DeviceNumber] |= DFLAGS_INT_DRQ;
DebugPrint((2,
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
} else {
DebugPrint((2,
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
}
if (((deviceExtension->IdentifyData[(Channel * 2) + DeviceNumber].GeneralConfiguration & 0xF00) == 0x100) &&
Command != IDE_COMMAND_IDENTIFY) {
//
// This is a tape.
//
deviceExtension->DeviceFlags[(Channel * 2) + DeviceNumber] |= DFLAGS_TAPE_DEVICE;
DebugPrint((2,
"IssueIdentify: Device is a tape drive.\n"));
} else {
DebugPrint((2,
"IssueIdentify: Device is not a tape drive.\n"));
}
//
// Work around for some IDE and one model Atapi that will present more than
// 256 bytes for the Identify data.
//
WaitOnBusy(baseIoAddress2,statusByte);
for (i = 0; i < 0x10000; i++) {
GetStatus(baseIoAddress2,statusByte);
if (statusByte & IDE_STATUS_DRQ) {
//
// Suck out any remaining bytes and throw away.
//
ScsiPortReadPortUshort(&baseIoAddress1->Data);
} else {
break;
}
}
DebugPrint((3,
"IssueIdentify: Status after read words (%x)\n",
statusByte));
return TRUE;
} // end IssueIdentify()
BOOLEAN
STDCALL
SetDriveParameters(
IN PVOID HwDeviceExtension,
IN ULONG DeviceNumber,
IN ULONG Channel
)
/*++
Routine Description:
Set drive parameters using the IDENTIFY data.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
DeviceNumber - Indicates which device.
Return Value:
TRUE if all goes well.
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Channel];
PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Channel];
PIDENTIFY_DATA2 identifyData = &deviceExtension->IdentifyData[(Channel * 2) + DeviceNumber];
ULONG i;
UCHAR statusByte;
DebugPrint((1,
"SetDriveParameters: Number of heads %x\n",
identifyData->NumberOfHeads));
DebugPrint((1,
"SetDriveParameters: Sectors per track %x\n",
identifyData->SectorsPerTrack));
//
// Set up registers for SET PARAMETER command.
//
ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
(UCHAR)(((DeviceNumber << 4) | 0xA0) | (identifyData->NumberOfHeads - 1)));
ScsiPortWritePortUchar(&baseIoAddress1->BlockCount,
(UCHAR)identifyData->SectorsPerTrack);
//
// Send SET PARAMETER command.
//
ScsiPortWritePortUchar(&baseIoAddress1->Command,
IDE_COMMAND_SET_DRIVE_PARAMETERS);
//
// Wait for up to 30 milliseconds for ERROR or command complete.
//
for (i=0; i<30 * 1000; i++) {
UCHAR errorByte;
GetStatus(baseIoAddress2, statusByte);
if (statusByte & IDE_STATUS_ERROR) {
errorByte = ScsiPortReadPortUchar((PUCHAR)baseIoAddress1 + 1);
DebugPrint((1,
"SetDriveParameters: Error bit set. Status %x, error %x\n",
errorByte,
statusByte));
return FALSE;
} else if ((statusByte & ~IDE_STATUS_INDEX ) == IDE_STATUS_IDLE) {
break;
} else {
ScsiPortStallExecution(100);
}
}
//
// Check for timeout.
//
if (i == 30 * 1000) {
return FALSE;
} else {
return TRUE;
}
} // end SetDriveParameters()
BOOLEAN
STDCALL
AtapiResetController(
IN PVOID HwDeviceExtension,
IN ULONG PathId
)
/*++
Routine Description:
Reset IDE controller and/or Atapi device.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
Return Value:
Nothing.
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
ULONG numberChannels = deviceExtension->NumberChannels;
PIDE_REGISTERS_1 baseIoAddress1;
PIDE_REGISTERS_2 baseIoAddress2;
BOOLEAN result = FALSE;
ULONG i,j;
UCHAR statusByte;
DebugPrint((2,"AtapiResetController: Reset IDE\n"));
//
// Check and see if we are processing an internal srb
//
if (deviceExtension->OriginalSrb) {
deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;
deviceExtension->OriginalSrb = NULL;
}
//
// Check if request is in progress.
//
if (deviceExtension->CurrentSrb) {
//
// Complete outstanding request with SRB_STATUS_BUS_RESET.
//
ScsiPortCompleteRequest(deviceExtension,
deviceExtension->CurrentSrb->PathId,
deviceExtension->CurrentSrb->TargetId,
deviceExtension->CurrentSrb->Lun,
(ULONG)SRB_STATUS_BUS_RESET);
//
// Clear request tracking fields.
//
deviceExtension->CurrentSrb = NULL;
deviceExtension->WordsLeft = 0;
deviceExtension->DataBuffer = NULL;
//
// Indicate ready for next request.
//
ScsiPortNotification(NextRequest,
deviceExtension,
NULL);
}
//
// Clear expecting interrupt flag.
//
deviceExtension->ExpectingInterrupt = FALSE;
deviceExtension->RDP = FALSE;
for (j = 0; j < numberChannels; j++) {
baseIoAddress1 = deviceExtension->BaseIoAddress1[j];
baseIoAddress2 = deviceExtension->BaseIoAddress2[j];
//
// Do special processing for ATAPI and IDE disk devices.
//
for (i = 0; i < 2; i++) {
//
// Check if device present.
//
if (deviceExtension->DeviceFlags[i + (j * 2)] & DFLAGS_DEVICE_PRESENT) {
//
// Check for ATAPI disk.
//
if (deviceExtension->DeviceFlags[i + (j * 2)] & DFLAGS_ATAPI_DEVICE) {
//
// Issue soft reset and issue identify.
//
GetStatus(baseIoAddress2,statusByte);
DebugPrint((1,
"AtapiResetController: Status before Atapi reset (%x).\n",
statusByte));
AtapiSoftReset(baseIoAddress1,i);
GetStatus(baseIoAddress2,statusByte);
if (statusByte == 0x0) {
IssueIdentify(HwDeviceExtension,
i,
j,
IDE_COMMAND_ATAPI_IDENTIFY);
} else {
DebugPrint((1,
"AtapiResetController: Status after soft reset %x\n",
statusByte));
}
} else {
//
// Write IDE reset controller bits.
//
IdeHardReset(baseIoAddress2,result);
if (!result) {
return FALSE;
}
//
// Set disk geometry parameters.
//
if (!SetDriveParameters(HwDeviceExtension,
i,
j)) {
DebugPrint((1,
"AtapiResetController: SetDriveParameters failed\n"));
}
}
}
}
}
//
// Call the HwInitialize routine to setup multi-block.
//
AtapiHwInitialize(HwDeviceExtension);
return TRUE;
} // end AtapiResetController()
ULONG
STDCALL
MapError(
IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb
)
/*++
Routine Description:
This routine maps ATAPI and IDE errors to specific SRB statuses.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
Srb - IO request packet
Return Value:
SRB status
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Srb->TargetId >> 1];
PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Srb->TargetId >> 1];
ULONG i;
UCHAR errorByte;
UCHAR srbStatus;
UCHAR scsiStatus;
//
// Read the error register.
//
errorByte = ScsiPortReadPortUchar((PUCHAR)baseIoAddress1 + 1);
DebugPrint((1,
"MapError: Error register is %x\n",
errorByte));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -