AtapiInterrupt函数是实现ATAPI的中断功能,主要根据SRB来判断是读取数据还是写入数据,然后对IDE设备读取或写入数据,还需要处理很多出错的情况。具体实现代码如下:

#001  BOOLEAN

#002  NTAPI

#003  AtapiInterrupt(

#004      IN PVOID HwDeviceExtension

#005      )

#006

#007  /*++

#008

#009  Routine Description:

#010

#011      This is the interrupt service routine for ATAPI IDE miniport driver.

#012

#013  Arguments:

#014

#015      HwDeviceExtension - HBA miniport driver's adapter data storage

#016

#017  Return Value:

#018

#019      TRUE if expecting an interrupt.

#020

#021  --*/

#022

#023  {

获取IDE的扩展对象结构。

#024      PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;

获取当前SRB数据。

#025      PSCSI_REQUEST_BLOCK srb              = deviceExtension->CurrentSrb;

#026      PATAPI_REGISTERS_1 baseIoAddress1;

#027      PATAPI_REGISTERS_2 baseIoAddress2;

每次读取256个双字节,也就是512个字节。

#028      ULONG wordCount = 0, wordsThisInterrupt = 256;

#029      ULONG status;

#030      ULONG i;

#031      UCHAR statusByte,interruptReason;

#032      BOOLEAN atapiDev = FALSE;

#033

获取IDE的基地址。

#034      if (srb) {

如果有SRB,说明直接从SRB里读取基地址就行了。

#035          baseIoAddress1 =    (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[srb->TargetId >> 1];

#036          baseIoAddress2 =    (PATAPI_REGISTERS_2)deviceExtension->BaseIoAddress2[srb->TargetId >> 1];

#037      } else {

否则就需要PPC的情况,或者使用一个默认的基地址。

#038          DebugPrint((2,

#039                      "AtapiInterrupt: CurrentSrb is NULL/n"));

#040          //

#041          // We can only support one ATAPI IDE master on Carolina, so find

#042          // the base address that is non NULL and clear its interrupt before

#043          // returning.

#044          //

#045

#046  #ifdef _PPC_

#047

#048          if ((PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[0] != NULL) {

#049             baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[0];

#050          } else {

#051             baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[1];

#052          }

#053

#054          GetBaseStatus(baseIoAddress1, statusByte);

#055  #else

#056

使用一个默认的基地址

#057          if (deviceExtension->InterruptMode == LevelSensitive) {

#058              if (deviceExtension->BaseIoAddress1[0] != NULL) {

#059                 baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[0];

#060                 GetBaseStatus(baseIoAddress1, statusByte);

#061              }

#062              if (deviceExtension->BaseIoAddress1[1] != NULL) {

#063                 baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[1];

#064                 GetBaseStatus(baseIoAddress1, statusByte);

#065              }

#066          }

#067  #endif

如果没有基地址,这个驱动程序不能访问IDE控制器。

#068          return FALSE;

#069      }

#070

如果驱动程序不能接收中断,就直接返回去。

#071      if (!(deviceExtension->ExpectingInterrupt)) {

#072

#073          DebugPrint((3,

#074                      "AtapiInterrupt: Unexpected interrupt./n"));

#075          return FALSE;

#076      }

#077

#078      //

#079      // Clear interrupt by reading status.

#080      //

#081

读取当前状态。

#082      GetBaseStatus(baseIoAddress1, statusByte);

#083

#084      DebugPrint((3,

#085                  "AtapiInterrupt: Entered with status (%x)/n",

#086                  statusByte));

#087

#088

如果IDE的状态为忙状态。

#089      if (statusByte & IDE_STATUS_BUSY) {

如果设备需要采用轮询的方式,就直接返回。

#090          if (deviceExtension->DriverMustPoll) {

#091

#092              //

#093              // Crashdump is polling and we got caught with busy asserted.

#094              // Just go away, and we will be polled again shortly.

#095              //

#096

#097              DebugPrint((3,

#098                          "AtapiInterrupt: Hit BUSY while polling during crashdump./n"));

#099

#100              return TRUE;

#101          }

#102

#103          //

#104          // Ensure BUSY is non-asserted.

#105          //

#106

如果查询10次,还是忙状态,说明IDE还是在忙,没有办法响应,调用函数ScsiPortNotification来设置回调函数。

#107          for (i = 0; i < 10; i++) {

#108

#109              GetBaseStatus(baseIoAddress1, statusByte);

#110              if (!(statusByte & IDE_STATUS_BUSY)) {

#111                  break;

#112              }

#113              ScsiPortStallExecution(5000);

#114          }

#115

#116          if (i == 10) {

#117

#118              DebugPrint((2,

#119                          "AtapiInterrupt: BUSY on entry. Status %x, Base IO %x/n",

#120                          statusByte,

#121                          baseIoAddress1));

#122

#123              ScsiPortNotification(RequestTimerCall,

#124                                   HwDeviceExtension,

#125                                   AtapiCallBack,

#126                                   500);

#127              return TRUE;

#128          }

#129      }

#130

#131

#132      //

#133      // Check for error conditions.

#134      //

#135

如果当前IDE设备的状态为出错,就设置这个SRB请求完成,并且是出错返回。

#136      if (statusByte & IDE_STATUS_ERROR) {

#137

#138          if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {

#139

#140              //

#141              // Fail this request.

#142              //

#143

#144              status = SRB_STATUS_ERROR;

#145              goto CompleteRequest;

#146          }

#147      }

#148

#149      //

#150      // check reason for this interrupt.

#151      //

#152

如果没有出错,也没有忙状态,判断这个中断的原因是什么。

#153      if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {

如果ATAPI设备中断,就读取中断的原因,并设置传送的字节数为512个字节。

#154

#155          interruptReason = (ScsiPortReadPortUchar(&baseIoAddress1->InterruptReason) & 0x3);

#156          atapiDev = TRUE;

#157          wordsThisInterrupt = 256;

#158

#159      } else {

#160

如果是DRQ的方式传送,就进入下面处理。

#161          if (statusByte & IDE_STATUS_DRQ) {

#162

多块传送数据。

#163              if (deviceExtension->MaximumBlockXfer[srb->TargetId]) {

#164                  wordsThisInterrupt = 256 * deviceExtension->MaximumBlockXfer[srb->TargetId];

#165

#166              }

#167

读取数据进来。

#168              if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {

#169

#170                  interruptReason =  0x2;

#171

传送数据出去。

#172              } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {

#173                  interruptReason = 0x0;

#174

#175              } else {

错误请求中断。

#176                  status = SRB_STATUS_ERROR;

#177                  goto CompleteRequest;

#178              }

#179

#180          } else if (statusByte & IDE_STATUS_BUSY) {

#181

#182              return FALSE;

#183

#184          } else {

#185

如果需要补充写字节,就进入下面处理。

#186              if (deviceExtension->WordsLeft) {

#187

#188                  ULONG k;

#189

#190                  //

#191                  // Funky behaviour seen with PCI IDE (not all, just one).

#192                  // The ISR hits with DRQ low, but comes up later.

#193                  //

#194

#195                  for (k = 0; k < 5000; k++) {

#196                      GetStatus(baseIoAddress2,statusByte);

#197                      if (!(statusByte & IDE_STATUS_DRQ)) {

#198                          ScsiPortStallExecution(100);

#199                      } else {

#200                          break;

#201                      }

#202                  }

#203

#204                  if (k == 5000) {

#205

#206                      //

#207                      // reset the controller.

#208                      //

#209

#210                      DebugPrint((1,

#211                                  "AtapiInterrupt: Resetting due to DRQ not up. Status %x, Base IO %x/n",

#212                                  statusByte,

#213                                  baseIoAddress1));

#214

#215                      AtapiResetController(HwDeviceExtension,srb->PathId);

#216                      return TRUE;

#217                  } else {

#218

#219                      interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x2 : 0x0;

#220                  }

#221

#222              } else {

#223

下面获取媒介的状态。

#224                  //

#225                  // Command complete - verify, write, or the SMART enable/disable.

#226                  //

#227                  // Also get_media_status

#228

#229                  interruptReason = 0x3;

#230              }

#231          }

#232      }

#233

根据中断原因进行处理。

#234      if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {

#235

中断原因是写数据到IDE设备。

#236          //

#237          // Write the packet.

#238          //

#239

#240          DebugPrint((2,

#241                      "AtapiInterrupt: Writing Atapi packet./n"));

#242

#243          //

#244          // Send CDB to device.

#245          //

#246

把CDB数据发送给设备。这里的WriteBuffer,其实是调用函数ScsiPortWritePortBufferUshort,它的作用就是把缓冲区里的数据发送到HBA总线上。

#247          WriteBuffer(baseIoAddress1,

#248                      (PUSHORT)srb->Cdb,

#249                      6);

#250

#251          return TRUE;

#252

#253      } else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) {

#254

#255          //

#256          // Write the data.

#257          //

#258

确认是否ATAPI设备。

#259          if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {

#260

#261              //

#262              // Pick up bytes to transfer and convert to words.

#263              //

#264

从ATAPI设备里读取要传送的字节数,把字节转换为字的个数。

#265              wordCount =

#266                  ScsiPortReadPortUchar(&baseIoAddress1->ByteCountLow);

#267

#268              wordCount |=

#269                  ScsiPortReadPortUchar(&baseIoAddress1->ByteCountHigh) << 8;

#270

#271              //

#272              // Covert bytes to words.

#273              //

#274

#275              wordCount >>= 1;

#276

#277              if (wordCount != deviceExtension->WordsLeft) {

#278                  DebugPrint((3,

#279                             "AtapiInterrupt: %d words requested; %d words xferred/n",

#280                             deviceExtension->WordsLeft,

#281                             wordCount));

#282              }

#283

如果要传送的字个数大于剩余的个数,那么就只传送剩余的个数。

#284              //

#285              // Verify this makes sense.

#286              //

#287

#288              if (wordCount > deviceExtension->WordsLeft) {

#289                  wordCount = deviceExtension->WordsLeft;

#290              }

#291

#292          } else {

#293

#294              //

#295              // IDE path. Check if words left is at least 256.

#296              //

#297

判断是否剩余字个数小于256个字,如果是小于,就只传送剩余个数,否则就传送256个字。

#298              if (deviceExtension->WordsLeft < wordsThisInterrupt) {

#299

#300                 //

#301                 // Transfer only words requested.

#302                 //

#303

#304                 wordCount = deviceExtension->WordsLeft;

#305

#306              } else {

#307

#308                 //

#309                 // Transfer next block.

#310                 //

#311

#312                 wordCount = wordsThisInterrupt;

#313              }

#314          }

#315

#316          //

#317          // Ensure that this is a write command.

#318          //

#319

检查它是写的命令。

#320          if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {

#321

#322             DebugPrint((3,

#323                        "AtapiInterrupt: Write interrupt/n"));

#324

等到IDE设备不忙。

#325             WaitOnBusy(baseIoAddress2,statusByte);

#326

判断是否写到第三个基地址。

#327             if (atapiDev || !deviceExtension->DWordIO) {

#328

#329                 WriteBuffer(baseIoAddress1,

#330                             deviceExtension->DataBuffer,

#331                             wordCount);

#332             } else {

#333

#334                 PIDE_REGISTERS_3 address3 = (PIDE_REGISTERS_3)baseIoAddress1;

#335

#336                 WriteBuffer2(address3,

#337                             (PULONG)(deviceExtension->DataBuffer),

#338                             wordCount / 2);

#339             }

#340          } else {

#341

如果不是写的命令,就提示出错返回。

#342              DebugPrint((1,

#343                          "AtapiInterrupt: Int reason %x, but srb is for a write %x./n",

#344                          interruptReason,

#345                          srb));

#346

#347              //

#348              // Fail this request.

#349              //

#350

#351              status = SRB_STATUS_ERROR;

#352              goto CompleteRequest;

#353          }

#354

#355

#356          //

#357          // Advance data buffer pointer and bytes left.

#358          //

#359

调整已经传送的缓冲区字个数,以便下一次传送。

#360          deviceExtension->DataBuffer += wordCount;

#361          deviceExtension->WordsLeft -= wordCount;

#362

#363          return TRUE;

#364

#365      } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) {

#366

#367

这是读取数据命令。

#368          if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {

#369

#370              //

#371              // Pick up bytes to transfer and convert to words.

#372              //

#373

读取IDE设备要传送的字节数,并转换为字的个数。

#374              wordCount =

#375                  ScsiPortReadPortUchar(&baseIoAddress1->ByteCountLow);

#376

#377              wordCount |=

#378                  ScsiPortReadPortUchar(&baseIoAddress1->ByteCountHigh) << 8;

#379

#380              //

#381              // Covert bytes to words.

#382              //

#383

#384              wordCount >>= 1;

#385

请求的个数不等于IDE设备要传送的字节数,就提示。

#386              if (wordCount != deviceExtension->WordsLeft) {

#387                  DebugPrint((3,

#388                             "AtapiInterrupt: %d words requested; %d words xferred/n",

#389                             deviceExtension->WordsLeft,

#390                             wordCount));

#391              }

#392

#393              //

#394              // Verify this makes sense.

#395              //

#396

如果取得最小的值来传送。

#397              if (wordCount > deviceExtension->WordsLeft) {

#398                  wordCount = deviceExtension->WordsLeft;

#399              }

#400

#401          } else {

#402

#403              //

#404              // Check if words left is at least 256.

#405              //

#406

如果只是传送剩余的字节,就设置传送剩余字节,否则就是传送512个字节。

#407              if (deviceExtension->WordsLeft < wordsThisInterrupt) {

#408

#409                 //

#410                 // Transfer only words requested.

#411                 //

#412

#413                 wordCount = deviceExtension->WordsLeft;

#414

#415              } else {

#416

#417                 //

#418                 // Transfer next block.

#419                 //

#420

#421                 wordCount = wordsThisInterrupt;

#422              }

#423          }

#424

#425          //

#426          // Ensure that this is a read command.

#427          //

#428

检查这个命令是读取的命令。

#429          if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {

#430

#431             DebugPrint((3,

#432                        "AtapiInterrupt: Read interrupt/n"));

#433

等待IDE设备空闲。

#434             WaitOnBusy(baseIoAddress2,statusByte);

#435

读取数据到缓冲区。

#436             if (atapiDev || !deviceExtension->DWordIO) {

#437                 ReadBuffer(baseIoAddress1,

#438                           deviceExtension->DataBuffer,

#439                           wordCount);

#440

#441             } else {

使用4字节的方式读取。

#442                 PIDE_REGISTERS_3 address3 = (PIDE_REGISTERS_3)baseIoAddress1;

#443

#444                 ReadBuffer2(address3,

#445                            (PULONG)(deviceExtension->DataBuffer),

#446                            wordCount / 2);

#447             }

#448          } else {

#449

处理这个IDE设备请示失败。

#450              DebugPrint((1,

#451                          "AtapiInterrupt: Int reason %x, but srb is for a read %x./n",

#452                          interruptReason,

#453                          srb));

#454

#455              //

#456              // Fail this request.

#457              //

#458

#459              status = SRB_STATUS_ERROR;

#460              goto CompleteRequest;

#461          }

#462

#463          //

#464          // Translate ATAPI data back to SCSI data if needed

#465          //

#466

#467          if (srb->Cdb[0] == ATAPI_MODE_SENSE &&

#468              deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {

#469

#470              //

#471              //convert and adjust the wordCount

#472              //

#473

#474              wordCount -= Atapi2Scsi(srb, (char *)deviceExtension->DataBuffer,

#475                                       wordCount << 1);

#476          }

#477          //

#478          // Advance data buffer pointer and bytes left.

#479          //

#480

调整已经传送的字节。

#481          deviceExtension->DataBuffer += wordCount;

#482          deviceExtension->WordsLeft -= wordCount;

#483

#484          //

#485          // Check for read command complete.

#486          //

#487

检查是否读取完成。

#488          if (deviceExtension->WordsLeft == 0) {

#489

#490              if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {

#491

#492                  //

#493                  // Work around to make many atapi devices return correct sector size

#494                  // of 2048. Also certain devices will have sector count == 0x00, check

#495                  // for that also.

#496                  //

#497

#498                  if ((srb->Cdb[0] == 0x25) &&

#499                      ((deviceExtension->IdentifyData[srb->TargetId].GeneralConfiguration >> 8) & 0x1f) == 0x05) {

#500

#501                      deviceExtension->DataBuffer -= wordCount;

#502                      if (deviceExtension->DataBuffer[0] == 0x00) {

#503

#504                          *((ULONG *) &(deviceExtension->DataBuffer[0])) = 0xFFFFFF7F;

#505

#506                      }

#507

#508                      *((ULONG *) &(deviceExtension->DataBuffer[2])) = 0x00080000;

#509                      deviceExtension->DataBuffer += wordCount;

#510                  }

#511              } else {

#512

#513                  //

#514                  // Completion for IDE drives.

#515                  //

#516

到这里已经读取数据完成。

#517

#518                  if (deviceExtension->WordsLeft) {

#519

#520                      status = SRB_STATUS_DATA_OVERRUN;

#521

#522                  } else {

#523

#524                      status = SRB_STATUS_SUCCESS;

#525

#526                  }

#527

#528                  goto CompleteRequest;

#529

#530              }

#531          }

#532

#533          return TRUE;

#534

#535      } else if (interruptReason == 0x3  && !(statusByte & IDE_STATUS_DRQ)) {

#536

#537          //

#538          // Command complete.

#539          //

#540

否则是写数据完成。

#541          if (deviceExtension->WordsLeft) {

#542

#543              status = SRB_STATUS_DATA_OVERRUN;

#544

#545          } else {

#546

#547              status = SRB_STATUS_SUCCESS;

#548

#549          }

#550

#551  CompleteRequest:

#552

#553          //

#554          // Check and see if we are processing our secret (mechanism status/request sense) srb

#555          //

#556          if (deviceExtension->OriginalSrb) {

#557

#558              ULONG srbStatus;

#559

#560              if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {

#561

#562                  if (status == SRB_STATUS_SUCCESS) {

#563                      // Bingo!!

#564                      AtapiHwInitializeChanger (HwDeviceExtension,

#565                                                srb->TargetId,

#566                                                (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);

#567

#568                      // Get ready to issue the original srb

#569                      srb = deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;

#570                      deviceExtension->OriginalSrb = NULL;

#571

#572                  } else {

#573                      // failed!  Get the sense key and maybe try again

#574                      srb = deviceExtension->CurrentSrb = BuildRequestSenseSrb (

#575                                                            HwDeviceExtension,

#576                                                            deviceExtension->OriginalSrb->PathId,

#577                                                            deviceExtension->OriginalSrb->TargetId);

#578                  }

#579

重新发送当前SRB数据包。

#580                  srbStatus = AtapiSendCommand(HwDeviceExtension, deviceExtension->CurrentSrb);

#581                  if (srbStatus == SRB_STATUS_PENDING) {

#582                      return TRUE;

#583                  }

#584

#585              } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)

#586

#587                  PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;

#588

#589                  if (status == SRB_STATUS_DATA_OVERRUN) {

#590                      // Check to see if we at least get mininum number of bytes

#591                      if ((srb->DataTransferLength - deviceExtension->WordsLeft) >

#592                          (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) {

#593                          status = SRB_STATUS_SUCCESS;

#594                      }

#595                  }

#596

#597                  if (status == SRB_STATUS_SUCCESS) {

#598                      if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&

#599                          deviceExtension->MechStatusRetryCount) {

#600

#601                          // The sense key doesn't say the last request is illegal, so try again

#602                          deviceExtension->MechStatusRetryCount--;

#603                          srb = deviceExtension->CurrentSrb = BuildMechanismStatusSrb (

#604                                                                HwDeviceExtension,

#605                                                                deviceExtension->OriginalSrb->PathId,

#606                                                                deviceExtension->OriginalSrb->TargetId);

#607                      } else {

#608

#609                          // last request was illegal.  No point trying again

#610

#611                          AtapiHwInitializeChanger (HwDeviceExtension,

#612                                                    srb->TargetId,

#613                                                    (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);

#614

#615                          // Get ready to issue the original srb

#616                          srb = deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;

#617                          deviceExtension->OriginalSrb = NULL;

#618                      }

#619

#620                      srbStatus = AtapiSendCommand(HwDeviceExtension, deviceExtension->CurrentSrb);

#621                      if (srbStatus == SRB_STATUS_PENDING) {

#622                          return TRUE;

#623                      }

#624                  }

#625              }

#626

#627              // If we get here, it means AtapiSendCommand() has failed

#628              // Can't recover.  Pretend the original srb has failed and complete it.

#629

运行到这里,已经说明AtapiSendCommand函数发送失败。

#630              if (deviceExtension->OriginalSrb) {

#631                  AtapiHwInitializeChanger (HwDeviceExtension,

#632                                            srb->TargetId,

#633                                            (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);

#634                  srb = deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;

#635                  deviceExtension->OriginalSrb = NULL;

#636              }

#637

#638              // fake an error and read no data

#639              status = SRB_STATUS_ERROR;

#640              srb->ScsiStatus = 0;

#641              deviceExtension->DataBuffer = srb->DataBuffer;

#642              deviceExtension->WordsLeft = srb->DataTransferLength;

#643              deviceExtension->RDP = FALSE;

#644

#645          } else if (status == SRB_STATUS_ERROR) {

#646

#647              //

#648              // Map error to specific SRB status and handle request sense.

#649              //

#650

SRB数据包的状态出错。

#651              status = MapError(deviceExtension,

#652                                srb);

#653

#654              deviceExtension->RDP = FALSE;

#655

#656          } else {

#657

#658              //

#659              // Wait for busy to drop.

#660              //

#661

忙等IDE设备,并且复位IDE设备。

#662              for (i = 0; i < 30; i++) {

#663                  GetStatus(baseIoAddress2,statusByte);

#664                  if (!(statusByte & IDE_STATUS_BUSY)) {

#665                      break;

#666                  }

#667                  ScsiPortStallExecution(500);

#668              }

#669

#670              if (i == 30) {

#671

#672                  //

#673                  // reset the controller.

#674                  //

#675

#676                  DebugPrint((1,

#677                              "AtapiInterrupt: Resetting due to BSY still up - %x. Base Io %x/n",

#678                              statusByte,

#679                              baseIoAddress1));

#680                  AtapiResetController(HwDeviceExtension,srb->PathId);

#681                  return TRUE;

#682              }

#683

#684              //

#685              // Check to see if DRQ is still up.

#686              //

#687

如果IDE设备还是DRQ状态,就等一会,直到不是这个状态。

#688              if (statusByte & IDE_STATUS_DRQ) {

#689

#690                  for (i = 0; i < 500; i++) {

#691                      GetStatus(baseIoAddress2,statusByte);

#692                      if (!(statusByte & IDE_STATUS_DRQ)) {

#693                          break;

#694                      }

#695                      ScsiPortStallExecution(100);

#696

#697                  }

#698

#699                  if (i == 500) {

#700

#701                      //

#702                      // reset the controller.

#703                      //

#704

#705                      DebugPrint((1,

#706                                  "AtapiInterrupt: Resetting due to DRQ still up - %x/n",

#707                                  statusByte));

#708                      AtapiResetController(HwDeviceExtension,srb->PathId);

#709                      return TRUE;

#710                  }

#711

#712              }

#713          }

#714

#715

#716          //

#717          // Clear interrupt expecting flag.

#718          //

#719

清除中断标志。

#720          deviceExtension->ExpectingInterrupt = FALSE;

#721

#722          //

#723          // Sanity check that there is a current request.

#724          //

#725

检查当前请求包。

#726          if (srb != NULL) {

#727

#728              //

#729              // Set status in SRB.

#730              //

#731

#732              srb->SrbStatus = (UCHAR)status;

#733

#734              //

#735              // Check for underflow.

#736              //

#737

#738              if (deviceExtension->WordsLeft) {

#739

#740                  //

#741                  // Subtract out residual words and update if filemark hit,

#742                  // setmark hit , end of data, end of media...

#743                  //

#744

#745                  if (!(deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_TAPE_DEVICE)) {

#746                  if (status == SRB_STATUS_DATA_OVERRUN) {

#747                      srb->DataTransferLength -= deviceExtension->WordsLeft;

#748                  } else {

#749                      srb->DataTransferLength = 0;

#750                  }

#751                  } else {

#752                      srb->DataTransferLength -= deviceExtension->WordsLeft;

#753                  }

#754              }

#755

#756              if (srb->Function != SRB_FUNCTION_IO_CONTROL) {

#757

#758                  //

#759                  // Indicate command complete.

#760                  //

#761

#762                  if (!(deviceExtension->RDP)) {

#763                      ScsiPortNotification(RequestComplete,

#764                                           deviceExtension,

#765                                           srb);

#766

#767                  }

#768              } else {

#769

#770                  PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));

#771                  UCHAR             error = 0;

#772

#773                  if (status != SRB_STATUS_SUCCESS) {

#774                      error = ScsiPortReadPortUchar((PUCHAR)baseIoAddress1 + 1);

#775                  }

#776

#777                  //

#778                  // Build the SMART status block depending upon the completion status.

#779                  //

#780

#781                  cmdOutParameters->cBufferSize = wordCount;

#782                  cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;

#783                  cmdOutParameters->DriverStatus.bIDEError = error;

#784

#785                  //

#786                  // If the sub-command is return smart status, jam the value from cylinder low and high, into the

#787                  // data buffer.

#788                  //

#789

#790                  if (deviceExtension->SmartCommand == RETURN_SMART_STATUS) {

#791                      cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;

#792                      cmdOutParameters->bBuffer[1] = ScsiPortReadPortUchar(&baseIoAddress1->InterruptReason);

#793                      cmdOutParameters->bBuffer[2] = ScsiPortReadPortUchar(&baseIoAddress1->Unused1);

#794                      cmdOutParameters->bBuffer[3] = ScsiPortReadPortUchar(&baseIoAddress1->ByteCountLow);

#795                      cmdOutParameters->bBuffer[4] = ScsiPortReadPortUchar(&baseIoAddress1->ByteCountHigh);

#796                      cmdOutParameters->bBuffer[5] = ScsiPortReadPortUchar(&baseIoAddress1->DriveSelect);

#797                      cmdOutParameters->bBuffer[6] = SMART_CMD;

#798                      cmdOutParameters->cBufferSize = 8;

#799                  }

#800

#801                  //

#802                  // Indicate command complete.

#803                  //

#804

#805                  ScsiPortNotification(RequestComplete,

#806                                       deviceExtension,

#807                                       srb);

#808

#809              }

#810

#811          } else {

#812

#813              DebugPrint((1,

#814                         "AtapiInterrupt: No SRB!/n"));

#815          }

#816

#817          //

#818          // Indicate ready for next request.

#819          //

#820

设置IDE设备可能处理下一个请求包。

#821          if (!(deviceExtension->RDP)) {

#822

#823              //

#824              // Clear current SRB.

#825              //

#826

#827              deviceExtension->CurrentSrb = NULL;

#828

#829              ScsiPortNotification(NextRequest,

#830                                   deviceExtension,

#831                                   NULL);

#832          } else {

#833

#834              ScsiPortNotification(RequestTimerCall,

#835                                   HwDeviceExtension,

#836                                   AtapiCallBack,

#837                                   2000);

#838          }

#839

#840          return TRUE;

#841

#842      } else {

#843

#844          //

#845          // Unexpected int.

#846          //

#847

#848          DebugPrint((3,

#849                      "AtapiInterrupt: Unexpected interrupt. InterruptReason %x. Status %x./n",

#850                      interruptReason,

#851                      statusByte));

#852          return FALSE;

#853      }

#854

#855      return TRUE;

#856

#857  } // end AtapiInterrupt()

转载于:https://www.cnblogs.com/ajuanabc/archive/2009/10/19/2463676.html

reactos操作系统实现(109)相关推荐

  1. reactos操作系统实现 2

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 对于开发 ...

  2. reactos操作系统实现(2)

    对于开发一个操作系统是一个漫长的过程,并不像一个Hello world程序那么快捷,那么明了.因此对开发OS的基本知识,基本技能也需要比较高深一些,特别对一些名词和概念,更需要深入地了解.由于操作系统 ...

  3. reactos操作系统实现(47)

    当光盘变成记录数据以后,就开始使用光盘来分发操作系统了.毕竟光盘有着储存数据量大,成本便宜的优势.下面就来分析Reactos是怎么样通过光盘的格式来引导操作系统的. 现今的计算机BIOS,会在开机时根 ...

  4. reactos操作系统实现 1

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! reac ...

  5. reactos操作系统实现 3

    有人说,reactos不是实时操作系统,不能做嵌入式系统,难道真的不能做嵌入式系统吗?其实不是这样的,嵌入式系统本来就包括有两类系统,一种是要求实时性强,一种是要求实时性弱的.这两种都是嵌入式系统.因 ...

  6. reactos操作系统实现(1)

    reactos是什么操作系统呢?它是一个开源的操作系统,并且是兼容Windows XP的应用程序和驱动程序的操作系统.意思就是说,直接安装一个reactos之后,把第三方的驱动程序安装好后,就可以运行 ...

  7. reactos操作系统实现(3)

    有人说,reactos不是实时操作系统,不能做嵌入式系统,难道真的不能做嵌入式系统吗?其实不是这样的,嵌入式系统本来就包括有两类系统,一种是要求实时性强,一种是要求实时性弱的.这两种都是嵌入式系统.因 ...

  8. reactos操作系统实现(12)

    有了上面的知识,就来分析ReactOS里引导任务是怎么样设置全局描述符表.其工作过程如下图所示: 由于CPU初始化运行后,就当作为一个任务在运行.这里主要设置这个任务的运行保存环境,以便CPU可以交给 ...

  9. reactos操作系统实现(6)

    硬盘引导的流程与相应源码文件名称: 引导序号 引导过程 引导执行代码位数 目标文件名称 1. 主引导代码(Master Boot Record (MBR) code),主要寻找活动分区,然后读入引导扇 ...

  10. reactos操作系统实现(119)

    前介绍了初始化函数ScsiClassInitialize,那么在这个函数里使用下面的语句来查找SCSI的磁盘,如下: if (InitializationData->ClassFindDevic ...

最新文章

  1. Android Studio 编译: Program type already present: XXX 解决方案
  2. wxWidgets:wxMemoryInputStream类用法
  3. POJ 2516 -- Minimum Cost (最小费用最大流, 必须分开建图)
  4. 创建一个追踪摄像机(2)
  5. Ubuntu下的Linux内核的编译及安装
  6. 用开源代码如何建立网站_建立开源社区时要考虑的6件事
  7. java中tcp传图片_Java学习之TCP上传图片
  8. 一:HTTP协议(超详解)
  9. python torchvision_pip install torchvision error:安装版本为0.4.1的torch后继续安装torchvision报错...
  10. Jira迁移及内存调整
  11. 高效维持网络长连接:手把手教你实现 自适应的心跳保活机制
  12. java经典编程练习题_java笔试经典练习题及答案
  13. 揭秘 | Akuna工作体验大揭秘
  14. oracle优质图书,Oracle经典图书之-Optimizing Oracle Performance
  15. “做真实的自己”是个坑
  16. 一张美团外卖的小票看透支付清结算架构!
  17. 【WebService】Caused by: org.apache.cxf.transport.http.HTTPException: HTTP respon ...
  18. Bandizip官网最新下载 中文,绿色版 Bandizip下载
  19. Interlaced Sparse Self-Attention for Semantic Segmentation
  20. 日常上网必备趣味,实用的100个网站

热门文章

  1. 教你炒股票19:学习缠中说禅技术分析理论的关键
  2. 三菱FX系列PLC-编程2
  3. LaTeX安装及周报模板
  4. 解决Anaconda第三方库下载慢
  5. JavaScript — 原生js实现上传图片控件
  6. 2020最新省市区县编码
  7. 地理信息系统(汤国安)重点整理与推导(第三章)
  8. 湖南大学离散数学实验——代码(一)
  9. 关于webstorm更换主题
  10. Python 最好用的8个VS Code扩展