⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsidev.cpp

📁 使用ASPI包装成的一些通用类
💻 CPP
字号:
////////////////////////////////////////////////////////////
//
// Module SCSIDEV.CPP
//
// ASPI class library
// SCSI device class
//
// Project: A Programmer's Guide to SCSI
//
// Copyright (C) 1997, Brian Sawert
// Portions copyright (C) 1995, Larry Martin
// All rights reserved
//
////////////////////////////////////////////////////////////


#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#include "scb.hpp"
#include "scsidev.hpp"
#include "scsidefs.h"


ScsiDevice::ScsiDevice()
{
   Adapter = 0;
   Unit = 0;
   Lun = 0;
   RealName = NULL;
   Name = NULL;
   Revision = NULL;
   RetryOnScsiBusy = 3*1000L;          // milliseconds
   RetryOnScsiError = 2*1000L;            // milliseconds
   RetryOnUnitAttention = 1*1000L;        // milliseconds
   RetryOnTargetNotReady = 0L;            // milliseconds
   RetryOnTargetBusy = 30*1000L;       // milliseconds
   RetryOnTargetBecomingReady = 30*1000L; // milliseconds
}


ScsiDevice::~ScsiDevice()
{
   if (RealName)
      free(RealName);

   if (Name)
      free(Name);

   if (Revision)
      free(Revision);
}

int ScsiDevice::SetName(char *s)
{
   if (Name)
      free(Name);

   Name = strdup(s);

   return Name ? 1 : 0;
}

ScbError ScsiDevice::Init(unsigned adapter, unsigned unit, unsigned lun )
{
   ScbError err;
   ScsiCmdBlock scb;
   SCSI_Cdb_Inquiry_t cdb;
   SCSI_InquiryData_t inq;

   Adapter = adapter;
   Unit = unit;
   Lun = lun;

   scb.Init(SC_EXEC_SCSI_CMD,Adapter,Unit,Lun);

   memset(&cdb,0,sizeof(cdb));
   cdb.CommandCode = SCSI_Cmd_Inquiry;
   cdb.Lun = Lun;
   cdb.Evpd = 0;
   cdb.PageCode = 0;
   cdb.AllocationLength = sizeof(inq);
   scb.SetCdb(&cdb,6);

   memset(&inq,0,sizeof(inq));
   scb.SetDataBuffer(&inq,sizeof(inq));

   {
   long tmp = RetryOnScsiError;
   err = ExecuteScb(scb,3000L);
   RetryOnScsiError = tmp;
   }

   if (!err)
      {
      Type = inq.DeviceType;
      if (RealName)
         free(RealName);
      RealName = (char *) malloc(sizeof(inq.VendorId)+sizeof(inq.ProductId)+2);
      if (RealName)
         {
         char *s = RealName;
         int i;
         for (i=0; i<sizeof(inq.VendorId); i++)
            *s++ = inq.VendorId[i];
         // Trim trailing spaces
         while (--s > RealName)
            {
            if (!(isascii(*s) && isspace(*s)))
               break;
            }
         s++;
         *s++ = ' ';
         for (i=0; i<sizeof(inq.ProductId); i++)
            *s++ = inq.ProductId[i];
         *s = '\0';
         // Trim trailing spaces
         while (--s > RealName)
            {
            if (isascii(*s) && isspace(*s))
               *s = '\0';
            else
               break;
            }
         if (Name == NULL)
            SetName(RealName);
         }

      // Save revision string
      if (Revision)
         free(Revision);
      Revision = (char *) malloc(sizeof(inq.ProductRevisionLevel+1));
      if (Revision)
         {
         char *s = Revision;
         int i;
         for (i=0; i<sizeof(inq.ProductRevisionLevel); i++)
            *s++ = inq.ProductRevisionLevel[i];
         *s = '\0';

         // Trim trailing spaces
         while (--s > Revision)
            {
            if (isascii(*s) && isspace(*s))
               *s = '\0';
            else
               break;
            }
         }

      // save other properties
         AnsiVersion = inq.AnsiVersion;
         bRemovable = inq.RemovableMedia;
         bWide32 = inq.WideBus32Support;
         bWide16 = inq.WideBus16Support;
         bSync = inq.SynchronousTransferSupport;
         bLinked = inq.LinkedCommandSupport;
         bQueue = inq.CommandQueueSupport;
         bSoftReset = inq.SoftResetSupport;
      }
   else
      {
      Type = 0x1F;
      }

   return err;
}

ScbError ScsiDevice::ExecuteScb( ScsiCmdBlock &scb, long timeout )
{
   ScbError err;
   unsigned tries = 0;
   long start_time = 0;
   int retry;
   int scsi_error;
   int scsi_busy;
   int target_busy;
   int target_becoming_ready;
   int target_not_ready;
   int target_unit_attention;

   do
      {
      retry = 0;
      scsi_error = 0;
      scsi_busy = 0;
      target_busy = 0;
      target_becoming_ready = 0;
      target_not_ready = 0;
      target_unit_attention = 0;

      err = scb.Execute(timeout);

      switch (err)
         {
         case Err_None:
            return err;

         case Err_Busy:
            scsi_busy = 1;
            if (RetryOnScsiBusy)
               retry = 1;
            break;

         case Err_TargetBusy:
         case Err_TargetQueueFull:
            target_busy = 1;
            if (RetryOnTargetBusy)
               retry = 1;
            break;

         case Err_SelectionTimeout:
         case Err_UnexpectedBusFree:
         case Err_TargetPhase:
         case Err_BusReset:
         case Err_ParityError:
            scsi_error = 1;
            if (RetryOnScsiError)
               retry = 1;
            break;

         case Err_CheckCondition:
            {
            SCSI_SenseData_t sense;
            scb.GetSense(&sense,sizeof(sense));
            if (sense.ErrorCode == 0x70)
               {
               switch (sense.SenseKey)
                  {
                  case SCSI_Skey_RecoveredError:
                     return Err_None;
                     break;

                  case SCSI_Skey_NotReady:
                     switch ( (sense.Asc << 8) | sense.Asq )
                        {
                        case 0x0401:   // coming ready?
                           target_becoming_ready = 1;
                           if (RetryOnTargetBecomingReady)
                              retry = 1;
                           break;
                        default:
                           target_not_ready = 1;
                           if (RetryOnTargetNotReady)
                              retry = 1;
                        }
                     break;

                  case SCSI_Skey_UnitAttention:
                     target_unit_attention = 1;
                     if (RetryOnUnitAttention)
                        retry = 1;
                     break;

                  default:
                     return err;
                  }
               }
            }
            break;

         default:
            return err;
         }

      if (retry)
         {
         long elapsed_time;

         if (start_time == 0)
            {
            start_time = time(NULL);
            elapsed_time = 0;
            }
         else
            elapsed_time = time(NULL) - start_time;

         if (scsi_busy)
            {
            if (elapsed_time > (RetryOnScsiBusy/1000 + 1) )
               return err;
            }
         else if (scsi_error)
            {
            if (elapsed_time > (RetryOnScsiError/1000 + 1) )
               return err;
            }
         else if (target_busy)
            {
            if (elapsed_time > (RetryOnTargetBusy/1000 + 1) )
               return err;
            Sleep(1000L);
            }
         else if (target_becoming_ready)
            {
            if (elapsed_time > (RetryOnTargetBecomingReady/1000 + 1) )
               return err;
            Sleep(1000L);
            }
         else if (target_unit_attention)
            {
            if (elapsed_time > (RetryOnUnitAttention/1000 + 1) )
               return err;
            }
         else if (target_not_ready)
            {
            if (elapsed_time > (RetryOnTargetNotReady/1000 + 1) )
               return err;
            Sleep(1000L);
            }
         else
            return err;
         }

      } while (retry);


   return err;
}


⌨️ 快捷键说明

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