📄 atapi.c
字号:
deviceExtension->DiscsPresent[i] = 3;
isSanyo = TRUE;
}
}
}
//
// We need to get our device ready for action before
// returning from this function
//
// According to the atapi spec 2.5 or 2.6, an atapi device
// clears its status BSY bit when it is ready for atapi commands.
// However, some devices (Panasonic SQ-TC500N) are still
// not ready even when the status BSY is clear. They don't react
// to atapi commands.
//
// Since there is really no other indication that tells us
// the drive is really ready for action. We are going to check BSY
// is clear and then just wait for an arbitrary amount of time!
//
if (deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE) {
PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[i >> 1];
PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[i >> 1];
ULONG waitCount;
// have to get out of the loop sometime!
// 10000 * 100us = 1000,000us = 1000ms = 1s
waitCount = 10000;
GetStatus(baseIoAddress2, statusByte);
while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
//
// Wait for Busy to drop.
//
ScsiPortStallExecution(100);
GetStatus(baseIoAddress2, statusByte);
waitCount--;
}
// 5000 * 100us = 500,000us = 500ms = 0.5s
waitCount = 5000;
do {
ScsiPortStallExecution(100);
} while (waitCount--);
}
}
}
return TRUE;
} // end AtapiHwInitialize()
VOID
STDCALL
AtapiHwInitializeChanger (
IN PVOID HwDeviceExtension,
IN ULONG TargetId,
IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
if (MechanismStatus) {
deviceExtension->DiscsPresent[TargetId] = MechanismStatus->NumberAvailableSlots;
if (deviceExtension->DiscsPresent[TargetId] > 1) {
deviceExtension->DeviceFlags[TargetId] |= DFLAGS_ATAPI_CHANGER;
}
}
return;
}
BOOLEAN
STDCALL
FindDevices(
IN PVOID HwDeviceExtension,
IN BOOLEAN AtapiOnly,
IN ULONG Channel
)
/*++
Routine Description:
This routine is called from AtapiFindController to identify
devices attached to an IDE controller.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
AtapiOnly - Indicates that routine should return TRUE only if
an ATAPI device is attached to the controller.
Return Value:
TRUE - True if devices found.
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Channel];
PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Channel];
BOOLEAN deviceResponded = FALSE,
skipSetParameters = FALSE;
ULONG waitCount = 10000;
ULONG deviceNumber;
ULONG i;
UCHAR signatureLow,
signatureHigh;
UCHAR statusByte;
//
// Clear expecting interrupt flag and current SRB field.
//
deviceExtension->ExpectingInterrupt = FALSE;
deviceExtension->CurrentSrb = NULL;
//
// Search for devices.
//
for (deviceNumber = 0; deviceNumber < 2; deviceNumber++) {
//
// Select the device.
//
ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
(UCHAR)((deviceNumber << 4) | 0xA0));
//
// Check here for some SCSI adapters that incorporate IDE emulation.
//
GetStatus(baseIoAddress2, statusByte);
if (statusByte == 0xFF) {
continue;
}
AtapiSoftReset(baseIoAddress1,deviceNumber);
WaitOnBusy(baseIoAddress2,statusByte);
signatureLow = ScsiPortReadPortUchar(&baseIoAddress1->CylinderLow);
signatureHigh = ScsiPortReadPortUchar(&baseIoAddress1->CylinderHigh);
if (signatureLow == 0x14 && signatureHigh == 0xEB) {
//
// ATAPI signature found.
// Issue the ATAPI identify command if this
// is not for the crash dump utility.
//
atapiIssueId:
if (!deviceExtension->DriverMustPoll) {
//
// Issue ATAPI packet identify command.
//
if (IssueIdentify(HwDeviceExtension,
deviceNumber,
Channel,
IDE_COMMAND_ATAPI_IDENTIFY)) {
//
// Indicate ATAPI device.
//
DebugPrint((1,
"FindDevices: Device %x is ATAPI\n",
deviceNumber));
deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_ATAPI_DEVICE;
deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_DEVICE_PRESENT;
deviceResponded = TRUE;
GetStatus(baseIoAddress2, statusByte);
if (statusByte & IDE_STATUS_ERROR) {
AtapiSoftReset(baseIoAddress1, deviceNumber);
}
} else {
//
// Indicate no working device.
//
DebugPrint((1,
"FindDevices: Device %x not responding\n",
deviceNumber));
deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] &= ~DFLAGS_DEVICE_PRESENT;
}
}
} else {
//
// Issue IDE Identify. If an Atapi device is actually present, the signature
// will be asserted, and the drive will be recognized as such.
//
if (IssueIdentify(HwDeviceExtension,
deviceNumber,
Channel,
IDE_COMMAND_IDENTIFY)) {
//
// IDE drive found.
//
DebugPrint((1,
"FindDevices: Device %x is IDE\n",
deviceNumber));
deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_DEVICE_PRESENT;
if (!AtapiOnly) {
deviceResponded = TRUE;
}
//
// Indicate IDE - not ATAPI device.
//
deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] &= ~DFLAGS_ATAPI_DEVICE;
} else {
//
// Look to see if an Atapi device is present.
//
AtapiSoftReset(baseIoAddress1,deviceNumber);
WaitOnBusy(baseIoAddress2,statusByte);
signatureLow = ScsiPortReadPortUchar(&baseIoAddress1->CylinderLow);
signatureHigh = ScsiPortReadPortUchar(&baseIoAddress1->CylinderHigh);
if (signatureLow == 0x14 && signatureHigh == 0xEB) {
goto atapiIssueId;
}
}
}
}
for (i = 0; i < 2; i++) {
if ((deviceExtension->DeviceFlags[i + (Channel * 2)] & DFLAGS_DEVICE_PRESENT) &&
(!(deviceExtension->DeviceFlags[i + (Channel * 2)] & DFLAGS_ATAPI_DEVICE)) && deviceResponded) {
//
// This hideous hack is to deal with ESDI devices that return
// garbage geometry in the IDENTIFY data.
// This is ONLY for the crashdump environment as
// these are ESDI devices.
//
if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
0x35 &&
deviceExtension->IdentifyData[i].NumberOfHeads ==
0x07) {
DebugPrint((1,
"FindDevices: Found nasty Compaq ESDI!\n"));
//
// Change these values to something reasonable.
//
deviceExtension->IdentifyData[i].SectorsPerTrack =
0x34;
deviceExtension->IdentifyData[i].NumberOfHeads =
0x0E;
}
if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
0x35 &&
deviceExtension->IdentifyData[i].NumberOfHeads ==
0x0F) {
DebugPrint((1,
"FindDevices: Found nasty Compaq ESDI!\n"));
//
// Change these values to something reasonable.
//
deviceExtension->IdentifyData[i].SectorsPerTrack =
0x34;
deviceExtension->IdentifyData[i].NumberOfHeads =
0x0F;
}
if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
0x36 &&
deviceExtension->IdentifyData[i].NumberOfHeads ==
0x07) {
DebugPrint((1,
"FindDevices: Found nasty UltraStor ESDI!\n"));
//
// Change these values to something reasonable.
//
deviceExtension->IdentifyData[i].SectorsPerTrack =
0x3F;
deviceExtension->IdentifyData[i].NumberOfHeads =
0x10;
skipSetParameters = TRUE;
}
if (!skipSetParameters) {
WaitOnBusy(baseIoAddress2,statusByte);
//
// Select the device.
//
ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
(UCHAR)((i << 4) | 0xA0));
GetStatus(baseIoAddress2, statusByte);
if (statusByte & IDE_STATUS_ERROR) {
//
// Reset the device.
//
DebugPrint((2,
"FindDevices: Resetting controller before SetDriveParameters.\n"));
ScsiPortWritePortUchar(&baseIoAddress2->AlternateStatus,IDE_DC_RESET_CONTROLLER );
ScsiPortStallExecution(500 * 1000);
ScsiPortWritePortUchar(&baseIoAddress2->AlternateStatus,IDE_DC_REENABLE_CONTROLLER);
ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
(UCHAR)((i << 4) | 0xA0));
do {
//
// Wait for Busy to drop.
//
ScsiPortStallExecution(100);
GetStatus(baseIoAddress2, statusByte);
} while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
}
WaitOnBusy(baseIoAddress2,statusByte);
DebugPrint((2,
"FindDevices: Status before SetDriveParameters: (%x) (%x)\n",
statusByte,
ScsiPortReadPortUchar(&baseIoAddress1->DriveSelect)));
//
// Use the IDENTIFY data to set drive parameters.
//
if (!SetDriveParameters(HwDeviceExtension,i,Channel)) {
DebugPrint((0,
"AtapHwInitialize: Set drive parameters for device %d failed\n",
i));
//
// Don't use this device as writes could cause corruption.
//
deviceExtension->DeviceFlags[i + Channel] = 0;
continue;
}
if (deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] & DFLAGS_REMOVABLE_DRIVE) {
//
// Pick up ALL IDE removable drives that conform to Yosemite V0.2...
//
AtapiOnly = FALSE;
}
//
// Indicate that a device was found.
//
if (!AtapiOnly) {
deviceResponded = TRUE;
}
}
}
}
//
// Make sure master device is selected on exit.
//
ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect, 0xA0);
//
// Reset the controller. This is a feeble attempt to leave the ESDI
// controllers in a state that ATDISK driver will recognize them.
// The problem in ATDISK has to do with timings as it is not reproducible
// in debug. The reset should restore the controller to its poweron state
// and give the system enough time to settle.
//
if (!deviceResponded) {
ScsiPortWritePortUchar(&baseIoAddress2->AlternateStatus,IDE_DC_RESET_CONTROLLER );
ScsiPortStallExecution(50 * 1000);
ScsiPortWritePortUchar(&baseIoAddress2->AlternateStatus,IDE_DC_REENABLE_CONTROLLER);
}
return deviceResponded;
} // end FindDevices()
ULONG
STDCALL
AtapiParseArgumentString(
IN PCHAR String,
IN PCHAR KeyWord
)
/*++
Routine Description:
This routine will parse the string for a match on the keyword, then
calculate the value for the keyword and return it to the caller.
Arguments:
String - The ASCII string to parse.
KeyWord - The keyword for the value desired.
Return Values:
Zero if value not found
Value converted from ASCII to binary.
--*/
{
PCHAR cptr;
PCHAR kptr;
ULONG value;
ULONG stringLength = 0;
ULONG keyWordLength = 0;
ULONG index;
if (!String) {
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -