ScsiIf-win.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:9k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log$
  21.  */
  22. static char rcsid[] = "$Id$";
  23. #include "config.h"
  24. #include <windows.h>
  25. #include <stdio.h>
  26. #include <fcntl.h>
  27. #include <errno.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include "winaspi.h"
  31. #include "ScsiIf.h"
  32. #include "util.h"
  33. #include "decodeSense.cc"
  34. typedef DWORD (*GETSUPPORTINFO) (void);
  35. typedef DWORD (*GETDLLVERSION)  (void);
  36. typedef DWORD (*SENDCOMMAND)    (char *);
  37. #define BUF_SIZE  (32*1024)
  38. class ScsiIfImpl 
  39. {
  40. public:
  41.   char *dev_;
  42.   
  43.   int maxSendLen_;
  44.   SRB_ExecSCSICmd6    cmd6_;
  45.   SRB_ExecSCSICmd10   cmd10_;
  46.   SRB_ExecSCSICmd12   cmd12_;
  47.   unsigned char senseBuffer_[SENSE_LEN];
  48.   char haid_;
  49.   char lun_;
  50.   char scsi_id_;
  51.   HINSTANCE   hinstlib;
  52.   SENDCOMMAND Sendcommand;
  53. };
  54. ScsiIf::ScsiIf(const char *dev)
  55. {
  56.   char *p, *q;
  57.  
  58.   impl_ = new ScsiIfImpl;
  59.   impl_->dev_ = strdupCC(dev);
  60.   maxDataLen_ = BUF_SIZE;
  61.   impl_->haid_ = 0;
  62.   impl_->lun_ = 0;
  63.   impl_->scsi_id_ = 0;
  64.   if (p = strchr (impl_->dev_, ':'))
  65.   {
  66.      *p = 0;
  67.      impl_->haid_ = atoi (impl_->dev_);
  68.      q = ++p;
  69.      if (p = strchr (q, ':'))
  70.      {
  71.         *p = 0;
  72.         impl_->lun_ = atoi (q);
  73.         q = ++p;
  74.         impl_->scsi_id_ = atoi (q);
  75.      }
  76.   }
  77.   impl_->hinstlib = 0;
  78.   vendor_[0] = 0;
  79.   product_[0] = 0;
  80.   revision_[0] = 0;
  81. }
  82. ScsiIf::~ScsiIf()
  83. {
  84.   delete[] impl_->dev_;
  85.   impl_->dev_ = NULL;
  86.   if (impl_->hinstlib)
  87.      FreeLibrary (impl_->hinstlib);
  88.   delete impl_;
  89. }
  90. // opens and flushes scsi device
  91. // return: 0: OK
  92. //         1: device could not be opened
  93. //         2: inquiry failed
  94. int ScsiIf::init()
  95. {
  96.   impl_->hinstlib = LoadLibrary ("WNASPI32.DLL");
  97.   if (!impl_->hinstlib)
  98.   {
  99.      message (-2, "Can't load WNASPI32.DLL");
  100.      return 1;
  101.   }
  102.   else {
  103.     impl_->Sendcommand = (SENDCOMMAND)GetProcAddress (impl_->hinstlib, "SendASPI32Command");
  104.   }
  105.   if (inquiry() != 0) 
  106.     return 2;
  107.   return 0;
  108. }
  109. // Sets given timeout value in seconds and returns old timeout.
  110. // return: old timeout
  111. int ScsiIf::timeout (int t)
  112. {
  113.   return 0;
  114. }
  115. // sends a scsi command and receives data
  116. // return 0: OK
  117. //        1: scsi command failed (os level, no sense data available)
  118. //        2: scsi command failed (sense data available)
  119. int ScsiIf::sendCmd (const unsigned char *cmd,     int cmdLen, 
  120.      const unsigned char *dataOut, int dataOutLen,
  121.      unsigned char *dataIn,  int dataInLen,
  122.      int showMessage)
  123. {
  124.   int status, i = 10;
  125.   switch (cmdLen)
  126.   {
  127.       case 6: memset (&impl_->cmd6_, 0, sizeof (SRB_ExecSCSICmd6));
  128.               memcpy (impl_->cmd6_.CDBByte, cmd, 6);
  129.               impl_->cmd6_.SRB_Cmd        = SC_EXEC_SCSI_CMD;
  130.               impl_->cmd6_.SRB_HaId       = impl_->haid_;
  131.               impl_->cmd6_.SRB_Target     = impl_->scsi_id_;
  132.               impl_->cmd6_.SRB_Lun        = impl_->lun_;
  133.               impl_->cmd6_.SRB_SenseLen   = SENSE_LEN;
  134.               impl_->cmd6_.SRB_CDBLen     = 6;
  135.               if (dataOut && dataOutLen)
  136.               {
  137.                  impl_->cmd6_.SRB_Flags      = SRBF_WRITE;
  138.                  impl_->cmd6_.SRB_BufPointer = dataOut;
  139.                  impl_->cmd6_.SRB_BufLen     = dataOutLen;
  140.               }
  141.               else
  142.               {
  143.                  impl_->cmd6_.SRB_Flags      = SRBF_READ;
  144.                  impl_->cmd6_.SRB_BufPointer = dataIn;
  145.                  impl_->cmd6_.SRB_BufLen     = dataInLen;
  146.               }
  147.               (impl_->Sendcommand) ((char *) &impl_->cmd6_);
  148.               while (i-- && impl_->cmd6_.SRB_Status != SS_COMP)
  149.               {
  150.                    while (!impl_->cmd6_.SRB_Status)
  151.                         Sleep (10);
  152.               }
  153.       // AM: Try to get sense data
  154.       if (impl_->cmd6_.SRB_Status == SS_ERR &&
  155.   impl_->cmd6_.SRB_TargStat == STATUS_CHKCOND) {
  156. memcpy(impl_->senseBuffer_, impl_->cmd6_.SenseArea, SENSE_LEN);
  157. if (showMessage)
  158.   printError();
  159. return 2;
  160.       }
  161.               if (impl_->cmd6_.SRB_Status != SS_COMP)
  162.                  return (1);
  163.               break; 
  164.      case 10: memset (&impl_->cmd10_, 0, sizeof (SRB_ExecSCSICmd10));
  165.               memcpy (impl_->cmd10_.CDBByte, cmd, 10);
  166.               impl_->cmd10_.SRB_Cmd        = SC_EXEC_SCSI_CMD;
  167.               impl_->cmd10_.SRB_HaId       = impl_->haid_;
  168.               impl_->cmd10_.SRB_Target     = impl_->scsi_id_;
  169.               impl_->cmd10_.SRB_Lun        = impl_->lun_;
  170.               impl_->cmd10_.SRB_SenseLen   = SENSE_LEN;
  171.               impl_->cmd10_.SRB_CDBLen     = 10;
  172.               if (dataOut && dataOutLen)
  173.               {
  174.                  impl_->cmd10_.SRB_Flags      = SRBF_WRITE;
  175.                  impl_->cmd10_.SRB_BufPointer = dataOut;
  176.                  impl_->cmd10_.SRB_BufLen     = dataOutLen;
  177.               }
  178.               else
  179.               {
  180.                  impl_->cmd10_.SRB_Flags      = SRBF_READ;
  181.                  impl_->cmd10_.SRB_BufPointer = dataIn;
  182.                  impl_->cmd10_.SRB_BufLen     = dataInLen;
  183.               }
  184.               
  185.               (impl_->Sendcommand) ((char *) &impl_->cmd10_);
  186.               while (i-- && impl_->cmd10_.SRB_Status != SS_COMP)
  187.               {
  188.                       while (!impl_->cmd10_.SRB_Status)
  189.                           Sleep (10);
  190.               }
  191.       // AM: Try to get sense data
  192.       if (impl_->cmd10_.SRB_Status == SS_ERR &&
  193.   impl_->cmd10_.SRB_TargStat == STATUS_CHKCOND) {
  194. memcpy(impl_->senseBuffer_, impl_->cmd10_.SenseArea10,
  195.        SENSE_LEN);
  196. if (showMessage)
  197.   printError();
  198. return 2;
  199.       }
  200.               if (impl_->cmd10_.SRB_Status != SS_COMP)
  201.                  return (1);
  202.               break; 
  203.      case 12: memset (&impl_->cmd12_, 0, sizeof (SRB_ExecSCSICmd12));
  204.               memcpy (impl_->cmd12_.CDBByte, cmd, 12);
  205.               impl_->cmd12_.SRB_Cmd        = SC_EXEC_SCSI_CMD;
  206.               impl_->cmd12_.SRB_HaId       = impl_->haid_;
  207.               impl_->cmd12_.SRB_Target     = impl_->scsi_id_;
  208.               impl_->cmd12_.SRB_Lun        = impl_->lun_;
  209.               impl_->cmd12_.SRB_SenseLen   = SENSE_LEN;
  210.               impl_->cmd12_.SRB_CDBLen     = 12;
  211.               if (dataOut && dataOutLen)
  212.               {
  213.                  impl_->cmd12_.SRB_Flags      = SRBF_WRITE;
  214.                  impl_->cmd12_.SRB_BufPointer = dataOut;
  215.                  impl_->cmd12_.SRB_BufLen     = dataOutLen;
  216.               }
  217.               else
  218.               {
  219.                  impl_->cmd12_.SRB_Flags      = SRBF_READ;
  220.                  impl_->cmd12_.SRB_BufPointer = dataIn;
  221.                  impl_->cmd12_.SRB_BufLen     = dataInLen;
  222.               }
  223.               
  224.               (impl_->Sendcommand) ((char *) &impl_->cmd12_);
  225.               while (i-- && impl_->cmd12_.SRB_Status != SS_COMP)
  226.               {
  227.                    while (!impl_->cmd12_.SRB_Status)
  228.                          Sleep (10);
  229.               }
  230.       // AM: Try to get sense data
  231.       if (impl_->cmd12_.SRB_Status == SS_ERR &&
  232.   impl_->cmd12_.SRB_TargStat == STATUS_CHKCOND) {
  233. memcpy(impl_->senseBuffer_, impl_->cmd12_.SenseArea12,
  234.        SENSE_LEN);
  235. if (showMessage)
  236.   printError();
  237. return 2;
  238.       }
  239.               if (impl_->cmd12_.SRB_Status != SS_COMP)
  240.                  return (1);
  241.               break; 
  242.   }
  243.   return 0;
  244. }
  245. const unsigned char *ScsiIf::getSense(int &len) const
  246. {
  247.   len = SENSE_LEN;
  248.   return impl_->senseBuffer_;
  249. }
  250. void ScsiIf::printError()
  251. {
  252.   decodeSense(impl_->senseBuffer_, SENSE_LEN);
  253. }
  254. int ScsiIf::inquiry()
  255. {
  256.   unsigned char cmd[6];
  257.   unsigned char result[0x2c];
  258.   int i;
  259.   cmd[0] = 0x12; // INQUIRY
  260.   cmd[1] = cmd[2] = cmd[3] = 0;
  261.   cmd[4] = 0x2c;
  262.   cmd[5] = 0;
  263.   if (sendCmd (cmd, 6, NULL, 0, result, 0x2c, 1) != 0) {
  264.     message (-2, "Inquiry command failed on '%s': ", impl_->dev_);
  265.     return 1;
  266.   }
  267.   strncpy(vendor_, (char *)(result + 0x08), 8);
  268.   vendor_[8] = 0;
  269.   strncpy(product_, (char *)(result + 0x10), 16);
  270.   product_[16] = 0;
  271.   strncpy(revision_, (char *)(result + 0x20), 4);
  272.   revision_[4] = 0;
  273.   for (i = 7; i >= 0 && vendor_[i] == ' '; i--) 
  274.   {
  275.      vendor_[i] = 0;
  276.   }
  277.   for (i = 15; i >= 0 && product_[i] == ' '; i--) 
  278.   {
  279.      product_[i] = 0;
  280.   }
  281.   for (i = 3; i >= 0 && revision_[i] == ' '; i--) 
  282.   {
  283.      revision_[i] = 0;
  284.   }
  285.   return 0;
  286. }