zl程序教程

您现在的位置是:首页 >  系统

当前栏目

reactos操作系统实现(106)

操作系统 实现 reactos 106
2023-09-14 09:10:38 时间

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()