reactos操作系统实现(106)
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() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |