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>

你可能感兴趣的:(reactos操作系统实现(110))