FindDevices函数主要用来查找ATAPI控制器,并且获取磁盘的参数。如果找到IDE的设备就返回TRUE,否则返回FALSE。其实是通过ATAPI的标志和IssueIdentify命令来判断IDE设备。
#001 BOOLEAN
#002 NTAPI
#003 FindDevices(
#004 IN PVOID HwDeviceExtension,
#005 IN BOOLEAN AtapiOnly,
#006 IN ULONG Channel
#007 )
#008
#009 /*++
#010
#011 Routine Description:
#012
#013 This routine is called from AtapiFindController to identify
#014 devices attached to an IDE controller.
#015
#016 Arguments:
#017
#018 HwDeviceExtension - HBA miniport driver's adapter data storage
#019 AtapiOnly - Indicates that routine should return TRUE only if
#020 an ATAPI device is attached to the controller.
#021
#022 Return Value:
#023
#024 TRUE - True if devices found.
#025
#026 --*/
#027
#028 {
HwDeviceExtension是主机总线适配器的数据。
#029 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
获取PCI总线配置空间的两个寄存器地址。
#030 PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Channel];
#031 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Channel];
#032 BOOLEAN deviceResponded = FALSE,
#033 skipSetParameters = FALSE;
#034 ULONG waitCount = 10000;
#035 ULONG deviceNumber;
#036 ULONG i;
#037 UCHAR signatureLow,
#038 signatureHigh;
#039 UCHAR statusByte;
#040
#041 //
#042 // Clear expecting interrupt flag and current SRB field.
#043 //
#044
清空需要中断的标志和SRB。
#045 deviceExtension->ExpectingInterrupt = FALSE;
#046 deviceExtension->CurrentSrb = NULL;
#047
#048 //
#049 // Search for devices.
#050 //
#051
每个IDE控制器上最多有两个设备。
#052 for (deviceNumber = 0; deviceNumber < 2; deviceNumber++) {
#053
#054 //
#055 // Select the device.
#056 //
#057
选择IDE主控制器。
#058 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
#059 (UCHAR)((deviceNumber << 4) | 0xA0));
#060
#061 //
#062 // Check here for some SCSI adapters that incorporate IDE emulation.
#063 //
#064
获取当前IDE控制器的状态,如果不成功就继续查找下一个。如果读回来的状态等于0XFF,说明总线是在浮动状态,也就是总是接到正5V的电源上。
#065 GetStatus(baseIoAddress2,statusByte);
#066 if (statusByte == 0xFF) {
#067 continue;
#068 }
#069
发送ATAPI的命令实现软件复位IDE控制器。
#070 AtapiSoftReset(baseIoAddress1,deviceNumber);
#071 WaitOnBusy(baseIoAddress2,statusByte);
#072
读取ATAPI的类型,比如是PATAPI,还是SATAPI/PATA/SATA。
#073 signatureLow = ScsiPortReadPortUchar(&baseIoAddress1->CylinderLow);
#074 signatureHigh = ScsiPortReadPortUchar(&baseIoAddress1->CylinderHigh);
#075
#076 if (signatureLow == 0x14 && signatureHigh == 0xEB) {
#077
如果发现是PATAPI的标志。
#078 //
#079 // ATAPI signature found.
#080 // Issue the ATAPI identify command if this
#081 // is not for the crash dump utility.
#082 //
#083
#084 atapiIssueId:
#085
如果设置不是轮询模式。
#086 if (!deviceExtension->DriverMustPoll) {
#087
#088 //
#089 // Issue ATAPI packet identify command.
#090 //
#091
发送IDE标识命令。
#092 if (IssueIdentify(HwDeviceExtension,
#093 deviceNumber,
#094 Channel,
#095 IDE_COMMAND_ATAPI_IDENTIFY)) {
#096
#097 //
#098 // Indicate ATAPI device.
#099 //
#100
#101 DebugPrint((1,
#102 "FindDevices: Device %x is ATAPI/n",
#103 deviceNumber));
#104
标识这里发现了ATAPI设备。
#105 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_ATAPI_DEVICE;
#106 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_DEVICE_PRESENT;
#107
#108 deviceResponded = TRUE;
#109
#110 GetStatus(baseIoAddress2,statusByte);
#111 if (statusByte & IDE_STATUS_ERROR) {
#112 AtapiSoftReset(baseIoAddress1,deviceNumber);
#113 }
#114
#115
#116 } else {
#117
没有发现任何ATAPI设备。
#118 //
#119 // Indicate no working device.
#120 //
#121
#122 DebugPrint((1,
#123 "FindDevices: Device %x not responding/n",
#124 deviceNumber));
#125
#126 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] &= ~DFLAGS_DEVICE_PRESENT;
#127 }
#128
#129 }
#130
#131 } else {
#132
#133 //
#134 // Issue IDE Identify. If an Atapi device is actually present,the signature
#135 // will be asserted,and the drive will be recognized as such.
#136 //
其它ATA设备类型,发送一个标识命令。
#137
#138 if (IssueIdentify(HwDeviceExtension,
#139 deviceNumber,
#140 Channel,
#141 IDE_COMMAND_IDENTIFY)) {
#142
#143 //
#144 // IDE drive found.
#145 //
#146
如果发送标识命令成功,说明发现了IDE设备。
#147
#148 DebugPrint((1,
#149 "FindDevices: Device %x is IDE/n",
#150 deviceNumber));
#151
#152 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_DEVICE_PRESENT;
#153
#154 if (!AtapiOnly) {
#155 deviceResponded = TRUE;
#156 }
#157
#158 //
#159 // Indicate IDE - not ATAPI device.
#160 //
#161
但这个设备不是ATAPI设备。
#162 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] &= ~DFLAGS_ATAPI_DEVICE;
#163
#164
#165 } else {
#166
#167 //
#168 // Look to see if an Atapi device is present.
#169 //
#170
再次查找,是否找到ATAPI标志,如果找到就再回去检查是否读取标识成功。
#171 AtapiSoftReset(baseIoAddress1,deviceNumber);
#172
#173 WaitOnBusy(baseIoAddress2,statusByte);
#174
#175 signatureLow = ScsiPortReadPortUchar(&baseIoAddress1->CylinderLow);
#176 signatureHigh = ScsiPortReadPortUchar(&baseIoAddress1->CylinderHigh);
#177
#178 if (signatureLow == 0x14 && signatureHigh == 0xEB) {
#179 goto atapiIssueId;
#180 }
#181 }
#182 }
#183 }
#184
开始对一些特别的IDE控制器进行参数转换处理。
#185 for (i = 0; i < 2; i++) {
#186 if ((deviceExtension->DeviceFlags[i + (Channel * 2)] & DFLAGS_DEVICE_PRESENT) &&
#187 (!(deviceExtension->DeviceFlags[i + (Channel * 2)] & DFLAGS_ATAPI_DEVICE)) && deviceResponded) {
#188
下面是对一些磁道和磁头的特别处理。
#189 //
#190 // This hideous hack is to deal with ESDI devices that return
#191 // garbage geometry in the IDENTIFY data.
#192 // This is ONLY for the crashdump environment as
#193 // these are ESDI devices.
#194 //
#195
#196 if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
#197 0x35 &&
#198 deviceExtension->IdentifyData[i].NumberOfHeads ==
#199 0x07) {
#200
#201 DebugPrint((1,
#202 "FindDevices: Found nasty Compaq ESDI!/n"));
#203
#204 //
#205 // Change these values to something reasonable.
#206 //
#207
#208 deviceExtension->IdentifyData[i].SectorsPerTrack =
#209 0x34;
#210 deviceExtension->IdentifyData[i].NumberOfHeads =
#211 0x0E;
#212 }
#213
#214 if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
#215 0x35 &&
#216 deviceExtension->IdentifyData[i].NumberOfHeads ==
#217 0x0F) {
#218
#219 DebugPrint((1,
#220 "FindDevices: Found nasty Compaq ESDI!/n"));
#221
#222 //
#223 // Change these values to something reasonable.
#224 //
#225
#226 deviceExtension->IdentifyData[i].SectorsPerTrack =
#227 0x34;
#228 deviceExtension->IdentifyData[i].NumberOfHeads =
#229 0x0F;
#230 }
#231
#232
#233 if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
#234 0x36 &&
#235 deviceExtension->IdentifyData[i].NumberOfHeads ==
#236 0x07) {
#237
#238 DebugPrint((1,
#239 "FindDevices: Found nasty UltraStor ESDI!/n"));
#240
#241 //
#242 // Change these values to something reasonable.
#243 //
#244
#245 deviceExtension->IdentifyData[i].SectorsPerTrack =
#246 0x3F;
#247 deviceExtension->IdentifyData[i].NumberOfHeads =
#248 0x10;
#249 skipSetParameters = TRUE;
#250 }
#251
#252
对磁盘进行参数设置。
#253 if (!skipSetParameters) {
#254
#255 WaitOnBusy(baseIoAddress2,statusByte);
#256
#257 //
#258 // Select the device.
#259 //
#260
#261 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
#262 (UCHAR)((i << 4) | 0xA0));
#263
#264 GetStatus(baseIoAddress2,statusByte);
#265
#266 if (statusByte & IDE_STATUS_ERROR) {
#267
#268 //
#269 // Reset the device.
#270 //
#271
#272 DebugPrint((2,
#273 "FindDevices: Resetting controller before SetDriveParameters./n"));
#274
#275 ScsiPortWritePortUchar(&baseIoAddress2->AlternateStatus,IDE_DC_RESET_CONTROLLER );
#276 ScsiPortStallExecution(500 * 1000);
#277 ScsiPortWritePortUchar(&baseIoAddress2->AlternateStatus,IDE_DC_REENABLE_CONTROLLER);
#278 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
#279 (UCHAR)((i << 4) | 0xA0));
#280
#281 do {
#282
#283 //
#284 // Wait for Busy to drop.
#285 //
#286
#287 ScsiPortStallExecution(100);
#288 GetStatus(baseIoAddress2,statusByte);
#289
#290 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
#291 }
#292
#293 WaitOnBusy(baseIoAddress2,statusByte);
#294 DebugPrint((2,
#295 "FindDevices: Status before SetDriveParameters: (%x) (%x)/n",
#296 statusByte,
#297 ScsiPortReadPortUchar(&baseIoAddress1->DriveSelect)));
#298
#299 //
#300 // Use the IDENTIFY data to set drive parameters.
#301 //
#302
#303 if (!SetDriveParameters(HwDeviceExtension,i,Channel)) {
#304
#305 DebugPrint((0,
#306 "AtapHwInitialize: Set drive parameters for device %d Failed/n",
#307 i));
#308
#309 //
#310 // Don't use this device as writes could cause corruption.
#311 //
#312
#313 deviceExtension->DeviceFlags[i + Channel] = 0;
#314 continue;
#315
#316 }
#317 if (deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] & DFLAGS_REMOVABLE_DRIVE) {
#318
#319 //
#320 // Pick up ALL IDE removable drives that conform to Yosemite V0.2...
#321 //
#322
#323 AtapiOnly = FALSE;
#324 }
#325
#326
#327 //
#328 // Indicate that a device was found.
#329 //
#330
#331 if (!AtapiOnly) {
#332 deviceResponded = TRUE;
#333 }
#334 }
#335 }
#336 }
#337
#338 //
#339 // Make sure master device is selected on exit.
#340 //
#341
选择主控制器。
#342 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,0xA0);
#343
#344 //
#345 // Reset the controller. This is a feeble attempt to leave the ESDI
#346 // controllers in a state that ATDISK driver will recognize them.
#347 // The problem in ATDISK has to do with timings as it is not reproducible
#348 // in debug. The reset should restore the controller to its poweron state
#349 // and give the system enough time to settle.
#350 //
#351
复位IDE控制器。
#352 if (!deviceResponded) {
#353
#354 ScsiPortWritePortUchar(&baseIoAddress2->AlternateStatus,IDE_DC_RESET_CONTROLLER );
#355 ScsiPortStallExecution(50 * 1000);
#356 ScsiPortWritePortUchar(&baseIoAddress2->AlternateStatus,IDE_DC_REENABLE_CONTROLLER);
#357 }
#358
#359 return deviceResponded;
#360
#361} // end FindDevices()