reactos操作系统实现(108)
AtapiHwInitialize函数初始化不是ATAPT设备,设置它支持多块传送。接着判断那些设备是CD-ROM设备,还清除忙状态。具体实现代码如下:
#001 BOOLEAN
#002 NTAPI
#003 AtapiHwInitialize(
#004 IN PVOID HwDeviceExtension
#005 )
#006
#007 /*++
#008
#009 Routine Description:
#010
#011 Arguments:
#012
#013 HwDeviceExtension - HBA miniport driver's adapter data storage
#014
#015 Return Value:
#016
#017 TRUE - if initialization successful.
#018 FALSE - if initialization unsuccessful.
#019
#020 --*/
#021
#022 {
#023 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
#024 PIDE_REGISTERS_1 baseIoAddress;
#025 ULONG i;
#026 UCHAR statusByte, errorByte;
#027
#028
对于两个通道4个IDE控制器进行初始化。
#029 for (i = 0; i < 4; i++) {
如果IDE的设备存在,就进行处理。
#030 if (deviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT) {
#031
如果这个设备不是ATAPI设备,就进入下面初始化。
#032 if (!(deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE)) {
#033
#034 //
#035 // Enable media status notification
#036 //
#037
获取基地址。
#038 baseIoAddress = deviceExtension->BaseIoAddress1[i >> 1];
#039
设置媒体感知。
#040 IdeMediaStatus(TRUE,HwDeviceExtension,i);
#041
如果支持多块传送,就设置多块传送参数。
#042 //
#043 // If supported, setup Multi-block transfers.
#044 //
#045 if (deviceExtension->MaximumBlockXfer[i]) {
#046
#047 //
#048 // Select the device.
#049 //
#050
#051 ScsiPortWritePortUchar(&baseIoAddress->DriveSelect,
#052 (UCHAR)(((i & 0x1) << 4) | 0xA0));
#053
#054 //
#055 // Setup sector count to reflect the # of blocks.
#056 //
#057
#058 ScsiPortWritePortUchar(&baseIoAddress->BlockCount,
#059 deviceExtension->MaximumBlockXfer[i]);
#060
#061 //
#062 // Issue the command.
#063 //
#064
设置多块传送。
#065 ScsiPortWritePortUchar(&baseIoAddress->Command,
#066 IDE_COMMAND_SET_MULTIPLE);
#067
#068 //
#069 // Wait for busy to drop.
#070 //
#071
#072 WaitOnBaseBusy(baseIoAddress,statusByte);
#073
#074 //
#075 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
#076 // command was aborted.
#077 //
#078
如果设置多块传送命令失败,就设置为不支持多块传送。
#079 if (statusByte & IDE_STATUS_ERROR) {
#080
#081 //
#082 // Read the error register.
#083 //
#084
#085 errorByte = ScsiPortReadPortUchar((PUCHAR)baseIoAddress + 1);
#086
#087 DebugPrint((1,
#088 "AtapiHwInitialize: Error setting multiple mode. Status %x, error byte %x/n",
#089 statusByte,
#090 errorByte));
#091 //
#092 // Adjust the devExt. value, if necessary.
#093 //
#094
#095 deviceExtension->MaximumBlockXfer[i] = 0;
#096
#097 } else {
#098 DebugPrint((2,
#099 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d/n",
#100 i,
#101 deviceExtension->MaximumBlockXfer[i]));
#102 }
#103 }
#104 } else if (!(deviceExtension->DeviceFlags[i] & DFLAGS_CHANGER_INITED)){
如果这个设备还没有初始化,就进行初始化设置。
#105
#106 ULONG j;
#107 BOOLEAN isSanyo = FALSE;
#108 UCHAR vendorId[26];
#109
#110 //
#111 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
#112 //
#113
判断这个IDE设备是否为CR-ROM设备。
#114 for (j = 0; j < 13; j += 2) {
#115
#116 //
#117 // Build a buffer based on the identify data.
#118 //
#119
#120 vendorId[j] = ((PUCHAR)deviceExtension->IdentifyData[i].ModelNumber)[j + 1];
#121 vendorId[j+1] = ((PUCHAR)deviceExtension->IdentifyData[i].ModelNumber)[j];
#122 }
#123
比较IDE设备标识是否为CD-ROM。
#124 if (!AtapiStringCmp ((PCHAR)vendorId, "CD-ROM CDR", 11)) {
#125
#126 //
#127 // Inquiry string for older model had a '-', newer is '_'
#128 //
#129
#130 if (vendorId[12] == 'C') {
#131
#132 //
#133 // Torisan changer. Set the bit. This will be used in several places
#134 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
#135 //
#136
设置设备已经初始化。
#137 deviceExtension->DeviceFlags[i] |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER);
#138 deviceExtension->DiscsPresent[i] = 3;
#139 isSanyo = TRUE;
#140 }
#141 }
#142 }
#143
#144 //
#145 // We need to get our device ready for action before
#146 // returning from this function
#147 //
#148 // According to the atapi spec 2.5 or 2.6, an atapi device
#149 // clears its status BSY bit when it is ready for atapi commands.
#150 // However, some devices (Panasonic SQ-TC500N) are still
#151 // not ready even when the status BSY is clear. They don't react
#152 // to atapi commands.
#153 //
#154 // Since there is really no other indication that tells us
#155 // the drive is really ready for action. We are going to check BSY
#156 // is clear and then just wait for an arbitrary amount of time!
#157 //
下面开始清除忙状态。
#158 if (deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE) {
#159 //PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[i >> 1];
#160 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[i >> 1];
#161 ULONG waitCount;
#162
#163 // have to get out of the loop sometime!
#164 // 10000 * 100us = 1000,000us = 1000ms = 1s
#165 waitCount = 10000;
#166 GetStatus(baseIoAddress2, statusByte);
#167 while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
#168 //
#169 // Wait for Busy to drop.
#170 //
#171 ScsiPortStallExecution(100);
#172 GetStatus(baseIoAddress2, statusByte);
#173 waitCount--;
#174 }
#175
#176 // 5000 * 100us = 500,000us = 500ms = 0.5s
#177 waitCount = 5000;
#178 do {
#179 ScsiPortStallExecution(100);
#180 } while (waitCount--);
#181 }
#182 }
#183 }
#184
#185 return TRUE;
#186
#187 } // end AtapiHwInitialize()