📄 atapi.c
字号:
if (!KeyWord) {
return 0;
}
//
// Calculate the string length and lower case all characters.
//
cptr = String;
while (*cptr) {
if (*cptr >= 'A' && *cptr <= 'Z') {
*cptr = *cptr + ('a' - 'A');
}
cptr++;
stringLength++;
}
//
// Calculate the keyword length and lower case all characters.
//
cptr = KeyWord;
while (*cptr) {
if (*cptr >= 'A' && *cptr <= 'Z') {
*cptr = *cptr + ('a' - 'A');
}
cptr++;
keyWordLength++;
}
if (keyWordLength > stringLength) {
//
// Can't possibly have a match.
//
return 0;
}
//
// Now setup and start the compare.
//
cptr = String;
ContinueSearch:
//
// The input string may start with white space. Skip it.
//
while (*cptr == ' ' || *cptr == '\t') {
cptr++;
}
if (*cptr == '\0') {
//
// end of string.
//
return 0;
}
kptr = KeyWord;
while (*cptr++ == *kptr++) {
if (*(cptr - 1) == '\0') {
//
// end of string
//
return 0;
}
}
if (*(kptr - 1) == '\0') {
//
// May have a match backup and check for blank or equals.
//
cptr--;
while (*cptr == ' ' || *cptr == '\t') {
cptr++;
}
//
// Found a match. Make sure there is an equals.
//
if (*cptr != '=') {
//
// Not a match so move to the next semicolon.
//
while (*cptr) {
if (*cptr++ == ';') {
goto ContinueSearch;
}
}
return 0;
}
//
// Skip the equals sign.
//
cptr++;
//
// Skip white space.
//
while ((*cptr == ' ') || (*cptr == '\t')) {
cptr++;
}
if (*cptr == '\0') {
//
// Early end of string, return not found
//
return 0;
}
if (*cptr == ';') {
//
// This isn't it either.
//
cptr++;
goto ContinueSearch;
}
value = 0;
if ((*cptr == '0') && (*(cptr + 1) == 'x')) {
//
// Value is in Hex. Skip the "0x"
//
cptr += 2;
for (index = 0; *(cptr + index); index++) {
if (*(cptr + index) == ' ' ||
*(cptr + index) == '\t' ||
*(cptr + index) == ';') {
break;
}
if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
value = (16 * value) + (*(cptr + index) - '0');
} else {
if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
value = (16 * value) + (*(cptr + index) - 'a' + 10);
} else {
//
// Syntax error, return not found.
//
return 0;
}
}
}
} else {
//
// Value is in Decimal.
//
for (index = 0; *(cptr + index); index++) {
if (*(cptr + index) == ' ' ||
*(cptr + index) == '\t' ||
*(cptr + index) == ';') {
break;
}
if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
value = (10 * value) + (*(cptr + index) - '0');
} else {
//
// Syntax error return not found.
//
return 0;
}
}
}
return value;
} else {
//
// Not a match check for ';' to continue search.
//
while (*cptr) {
if (*cptr++ == ';') {
goto ContinueSearch;
}
}
return 0;
}
}
ULONG
STDCALL
AtapiFindController(
IN PVOID HwDeviceExtension,
IN PVOID Context,
IN PVOID BusInformation,
IN PCHAR ArgumentString,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
OUT PBOOLEAN Again
)
/*++
Routine Description:
This function is called by the OS-specific port driver after
the necessary storage has been allocated, to gather information
about the adapter's configuration.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
Context - Address of adapter count
ArgumentString - Used to determine whether driver is client of ntldr or crash dump utility.
ConfigInfo - Configuration information structure describing HBA
Again - Indicates search for adapters to continue
Return Value:
ULONG
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PULONG adapterCount = (PULONG)Context;
PUCHAR ioSpace;
ULONG i,j;
ULONG irq;
ULONG portBase;
ULONG retryCount;
PCI_SLOT_NUMBER slotData;
PPCI_COMMON_CONFIG pciData;
ULONG pciBuffer;
BOOLEAN atapiOnly;
UCHAR statusByte;
BOOLEAN preConfig = FALSE;
//
// The following table specifies the ports to be checked when searching for
// an IDE controller. A zero entry terminates the search.
//
CONST ULONG AdapterAddresses[5] = {0x1F0, 0x170, 0x1e8, 0x168, 0};
//
// The following table specifies interrupt levels corresponding to the
// port addresses in the previous table.
//
CONST ULONG InterruptLevels[5] = {14, 15, 11, 10, 0};
if (!deviceExtension) {
return SP_RETURN_ERROR;
}
//
// Check to see if this is a special configuration environment.
//
portBase = irq = 0;
if (ArgumentString) {
irq = AtapiParseArgumentString(ArgumentString, "Interrupt");
if (irq ) {
//
// Both parameters must be present to proceed
//
portBase = AtapiParseArgumentString(ArgumentString, "BaseAddress");
if (!portBase) {
//
// Try a default search for the part.
//
irq = 0;
}
}
}
//
// Scan though the adapter address looking for adapters.
//
if (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart) != 0) {
ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
ConfigInfo->AdapterInterfaceType,
ConfigInfo->SystemIoBusNumber,
(*ConfigInfo->AccessRanges)[0].RangeStart,
(*ConfigInfo->AccessRanges)[0].RangeLength,
(BOOLEAN) !((*ConfigInfo->AccessRanges)[0].RangeInMemory));
*Again = FALSE;
//
// Since we have pre-configured information we only need to go through this loop once
//
preConfig = TRUE;
portBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart);
}
while (AdapterAddresses[*adapterCount] != 0) {
retryCount = 4;
for (i = 0; i < 4; i++) {
//
// Zero device fields to ensure that if earlier devices were found,
// but not claimed, the fields are cleared.
//
deviceExtension->DeviceFlags[i] &= ~(DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT | DFLAGS_TAPE_DEVICE);
}
//
// Get the system physical address for this IO range.
//
//
// Check if configInfo has the default information
// if not, we go and find ourselves
//
if (preConfig == FALSE) {
if (portBase) {
ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
ConfigInfo->AdapterInterfaceType,
ConfigInfo->SystemIoBusNumber,
ScsiPortConvertUlongToPhysicalAddress(portBase),
8,
TRUE);
} else {
ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
ConfigInfo->AdapterInterfaceType,
ConfigInfo->SystemIoBusNumber,
ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount]),
8,
TRUE);
}
}// ConfigInfo check
//
// Update the adapter count.
//
(*adapterCount)++;
//
// Check if ioSpace accessible.
//
if (!ioSpace) {
continue;
}
retryIdentifier:
//
// Select master.
//
ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect, 0xA0);
//
// Check if card at this address.
//
ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow, 0xAA);
//
// Check if indentifier can be read back.
//
if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
DebugPrint((2,
"AtapiFindController: Identifier read back from Master (%x)\n",
statusByte));
statusByte = ScsiPortReadPortUchar(&((PATAPI_REGISTERS_2)ioSpace)->AlternateStatus);
if (statusByte & IDE_STATUS_BUSY) {
i = 0;
//
// Could be the TEAC in a thinkpad. Their dos driver puts it in a sleep-mode that
// warm boots don't clear.
//
do {
ScsiPortStallExecution(1000);
statusByte = ScsiPortReadPortUchar(&((PATAPI_REGISTERS_1)ioSpace)->Command);
DebugPrint((3,
"AtapiFindController: First access to status %x\n",
statusByte));
} while ((statusByte & IDE_STATUS_BUSY) && ++i < 10);
if (retryCount-- && (!(statusByte & IDE_STATUS_BUSY))) {
goto retryIdentifier;
}
}
//
// Select slave.
//
ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect, 0xB0);
//
// See if slave is present.
//
ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow, 0xAA);
if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
DebugPrint((2,
"AtapiFindController: Identifier read back from Slave (%x)\n",
statusByte));
//
//
// No controller at this base address.
//
ScsiPortFreeDeviceBase(HwDeviceExtension,
ioSpace);
continue;
}
}
//
// Record base IO address.
//
d
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -