IdeSendSmartCommand函数主要发送IDE的命令。具体实现代码如下:
#001 ULONG
#002 NTAPI
#003 IdeSendSmartCommand(
#004 IN PVOID HwDeviceExtension,
#005 IN PSCSI_REQUEST_BLOCK Srb
#006 )
#007
#008 /*++
#009
#010 Routine Description:
#011
#012 This routine handles SMART enable, disable, read attributes and threshold commands.
#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];
从SRB获取输入参数和输出参数。
#029 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
#030 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
#031 PIDEREGS regs = &cmdInParameters.irDriveRegs;
#032 ULONG i;
#033 UCHAR statusByte,targetId;
#034
#035
检查是否合法的操作。
#036 if (cmdInParameters.irDriveRegs.bCommandReg == SMART_CMD) {
#037
#038 targetId = cmdInParameters.bDriveNumber;
#039
#040 //TODO optimize this check
#041
#042 if ((!(deviceExtension->DeviceFlags[targetId] & DFLAGS_DEVICE_PRESENT)) ||
#043 (deviceExtension->DeviceFlags[targetId] & DFLAGS_ATAPI_DEVICE)) {
#044
#045 return SRB_STATUS_SELECTION_TIMEOUT;
#046 }
#047
获取输出的命令。
#048 deviceExtension->SmartCommand = cmdInParameters.irDriveRegs.bFeaturesReg;
#049
#050 //
#051 // Determine which of the commands to carry out.
#052 //
#053
检查命令是否读取的操作。
#054 if ((cmdInParameters.irDriveRegs.bFeaturesReg == READ_ATTRIBUTES) ||
#055 (cmdInParameters.irDriveRegs.bFeaturesReg == READ_THRESHOLDS)) {
#056
等待IDE设备空闲。
#057 WaitOnBusy(baseIoAddress2,statusByte);
#058
#059 if (statusByte & IDE_STATUS_BUSY) {
#060 DebugPrint((1,
#061 "IdeSendSmartCommand: Returning BUSY status/n"));
#062 return SRB_STATUS_BUSY;
#063 }
#064
#065 //
#066 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
#067 //
#068
清空输出缓冲区。
#069 for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1); i++) {
#070 ((PUCHAR)cmdOutParameters)[i] = 0;
#071 }
#072
#073 //
#074 // Set data buffer pointer and words left.
#075 //
#076
设置输出缓冲区作为接收IDE设备的数据保存区。
#077 deviceExtension->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
#078 deviceExtension->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
#079
#080 //
#081 // Indicate expecting an interrupt.
#082 //
#083
这里设置希望使用中断的方式返回。
#084 deviceExtension->ExpectingInterrupt = TRUE;
#085
把SRB的命令发送给IDE设备。
#086 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,(UCHAR)(((targetId & 0x1) << 4) | 0xA0));
#087 ScsiPortWritePortUchar((PUCHAR)baseIoAddress1 + 1,regs->bFeaturesReg);
#088 ScsiPortWritePortUchar(&baseIoAddress1->BlockCount,regs->bSectorCountReg);
#089 ScsiPortWritePortUchar(&baseIoAddress1->BlockNumber,regs->bSectorNumberReg);
#090 ScsiPortWritePortUchar(&baseIoAddress1->CylinderLow,regs->bCylLowReg);
#091 ScsiPortWritePortUchar(&baseIoAddress1->CylinderHigh,regs->bCylHighReg);
#092 ScsiPortWritePortUchar(&baseIoAddress1->Command,regs->bCommandReg);
#093
#094 //
#095 // Wait for interrupt.
#096 //
#097
进入等待中断读取数据返回。
#098 return SRB_STATUS_PENDING;
#099
#100 } else if ((cmdInParameters.irDriveRegs.bFeaturesReg == ENABLE_SMART) ||
#101 (cmdInParameters.irDriveRegs.bFeaturesReg == DISABLE_SMART) ||
#102 (cmdInParameters.irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS) ||
#103 (cmdInParameters.irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTOSAVE) ||
#104 (cmdInParameters.irDriveRegs.bFeaturesReg == EXECUTE_OFFLINE_DIAGS) ||
#105 (cmdInParameters.irDriveRegs.bFeaturesReg == SAVE_ATTRIBUTE_VALUES)) {
#106
这是设置一些属性,没有数据返回。
#107 WaitOnBusy(baseIoAddress2,statusByte);
#108
#109 if (statusByte & IDE_STATUS_BUSY) {
#110 DebugPrint((1,
#111 "IdeSendSmartCommand: Returning BUSY status/n"));
#112 return SRB_STATUS_BUSY;
#113 }
#114
#115 //
#116 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
#117 //
#118
#119 for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) - 1); i++) {
#120 ((PUCHAR)cmdOutParameters)[i] = 0;
#121 }
#122
#123 //
#124 // Set data buffer pointer and indicate no data transfer.
#125 //
#126
#127 deviceExtension->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
#128 deviceExtension->WordsLeft = 0;
#129
#130 //
#131 // Indicate expecting an interrupt.
#132 //
#133
#134 deviceExtension->ExpectingInterrupt = TRUE;
#135
#136 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,(UCHAR)(((targetId & 0x1) << 4) | 0xA0));
#137 ScsiPortWritePortUchar((PUCHAR)baseIoAddress1 + 1,regs->bFeaturesReg);
#138 ScsiPortWritePortUchar(&baseIoAddress1->BlockCount,regs->bSectorCountReg);
#139 ScsiPortWritePortUchar(&baseIoAddress1->BlockNumber,regs->bSectorNumberReg);
#140 ScsiPortWritePortUchar(&baseIoAddress1->CylinderLow,regs->bCylLowReg);
#141 ScsiPortWritePortUchar(&baseIoAddress1->CylinderHigh,regs->bCylHighReg);
#142 ScsiPortWritePortUchar(&baseIoAddress1->Command,regs->bCommandReg);
#143
#144 //
#145 // Wait for interrupt.
#146 //
#147
#148 return SRB_STATUS_PENDING;
#149 }
#150 }
#151
如果到这里运行,就是非法命令,不能处理。
#152 return SRB_STATUS_INVALID_REQUEST;
#153
#154 } // end IdeSendSmartCommand()