reactos操作系统实现(112)
IdeReadWrite函数主要实现了IDE设备的读和写命令发送。具体实现函数如下: #001 ULONG #002 NTAPI #003 IdeReadWrite( #004 IN PVOID HwDeviceExtension, #005 IN PSCSI_REQUEST_BLOCK Srb #006 ) #007 #008 /*++ #009 #010 Routine Description: #011 #012 This routine handles IDE read and writes. #013 #014 Arguments: #015 #016 HwDeviceExtension - HBA miniport driver's adapter data storage #017 Srb - IO request packet #018 #019 Return Value: #020 #021 SRB status #022 #023 --*/ #024 #025 {
获取驱动程序扩展对象和基地址寄存器。 #026 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; #027 PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Srb->TargetId >> 1]; #028 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Srb->TargetId >> 1]; #029 ULONG startingSector,i; #030 ULONG wordCount; #031 UCHAR statusByte,statusByte2; #032 UCHAR cylinderHigh,cylinderLow,drvSelect,sectorNumber; #033 #034 // #035 // Select device 0 or 1. #036 // #037
选择IDE设备0,还是设备1. #038 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect, #039 (UCHAR)(((Srb->TargetId & 0x1) << 4) | 0xA0)); #040
等待选择设备命令完成。 #041 WaitOnBusy(baseIoAddress2,statusByte2); #042
如果命令没有执行成功就返回。 #043 if (statusByte2 & IDE_STATUS_BUSY) { #044 DebugPrint((1, #045 "IdeReadWrite: Returning BUSY status/n")); #046 return SRB_STATUS_BUSY; #047 } #048 #049 // #050 // Set data buffer pointer and words left. #051 // #052
设置输出或读取缓冲区和传送的字节个数。 #053 deviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer; #054 deviceExtension->WordsLeft = Srb->DataTransferLength / 2; #055 #056 // #057 // Indicate expecting an interrupt. #058 // #059
设置期望使用中断响应。 #060 deviceExtension->ExpectingInterrupt = TRUE; #061 #062 // #063 // Set up sector count register. Round up to next block. #064 // #065
设置要传送的扇区寄器。 #066 ScsiPortWritePortUchar(&baseIoAddress1->BlockCount, #067 (UCHAR)((Srb->DataTransferLength + 0x1FF) / 0x200)); #068 #069 // #070 // Get starting sector number from CDB. #071 // #072
从SRB请求的CDB块计算开始的扇区。 #073 startingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 | #074 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 | #075 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 | #076 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24; #077 #078 DebugPrint((2, #079 "IdeReadWrite: Starting sector is %x,Number of bytes %x/n", #080 startingSector, #081 Srb->DataTransferLength)); #082 #083 // #084 // Set up sector number register. #085 // #086
计算扇区开始位置,并写入到寄存器。 #087 sectorNumber = (UCHAR)((startingSector % deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) + 1); #088 ScsiPortWritePortUchar(&baseIoAddress1->BlockNumber,sectorNumber); #089 #090 // #091 // Set up cylinder low register. #092 // #093
下面开始计算柱面位置。 #094 cylinderLow = (UCHAR)(startingSector / (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack * #095 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads)); #096 ScsiPortWritePortUchar(&baseIoAddress1->CylinderLow,cylinderLow); #097 #098 // #099 // Set up cylinder high register. #100 // #101 #102 cylinderHigh = (UCHAR)((startingSector / (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack * #103 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads)) >> 8); #104 ScsiPortWritePortUchar(&baseIoAddress1->CylinderHigh,cylinderHigh); #105 #106 // #107 // Set up head and drive select register. #108 // #109
计算磁头位置。 #110 drvSelect = (UCHAR)(((startingSector / deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) % #111 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads) |((Srb->TargetId & 0x1) << 4) | 0xA0); #112 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,drvSelect); #113 #114 DebugPrint((2, #115 "IdeReadWrite: Cylinder %x Head %x Sector %x/n", #116 startingSector / #117 (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack * #118 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads), #119 (startingSector / #120 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) % #121 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads, #122 startingSector % #123 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack + 1)); #124 #125 // #126 // Check if write request. #127 // #128
开始发送读或写命令给IDE设备。 #129 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) { #130 #131 // #132 // Send read command. #133 // #134
这里是读取扇区数据,所以发送读取命令给IDE设备。 #135 if (deviceExtension->MaximumBlockXfer[Srb->TargetId]) { #136 ScsiPortWritePortUchar(&baseIoAddress1->Command, #137 IDE_COMMAND_READ_MULTIPLE); #138 #139 } else { #140 ScsiPortWritePortUchar(&baseIoAddress1->Command, #141 IDE_COMMAND_READ); #142 } #143 } else { #144 #145 #146 // #147 // Send write command. #148 // #149
这里是写入数据到IDE设备,所以发送写入命令。 #150 if (deviceExtension->MaximumBlockXfer[Srb->TargetId]) { #151 wordCount = 256 * deviceExtension->MaximumBlockXfer[Srb->TargetId]; #152 #153 if (deviceExtension->WordsLeft < wordCount) { #154 #155 // #156 // Transfer only words requested. #157 // #158 #159 wordCount = deviceExtension->WordsLeft; #160 #161 } #162 ScsiPortWritePortUchar(&baseIoAddress1->Command, #163 IDE_COMMAND_WRITE_MULTIPLE); #164 #165 } else { #166 wordCount = 256; #167 ScsiPortWritePortUchar(&baseIoAddress1->Command, #168 IDE_COMMAND_WRITE); #169 } #170 #171 // #172 // Wait for BSY and DRQ. #173 // #174
等待读取或写入命令完成。 #175 WaitOnBaseBusy(baseIoAddress1,statusByte); #176
如果设备还是忙状态,说明读取或写命令有问题。 #177 if (statusByte & IDE_STATUS_BUSY) { #178 #179 DebugPrint((1, #180 "IdeReadWrite 2: Returning BUSY status %x/n", #181 statusByte)); #182 return SRB_STATUS_BUSY; #183 } #184 #185 for (i = 0; i < 1000; i++) { #186 GetBaseStatus(baseIoAddress1,statusByte); #187 if (statusByte & IDE_STATUS_DRQ) { #188 break; #189 } #190 ScsiPortStallExecution(200); #191 #192 } #193 如果不是状态IDE_STATUS_DRQ,说明处理命令出错了。 #194 if (!(statusByte & IDE_STATUS_DRQ)) { #195 #196 DebugPrint((1, #197 "IdeReadWrite: DRQ never asserted (%x) original status (%x)/n", #198 statusByte, #199 statusByte2)); #200 #201 deviceExtension->WordsLeft = 0; #202 #203 // #204 // Clear interrupt expecting flag. #205 // #206 #207 deviceExtension->ExpectingInterrupt = FALSE; #208 #209 // #210 // Clear current SRB. #211 // #212 #213 deviceExtension->CurrentSrb = NULL; #214 #215 return SRB_STATUS_TIMEOUT; #216 } #217 #218 // #219 // Write next 256 words. #220 // #221
写512个字节到IDE设备。 #222 WriteBuffer(baseIoAddress1, #223 deviceExtension->DataBuffer, #224 wordCount); #225 #226 // #227 // Adjust buffer address and words left count. #228 // #229
计算已经传送的字节数。 #230 deviceExtension->WordsLeft -= wordCount; #231 deviceExtension->DataBuffer += wordCount; #232 #233 } #234 #235 // #236 // Wait for interrupt. #237 // #238 #239 return SRB_STATUS_PENDING; #240 #241} // end IdeReadWrite() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |