AtapiStartIo函数主要处理同步的IO请求包。具代的实现代码如下:
#001 BOOLEAN
#002 NTAPI
#003 AtapiStartIo(
#004 IN PVOID HwDeviceExtension,
#005 IN PSCSI_REQUEST_BLOCK Srb
#006 )
#007
#008 /*++
#009
#010 Routine Description:
#011
#012 This routine is called from the SCSI port driver synchronized
#013 with the kernel to start an IO request.
#014
#015 Arguments:
#016
#017 HwDeviceExtension - HBA miniport driver's adapter data storage
#018 Srb - IO request packet
#019
#020 Return Value:
#021
#022 TRUE
#023
#024 --*/
#025
#026 {
#027 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
#028 ULONG status;
#029
#030 //
#031 // Determine which function.
#032 //
#033
检查SRB是做什么的功能。
#034 switch (Srb->Function) {
#035
执行SCSI命令。
#036 case SRB_FUNCTION_EXECUTE_SCSI:
#037
#038 //
#039 // Sanity check. Only one request can be outstanding on a
#040 // controller.
#041 //
#042
检查当前SRB是否已经存在,如果存在就是出错返回。
#043 if (deviceExtension->CurrentSrb) {
#044
#045 DebugPrint((1,
#046 "AtapiStartIo: Already have a request!/n"));
#047 Srb->SrbStatus = SRB_STATUS_BUSY;
知道这个请求完成返回。
#048 ScsiPortNotification(RequestComplete,
#049 deviceExtension,
#050 Srb);
#051 return FALSE;
#052 }
#053
#054 //
#055 // Indicate that a request is active on the controller.
#056 //
#057
保存将要发送的SRB。
#058 deviceExtension->CurrentSrb = Srb;
#059
#060 //
#061 // Send command to device.
#062 //
#063
把命令发送到设备。
#064 if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
#065
发送到ATAPI设备。
#066 status = AtapiSendCommand(HwDeviceExtension,
#067 Srb);
#068
#069 } else if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT) {
#070
发送到IDE设备,但不是ATAPI设备。
#071 status = IdeSendCommand(HwDeviceExtension,
#072 Srb);
#073 } else {
#074
否则没有设备可以发送。
#075 status = SRB_STATUS_SELECTION_TIMEOUT;
#076 }
#077
#078 break;
#079
放弃当前SRB输出。
#080 case SRB_FUNCTION_ABORT_COMMAND:
#081
#082 //
#083 // Verify that SRB to abort is still outstanding.
#084 //
#085
#086 if (!deviceExtension->CurrentSrb) {
#087
#088 DebugPrint((1, "AtapiStartIo: SRB to abort already completed/n"));
#089
#090 //
#091 // Complete abort SRB.
#092 //
#093
#094 status = SRB_STATUS_ABORT_FAILED;
#095
#096 break;
#097 }
#098
#099 //
#100 // Abort function indicates that a request timed out.
#101 // Call reset routine. Card will only be reset if
#102 // status indicates something is wrong.
#103 // Fall through to reset code.
#104 //
#105
下面对IDE控制器进行复位操作。
#106 case SRB_FUNCTION_RESET_BUS:
#107
#108 //
#109 // Reset Atapi and SCSI bus.
#110 //
#111
#112 DebugPrint((1, "AtapiStartIo: Reset bus request received/n"));
#113
#114 if (!AtapiResetController(deviceExtension,
#115 Srb->PathId)) {
#116
#117 DebugPrint((1,"AtapiStartIo: Reset bus failed/n"));
#118
#119 //
#120 // Log reset failure.
#121 //
#122
#123 ScsiPortLogError(
#124 HwDeviceExtension,
#125 NULL,
#126 0,
#127 0,
#128 0,
#129 SP_INTERNAL_ADAPTER_ERROR,
#130 5 << 8
#131 );
#132
#133 status = SRB_STATUS_ERROR;
#134
#135 } else {
#136
#137 status = SRB_STATUS_SUCCESS;
#138 }
#139
#140 break;
#141
#142 case SRB_FUNCTION_IO_CONTROL:
#143
如果当前SRB还没有处理,就返回。
#144 if (deviceExtension->CurrentSrb) {
#145
#146 DebugPrint((1,
#147 "AtapiStartIo: Already have a request!/n"));
#148 Srb->SrbStatus = SRB_STATUS_BUSY;
#149 ScsiPortNotification(RequestComplete,
#150 deviceExtension,
#151 Srb);
#152 return FALSE;
#153 }
#154
#155 //
#156 // Indicate that a request is active on the controller.
#157 //
#158
保存SRB为当前SRB。
#159 deviceExtension->CurrentSrb = Srb;
#160
如果SCSIDISK的控制器,就不能处理,这是非法的请求。
#161 if (AtapiStringCmp( (PCHAR)((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,"SCSIDISK",strlen("SCSIDISK"))) {
#162
#163 DebugPrint((1,
#164 "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s/n",
#165 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
#166 "SCSIDISK"));
#167
#168 status = SRB_STATUS_INVALID_REQUEST;
#169 break;
#170 }
#171
根据IO的控制码来决定做什么样的事情。
#172 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
#173
#174 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
#175
设置SCSI的驱动程序的版本。
#176 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
#177 UCHAR deviceNumber;
#178
#179 //
#180 // Version and revision per SMART 1.03
#181 //
#182
#183 versionParameters->bVersion = 1;
#184 versionParameters->bRevision = 1;
#185 versionParameters->bReserved = 0;
#186
#187 //
#188 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
#189 //
#190
设置驱动程序的兼容那些命令。
#191 versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
#192
#193 //
#194 // This is done because of how the IOCTL_SCSI_MINIPORT
#195 // determines 'targetid's'. Disk.sys places the real target id value
#196 // in the DeviceMap field. Once we do some parameter checking, the value passed
#197 // back to the application will be determined.
#198 //
#199
获取设备号。
#200 deviceNumber = versionParameters->bIDEDeviceMap;
#201
如果设备不存在,就返回选择当前的设备出错。
#202 if (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT) ||
#203 (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_ATAPI_DEVICE)) {
#204
#205 status = SRB_STATUS_SELECTION_TIMEOUT;
#206 break;
#207 }
#208
#209 //
#210 // NOTE: This will only set the bit
#211 // corresponding to this drive's target id.
#212 // The bit mask is as follows:
#213 //
#214 // Sec Pri
#215 // S M S M
#216 // 3 2 1 0
#217 //
#218
计算选择的设备号。
#219 if (deviceExtension->NumberChannels == 1) {
#220 if (deviceExtension->PrimaryAddress) {
#221 deviceNumber = 1 << Srb->TargetId;
#222 } else {
#223 deviceNumber = 4 << Srb->TargetId;
#224 }
#225 } else {
#226 deviceNumber = 1 << Srb->TargetId;
#227 }
#228
#229 versionParameters->bIDEDeviceMap = deviceNumber;
#230
#231 status = SRB_STATUS_SUCCESS;
#232 break;
#233 }
#234
#235 case IOCTL_SCSI_MINIPORT_IDENTIFY: {
#236
获取输出参数。
#237 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
获取输入参数。
#238 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
#239 ULONG i;
#240 UCHAR targetId;
#241
#242
如果是命令寄存器,就选择下面的处理。
#243 if (cmdInParameters.irDriveRegs.bCommandReg == ID_CMD) {
#244
#245 //
#246 // Extract the target.
#247 //
#248
获取目标驱动器设备。
#249 targetId = cmdInParameters.bDriveNumber;
#250
如果设备没有,或者设备不是ATAPI设备,就返回出错。
#251 if (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT) ||
#252 (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_ATAPI_DEVICE)) {
#253
#254 status = SRB_STATUS_SELECTION_TIMEOUT;
#255 break;
#256 }
#257
#258 //
#259 // Zero the output buffer
#260 //
#261
清空输出缓冲区。
#262 for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
#263 ((PUCHAR)cmdOutParameters)[i] = 0;
#264 }
#265
#266 //
#267 // Build status block.
#268 //
#269
设置输出参数的大小和设备状态。
#270 cmdOutParameters->cBufferSize = IDENTIFY_BUFFER_SIZE;
#271 cmdOutParameters->DriverStatus.bDriverError = 0;
#272 cmdOutParameters->DriverStatus.bIDEError = 0;
#273
#274 //
#275 // Extract the identify data from the device extension.
#276 //
#277
从设备获取标识数据给输出缓冲区。
#278 ScsiPortMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->IdentifyData[targetId], IDENTIFY_DATA_SIZE);
#279
#280 status = SRB_STATUS_SUCCESS;
#281
#282
#283 } else {
#284 status = SRB_STATUS_INVALID_REQUEST;
#285 }
#286 break;
#287 }
#288
#289 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
#290 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
#291 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
#292 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
#293 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
#294 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
#295 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
#296 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
#297
处理SMART相关的命令。
#298 status = IdeSendSmartCommand(HwDeviceExtension,Srb);
#299 break;
#300
#301 default :
#302
#303 status = SRB_STATUS_INVALID_REQUEST;
#304 break;
#305
#306 }
#307
#308 break;
#309
#310 default:
#311
#312 //
#313 // Indicate unsupported command.
#314 //
#315
#316 status = SRB_STATUS_INVALID_REQUEST;
#317
#318 break;
#319
#320 } // end switch
#321
#322 //
#323 // Check if command complete.
#324 //
#325
检查命令是否完成。
#326 if (status != SRB_STATUS_PENDING) {
#327
如果状态不是阻塞状态,说明命令已经处理完成。
#328 DebugPrint((2,
#329 "AtapiStartIo: Srb %x complete with status %x/n",
#330 Srb,
#331 status));
#332
#333 //
#334 // Clear current SRB.
#335 //
#336
清除当前的SRB。
#337 deviceExtension->CurrentSrb = NULL;
#338
#339 //
#340 // Set status in SRB.
#341 //
#342
设置SRB返回状态。
#343 Srb->SrbStatus = (UCHAR)status;
#344
#345 //
#346 // Indicate command complete.
#347 //
#348
通知这个SRB命令已经完成。
#349 ScsiPortNotification(RequestComplete,
#350 deviceExtension,
#351 Srb);
#352
#353 //
#354 // Indicate ready for next request.
#355 //
#356
准备处理下一个SRB。
#357 ScsiPortNotification(NextRequest,
#358 deviceExtension,
#359 NULL);
#360 }
#361
#362 return TRUE;
#363
#364 } // end AtapiStartIo()
SENDCMDOUTPARAMS结构:
#001 #include <pshpack1.h>
#002 typedef struct _SENDCMDOUTPARAMS {
指明缓冲区里有多少字节数据。
#003 ULONG cBufferSize;
驱动程序状态的结构。
#004 DRIVERSTATUS DriverStatus;
保存从驱动器读取到的字节。
#005 UCHAR bBuffer[1];
#006 } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
#007 #include <poppack.h>
SENDCMDINPARAMS结构:
#001 #include <pshpack1.h>
#002 typedef struct _SENDCMDINPARAMS {
指明缓冲区里有多少字节。
#003 ULONG cBufferSize;
保存IDE寄存器。
#004 IDEREGS irDriveRegs;
驱动器序号。
#005 UCHAR bDriveNumber;
#006 UCHAR bReserved[3];
#007 ULONG dwReserved[4];
保存数据的缓冲区。
#008 UCHAR bBuffer[1];
#009 } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
#010 #include <poppack.h>