reactos操作系统实现(110)
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> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |