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

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: ScsiIf-linux.cc,v $
  21.  * Revision 1.5  1998/09/06 13:34:22  mueller
  22.  * Use 'message()' for printing messages.
  23.  *
  24.  * Revision 1.4  1998/08/13 19:13:28  mueller
  25.  * Added member function 'timout()' to set timeout of SCSI commands.
  26.  *
  27.  * Revision 1.3  1998/08/07 12:36:04  mueller
  28.  * Added enabling command transformation for emulated host adaptor (ATAPI).
  29.  *
  30.  */
  31. static char rcsid[] = "$Id: ScsiIf-linux.cc,v 1.5 1998/09/06 13:34:22 mueller Exp $";
  32. #include "config.h"
  33. #include <windows.h>
  34. #include <winioctl.h>
  35. #include <stdio.h>
  36. #include <fcntl.h>
  37. #include <errno.h>
  38. #include <stddef.h>
  39. #include <string.h>
  40. #include <assert.h>
  41. #include "ScsiIf.h"
  42. #include "util.h"
  43. #include "ntddcdrm.h"
  44. #include "decodeSense.cc"
  45. //
  46. // SCSI Definitionen.
  47. //
  48. #define IOCTL_SCSI_BASE                 FILE_DEVICE_CONTROLLER
  49. #define IOCTL_SCSI_GET_CAPABILITIES     CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
  50. #define IOCTL_SCSI_PASS_THROUGH_DIRECT  CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
  51. #define IOCTL_SCSI_GET_ADDRESS          CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS)
  52. #define SCSI_IOCTL_DATA_OUT          0
  53. #define SCSI_IOCTL_DATA_IN           1
  54. #define SCSI_IOCTL_DATA_UNSPECIFIED  2
  55. #pragma pack(4)
  56. typedef struct _IO_SCSI_CAPABILITIES 
  57. {
  58.     ULONG Length;
  59.     ULONG MaximumTransferLength;
  60.     ULONG MaximumPhysicalPages;
  61.     ULONG SupportedAsynchronousEvents;
  62.     ULONG AlignmentMask;
  63.     BOOLEAN TaggedQueuing;
  64.     BOOLEAN AdapterScansDown;
  65.     BOOLEAN AdapterUsesPio;
  66. } IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES;
  67. typedef struct _SCSI_PASS_THROUGH_DIRECT 
  68. {
  69.     USHORT Length;
  70.     UCHAR ScsiStatus;
  71.     UCHAR PathId;
  72.     UCHAR TargetId;
  73.     UCHAR Lun;
  74.     UCHAR CdbLength;
  75.     UCHAR SenseInfoLength;
  76.     UCHAR DataIn;
  77.     ULONG DataTransferLength;
  78.     ULONG TimeOutValue;
  79.     PVOID DataBuffer;
  80.     ULONG SenseInfoOffset;
  81.     UCHAR Cdb[16];
  82. } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
  83. typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER 
  84. {
  85.   SCSI_PASS_THROUGH_DIRECT sptd;
  86.   ULONG Filler;      // realign buffer to double word boundary
  87.   UCHAR ucSenseBuf[32];
  88. } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
  89. typedef struct _SCSI_INQUIRY_DEVICE 
  90. {
  91.   UCHAR Type;
  92.   UCHAR TypeModifier;
  93.   UCHAR Version;
  94.   UCHAR Format;
  95.   UCHAR AddLength; // n-4
  96.   UCHAR Reserved[2];
  97.   UCHAR Flags;
  98.   char  VendorId[8];
  99.   char  ProductId[16];
  100.   char  ProductRevLevel[4];
  101.   char  ProductRevDate[8];
  102. } SCSI_INQUIRY_DEVICE, *PSCSI_INQUIRY_DEVICE;
  103. typedef struct _SCSI_ADDRESS {
  104.     ULONG Length;
  105.     UCHAR PortNumber;
  106.     UCHAR PathId;
  107.     UCHAR TargetId;
  108.     UCHAR Lun;
  109. }SCSI_ADDRESS, *PSCSI_ADDRESS;
  110. #pragma pack(1)
  111. //
  112. // SCSI CDB operation codes
  113. //
  114. #define SCSIOP_INQUIRY             0x12
  115. #define SCSIOP_MODE_SELECT         0x15
  116. #define SCSIOP_MODE_SENSE          0x1A
  117. #define AUDIO_BLOCK_LEN 2352
  118. #define BUF_SIZE  (63*1024)
  119. class ScsiIfImpl 
  120. {
  121. public:
  122.   char *dev_;
  123.   HANDLE hCD;
  124.   SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb;
  125.   
  126.   unsigned char senseBuffer_[32];
  127.   char haid_;
  128.   char lun_;
  129.   char scsi_id_;
  130. };
  131. ScsiIf::ScsiIf(const char *dev)
  132. {
  133.   impl_ = new ScsiIfImpl;
  134.   impl_->dev_ = strdup3CC("\\.\", dev, NULL);
  135.   impl_->hCD = INVALID_HANDLE_VALUE;
  136.   vendor_[0] = 0;
  137.   product_[0] = 0;
  138.   revision_[0] = 0;
  139. }
  140. ScsiIf::~ScsiIf()
  141. {
  142.   if (impl_->hCD != INVALID_HANDLE_VALUE)
  143.      CloseHandle (impl_->hCD);
  144.   delete impl_;
  145. }
  146. // opens scsi device
  147. // return: 0: OK
  148. //         1: device could not be opened
  149. //         2: inquiry failed
  150. int ScsiIf::init()
  151. {
  152.   int i = 0;
  153.   DWORD ol;
  154.   SCSI_ADDRESS sa;
  155.   IO_SCSI_CAPABILITIES ca;
  156.   while (i++ < 3 && (impl_->hCD == INVALID_HANDLE_VALUE))
  157.   {
  158.     impl_->hCD = CreateFile (impl_->dev_, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  159.   }
  160.   if (impl_->hCD == INVALID_HANDLE_VALUE) {
  161.     return 1;
  162.   }
  163.   if (DeviceIoControl (impl_->hCD, IOCTL_SCSI_GET_ADDRESS, NULL, 0, &sa, sizeof(SCSI_ADDRESS), &ol, NULL)) 
  164.   { 
  165.     impl_->haid_    = sa.PortNumber;
  166.     impl_->lun_     = sa.Lun;
  167.     impl_->scsi_id_ = sa.TargetId;
  168.   }
  169.   else
  170.   {
  171.     CloseHandle (impl_->hCD);
  172.     impl_->hCD = INVALID_HANDLE_VALUE;
  173.     return 1;
  174.   }
  175.   if (DeviceIoControl (impl_->hCD, IOCTL_SCSI_GET_CAPABILITIES, NULL, 0, &ca, sizeof(IO_SCSI_CAPABILITIES), &ol, NULL)) 
  176.   {
  177.     maxDataLen_ = ca.MaximumTransferLength;
  178.   }
  179.   else
  180.   {
  181.     CloseHandle (impl_->hCD);
  182.     impl_->hCD = INVALID_HANDLE_VALUE;
  183.     return 1;
  184.   }
  185.   if (inquiry() != 0) 
  186.     return 2;
  187.   return 0;
  188. }
  189. // Sets given timeout value in seconds and returns old timeout.
  190. // return: old timeout
  191. int ScsiIf::timeout (int t)
  192. {
  193.   return 0;
  194. }
  195. // sends a scsi command and receives data
  196. // return 0: OK
  197. //        1: scsi command failed (os level, no sense data available)
  198. //        2: scsi command failed (sense data available)
  199. int ScsiIf::sendCmd (unsigned char *cmd,     int cmdLen, 
  200.      unsigned char *dataOut, int dataOutLen,
  201.      unsigned char *dataIn,  int dataInLen,
  202.      int showMessage)
  203. {
  204.   int i = 10;
  205.   DWORD er, il, ol;
  206.   ZeroMemory (&impl_->sb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
  207.   impl_->sb.sptd.Length             = sizeof(SCSI_PASS_THROUGH_DIRECT);
  208.   impl_->sb.sptd.PathId             = 0;
  209.   impl_->sb.sptd.TargetId           = impl_->scsi_id_;
  210.   impl_->sb.sptd.Lun                = impl_->lun_;
  211.   impl_->sb.sptd.CdbLength          = cmdLen;
  212.   impl_->sb.sptd.SenseInfoLength    = 32;
  213.   impl_->sb.sptd.TimeOutValue       = 4;
  214.   impl_->sb.sptd.SenseInfoOffset    = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
  215.   memcpy (impl_->sb.sptd.Cdb, cmd, cmdLen);
  216.   if (dataOut && dataOutLen)
  217.   {
  218.      impl_->sb.sptd.DataIn              = SCSI_IOCTL_DATA_OUT;
  219.      impl_->sb.sptd.DataBuffer          = dataOut;
  220.      impl_->sb.sptd.DataTransferLength  = dataOutLen;
  221.   }
  222.   else
  223.   {
  224.      impl_->sb.sptd.DataIn              = SCSI_IOCTL_DATA_IN;
  225.      impl_->sb.sptd.DataBuffer          = dataIn;
  226.      impl_->sb.sptd.DataTransferLength  = dataInLen;
  227.   }
  228.   il = sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
  229.   // AM: what about sense data?
  230.   if (DeviceIoControl (impl_->hCD, IOCTL_SCSI_PASS_THROUGH_DIRECT, &impl_->sb, il, &impl_->sb, il, &ol, NULL)) 
  231.   {
  232.       er = impl_->sb.sptd.ScsiStatus ? impl_->sb.sptd.ScsiStatus | 0x20000000 : 0;
  233.       if (!er)
  234.          return (0); 
  235.   }
  236.   else 
  237.      return (1);
  238.   
  239.   return 0;
  240. }
  241. const unsigned char *ScsiIf::getSense(int &len) const
  242. {
  243.   len = 32;
  244.   return impl_->sb.ucSenseBuf;
  245. }
  246. void ScsiIf::printError()
  247. {
  248.   decodeSense(impl_->sb.ucSenseBuf, 32);
  249. }
  250. int ScsiIf::inquiry()
  251. {
  252.   unsigned char cmd[6];
  253.   int i;
  254.   SCSI_INQUIRY_DEVICE NTinqbuf;
  255.   ZeroMemory (&NTinqbuf, sizeof(SCSI_INQUIRY_DEVICE));
  256.   cmd[0] = 0x12; // INQUIRY
  257.   cmd[1] = cmd[2] = cmd[3] = 0;
  258.   cmd[4] = sizeof (NTinqbuf);
  259.   cmd[5] = 0;
  260.   if (sendCmd (cmd, 6, NULL, 0,
  261.        (unsigned char *) &NTinqbuf, sizeof (NTinqbuf), 1) != 0) {
  262.     message (-2, "Inquiry command failed on '%s': ", impl_->dev_);
  263.     return 1;
  264.   }
  265.   strncpy(vendor_, (char *)(NTinqbuf.VendorId), 8);
  266.   vendor_[8] = 0;
  267.   strncpy(product_, (char *)(NTinqbuf.ProductId), 16);
  268.   product_[16] = 0;
  269.   strncpy(revision_, (char *)(NTinqbuf.ProductRevLevel), 4);
  270.   revision_[4] = 0;
  271.   for (i = 7; i >= 0 && vendor_[i] == ' '; i--) 
  272.   {
  273.      vendor_[i] = 0;
  274.   }
  275.   for (i = 15; i >= 0 && product_[i] == ' '; i--) 
  276.   {
  277.      product_[i] = 0;
  278.   }
  279.   for (i = 3; i >= 0 && revision_[i] == ' '; i--) 
  280.   {
  281.      revision_[i] = 0;
  282.   }
  283.   return 0;
  284. }