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