atapi.c

来自「一个类似windows」· C语言 代码 · 共 2,047 行 · 第 1/5 页

C
2,047
字号
    {
      DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
	     DrvHead & IDE_DH_DRV1 ? 1 : 0,
	     ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
	     SectorCnt,
	     Command);
    }
  else
    {
      DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
	     DrvHead & IDE_DH_DRV1 ? 1 : 0,
	     CylinderHigh,
	     CylinderLow,
	     DrvHead & 0x0f,
	     SectorNum,
	     SectorCnt,
	     Command);
    }

  /*  Setup command parameters  */
  IDEWritePrecomp(CommandPort, PreComp);
  IDEWriteSectorCount(CommandPort, SectorCnt);
  IDEWriteSectorNum(CommandPort, SectorNum);
  IDEWriteCylinderHigh(CommandPort, CylinderHigh);
  IDEWriteCylinderLow(CommandPort, CylinderLow);
  IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);

  /*  Issue the command  */
  IDEWriteCommand(CommandPort, Command);
  ScsiPortStallExecution(50);

  /*  wait for DRQ or error  */
  for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
    {
      Status = IDEReadStatus(CommandPort);
      if (!(Status & IDE_SR_BUSY))
	{
	  if (Status & IDE_SR_ERR)
	    {
	      IDEWriteDriveControl(ControlPort, 0);
	      ScsiPortStallExecution(50);
	      IDEReadStatus(CommandPort);

	      return FALSE;
	    }

	  if (Status & IDE_SR_DRQ)
	    {
	      break;
	    }
	  else
	    {
	      IDEWriteDriveControl(ControlPort, 0);
	      ScsiPortStallExecution(50);
	      IDEReadStatus(CommandPort);

	      return FALSE;
	    }
	}
      ScsiPortStallExecution(10);
    }

  /*  timed out  */
  if (RetryCount >= IDE_MAX_POLL_RETRIES)
    {
      IDEWriteDriveControl(ControlPort, 0);
      ScsiPortStallExecution(50);
      IDEReadStatus(CommandPort);

      return FALSE;
    }

  while (1)
    {
      /*  Read data into buffer  */
      if (Junk == FALSE)
	{
	  IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
	  Buffer += IDE_SECTOR_BUF_SZ;
	}
      else
	{
	  UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
	  IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
	}
      SectorCount++;

      /*  Check for error or more sectors to read  */
      for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
	{
	  Status = IDEReadStatus(CommandPort);
	  if (!(Status & IDE_SR_BUSY))
	    {
	      if (Status & IDE_SR_ERR)
		{
		  IDEWriteDriveControl(ControlPort, 0);
		  ScsiPortStallExecution(50);
		  IDEReadStatus(CommandPort);

		  return FALSE;
		}
	      if (Status & IDE_SR_DRQ)
		{
		  if (SectorCount >= SectorCnt)
		    {
		      DPRINT("Buffer size exceeded!\n");
		      Junk = TRUE;
		    }
		  break;
		}
	      else
		{
		  if (SectorCount > SectorCnt)
		    {
		      DPRINT("Read %lu sectors of junk!\n",
			     SectorCount - SectorCnt);
		    }
		  IDEWriteDriveControl(ControlPort, 0);
		  ScsiPortStallExecution(50);
		  IDEReadStatus(CommandPort);

		  return TRUE;
		}
	    }
	}
    }
}


//  -------------------------------------------  Nondiscardable statics

static ULONG
AtapiSendSmartCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
		      IN PSCSI_REQUEST_BLOCK Srb)
{
  PSRB_IO_CONTROL SrbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;
  SENDCMDINPARAMS InParams;
  PSENDCMDOUTPARAMS OutParams = (PSENDCMDOUTPARAMS)(SrbIoControl + 1);
  ULONG Retries;
  UCHAR Status;

  if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 ||
      SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1)
    {
      return SRB_STATUS_INVALID_REQUEST;
    }
  InParams = *(PSENDCMDINPARAMS)(SrbIoControl + 1);

  DPRINT("%02x %02x %02x %02x %02x %02x %02x %02x\n",
         InParams.irDriveRegs.bFeaturesReg,
         InParams.irDriveRegs.bSectorCountReg,
         InParams.irDriveRegs.bSectorNumberReg,
         InParams.irDriveRegs.bCylLowReg,
         InParams.irDriveRegs.bCylHighReg,
         InParams.irDriveRegs.bDriveHeadReg,
         InParams.irDriveRegs.bCommandReg,
         InParams.irDriveRegs.bReserved);

  if (InParams.bDriveNumber > 1 ||
      (DeviceExtension->DeviceFlags[InParams.bDriveNumber] & (DEVICE_PRESENT|DEVICE_ATAPI)) != DEVICE_PRESENT)
    {
      RtlZeroMemory(&OutParams, sizeof(SENDCMDOUTPARAMS));
      OutParams->DriverStatus.bIDEError = 1;
      return SRB_STATUS_NO_DEVICE;
    }

  DeviceExtension->DataTransferLength = 0;

  switch (SrbIoControl->ControlCode)
    {
      case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
        DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS\n");

        if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE ||
            SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE ||
            InParams.irDriveRegs.bFeaturesReg != READ_ATTRIBUTES ||
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        InParams.irDriveRegs.bSectorCountReg = 0; 
        InParams.irDriveRegs.bSectorNumberReg = 0;
        DeviceExtension->DataTransferLength = READ_ATTRIBUTE_BUFFER_SIZE;
        break;
      
      case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
        DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS\n");

        if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE ||
            SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE ||
            InParams.irDriveRegs.bFeaturesReg != READ_THRESHOLDS ||
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        InParams.irDriveRegs.bSectorCountReg = 0; 
        InParams.irDriveRegs.bSectorNumberReg = 0;
        DeviceExtension->DataTransferLength = READ_THRESHOLD_BUFFER_SIZE;
        break;

      case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
        DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_LOG\n");

        if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE ||
            SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE ||
            InParams.irDriveRegs.bFeaturesReg != SMART_READ_LOG ||
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        DeviceExtension->DataTransferLength = max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE;
        break;

      case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
        DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE\n");

        if (InParams.irDriveRegs.bFeaturesReg != ENABLE_DISABLE_AUTOSAVE ||
            (InParams.irDriveRegs.bSectorCountReg != 0 && InParams.irDriveRegs.bSectorCountReg != 1) || 
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        InParams.irDriveRegs.bSectorNumberReg = 0;
        break;

      case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
        DPRINT("IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES\n");

        if (InParams.irDriveRegs.bFeaturesReg != SAVE_ATTRIBUTE_VALUES ||
            (InParams.irDriveRegs.bSectorCountReg != 0 && InParams.irDriveRegs.bSectorCountReg != 0xf1) || 
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        InParams.irDriveRegs.bSectorNumberReg = 0;
        break;

      case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
        DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");

        if (InParams.irDriveRegs.bFeaturesReg != EXECUTE_OFFLINE_DIAGS ||
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        InParams.irDriveRegs.bSectorCountReg = 0; 
        break;

      case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
        DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_SMART\n");

        if (InParams.irDriveRegs.bFeaturesReg != ENABLE_SMART ||
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        InParams.irDriveRegs.bSectorCountReg = 0; 
        InParams.irDriveRegs.bSectorNumberReg = 0;
        break;

      case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
        DPRINT("IOCTL_SCSI_MINIPORT_DISABLE_SMART\n");

        if (InParams.irDriveRegs.bFeaturesReg != DISABLE_SMART ||
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        InParams.irDriveRegs.bSectorCountReg = 0; 
        InParams.irDriveRegs.bSectorNumberReg = 0;
        break;

      case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
        DPRINT("IOCTL_SCSI_MINIPORT_RETURN_STATUS\n");

        if (InParams.irDriveRegs.bFeaturesReg != RETURN_SMART_STATUS ||
            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
            InParams.irDriveRegs.bCommandReg != SMART_CMD)
          {
            return SRB_STATUS_INVALID_REQUEST;            
          }
        InParams.irDriveRegs.bSectorCountReg = 0; 
        InParams.irDriveRegs.bSectorNumberReg = 0;
        break;
    }

  Srb->TargetId = InParams.bDriveNumber;
  
  /* Set pointer to data buffer. */
  DeviceExtension->DataBuffer = (PUCHAR)OutParams->bBuffer;

  DeviceExtension->CurrentSrb = Srb;

  /*  wait for BUSY to clear  */
  for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
    {
      Status = IDEReadStatus(DeviceExtension->CommandPortBase);
      if (!(Status & IDE_SR_BUSY))
        {
          break;
        }
      ScsiPortStallExecution(10);
    }
  if (Retries >= IDE_MAX_BUSY_RETRIES)
    {
      DPRINT ("Drive is BUSY for too long\n");
      return(SRB_STATUS_BUSY);
    }

  /*  Select the desired drive  */
  InParams.irDriveRegs.bDriveHeadReg = (InParams.bDriveNumber ? IDE_DH_DRV1 : IDE_DH_DRV0) | IDE_DH_FIXED;
  IDEWriteDriveHead(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bDriveHeadReg);
  ScsiPortStallExecution(2);

  IDEWritePrecomp(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bFeaturesReg);
  IDEWriteSectorCount(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bSectorCountReg);
  IDEWriteSectorNum(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bSectorNumberReg);
  IDEWriteCylinderLow(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bCylLowReg);
  IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bCylHighReg);

  AtapiExecuteCommand(DeviceExtension, InParams.irDriveRegs.bCommandReg, AtapiSmartInterrupt);

  /* Wait for interrupt. */
  return SRB_STATUS_PENDING;

}

static ULONG
AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
		      IN PSCSI_REQUEST_BLOCK Srb)
{
  UCHAR ByteCountHigh;
  UCHAR ByteCountLow;
  ULONG Retries;
  ULONG CdbSize;
  UCHAR Status;

  DPRINT("AtapiSendAtapiCommand() called!\n");

  if (Srb->PathId != 0)
    {
      Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
      return(SRB_STATUS_INVALID_PATH_ID);
    }

  if (Srb->TargetId > 1)
    {
      Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
      return(SRB_STATUS_INVALID_TARGET_ID);
    }

  if (Srb->Lun != 0)
    {
      Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
      return(SRB_STATUS_INVALID_LUN);
    }

  if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
    {
      Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
      return(SRB_STATUS_NO_DEVICE);
    }

  if (Srb->Cdb[0] == SCSIOP_MODE_SENSE)
    {
      Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
      return (SRB_STATUS_INVALID_REQUEST);
    }

  DPRINT("AtapiSendAtapiCommand(): TargetId: %lu\n",
	 Srb->TargetId);

  if (Srb->Cdb[0] == SCSIOP_INQUIRY)
    return(AtapiInquiry(DeviceExtension,
			Srb));

  /* Set pointer to data buffer. */
  DeviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
  DeviceExtension->DataTransferLength = Srb->DataTransferLength;
  DeviceExtension->CurrentSrb = Srb;

  DPRINT("BufferAddress %x, BufferLength %d\n", Srb->DataBuffer, Srb->DataTransferLength);

  /* Wait for BUSY to clear */
  for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
    {
      Status = IDEReadStatus(DeviceExtension->CommandPortBase);
      if (!(Status & IDE_SR_BUSY))
        {
 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?