ScsiIf-nt.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:8k
- /* cdrdao - write audio CD-Rs in disc-at-once mode
- *
- * Copyright (C) 1998 Andreas Mueller <mueller@daneb.ping.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /*
- * $Log: ScsiIf-linux.cc,v $
- * Revision 1.5 1998/09/06 13:34:22 mueller
- * Use 'message()' for printing messages.
- *
- * Revision 1.4 1998/08/13 19:13:28 mueller
- * Added member function 'timout()' to set timeout of SCSI commands.
- *
- * Revision 1.3 1998/08/07 12:36:04 mueller
- * Added enabling command transformation for emulated host adaptor (ATAPI).
- *
- */
- static char rcsid[] = "$Id: ScsiIf-linux.cc,v 1.5 1998/09/06 13:34:22 mueller Exp $";
- #include "config.h"
- #include <windows.h>
- #include <winioctl.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <stddef.h>
- #include <string.h>
- #include <assert.h>
- #include "ScsiIf.h"
- #include "util.h"
- #include "ntddcdrm.h"
- #include "decodeSense.cc"
- //
- // SCSI Definitionen.
- //
- #define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
- #define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
- #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
- #define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS)
- #define SCSI_IOCTL_DATA_OUT 0
- #define SCSI_IOCTL_DATA_IN 1
- #define SCSI_IOCTL_DATA_UNSPECIFIED 2
- #pragma pack(4)
- typedef struct _IO_SCSI_CAPABILITIES
- {
- ULONG Length;
- ULONG MaximumTransferLength;
- ULONG MaximumPhysicalPages;
- ULONG SupportedAsynchronousEvents;
- ULONG AlignmentMask;
- BOOLEAN TaggedQueuing;
- BOOLEAN AdapterScansDown;
- BOOLEAN AdapterUsesPio;
- } IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES;
- typedef struct _SCSI_PASS_THROUGH_DIRECT
- {
- USHORT Length;
- UCHAR ScsiStatus;
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
- UCHAR CdbLength;
- UCHAR SenseInfoLength;
- UCHAR DataIn;
- ULONG DataTransferLength;
- ULONG TimeOutValue;
- PVOID DataBuffer;
- ULONG SenseInfoOffset;
- UCHAR Cdb[16];
- } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
- typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
- {
- SCSI_PASS_THROUGH_DIRECT sptd;
- ULONG Filler; // realign buffer to double word boundary
- UCHAR ucSenseBuf[32];
- } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
- typedef struct _SCSI_INQUIRY_DEVICE
- {
- UCHAR Type;
- UCHAR TypeModifier;
- UCHAR Version;
- UCHAR Format;
- UCHAR AddLength; // n-4
- UCHAR Reserved[2];
- UCHAR Flags;
- char VendorId[8];
- char ProductId[16];
- char ProductRevLevel[4];
- char ProductRevDate[8];
- } SCSI_INQUIRY_DEVICE, *PSCSI_INQUIRY_DEVICE;
- typedef struct _SCSI_ADDRESS {
- ULONG Length;
- UCHAR PortNumber;
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
- }SCSI_ADDRESS, *PSCSI_ADDRESS;
- #pragma pack(1)
- //
- // SCSI CDB operation codes
- //
- #define SCSIOP_INQUIRY 0x12
- #define SCSIOP_MODE_SELECT 0x15
- #define SCSIOP_MODE_SENSE 0x1A
- #define AUDIO_BLOCK_LEN 2352
- #define BUF_SIZE (63*1024)
- class ScsiIfImpl
- {
- public:
- char *dev_;
- HANDLE hCD;
- SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb;
-
- unsigned char senseBuffer_[32];
- char haid_;
- char lun_;
- char scsi_id_;
- };
- ScsiIf::ScsiIf(const char *dev)
- {
- impl_ = new ScsiIfImpl;
- impl_->dev_ = strdup3CC("\\.\", dev, NULL);
- impl_->hCD = INVALID_HANDLE_VALUE;
- vendor_[0] = 0;
- product_[0] = 0;
- revision_[0] = 0;
- }
- ScsiIf::~ScsiIf()
- {
- if (impl_->hCD != INVALID_HANDLE_VALUE)
- CloseHandle (impl_->hCD);
- delete impl_;
- }
- // opens scsi device
- // return: 0: OK
- // 1: device could not be opened
- // 2: inquiry failed
- int ScsiIf::init()
- {
- int i = 0;
- DWORD ol;
- SCSI_ADDRESS sa;
- IO_SCSI_CAPABILITIES ca;
- while (i++ < 3 && (impl_->hCD == INVALID_HANDLE_VALUE))
- {
- impl_->hCD = CreateFile (impl_->dev_, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- }
- if (impl_->hCD == INVALID_HANDLE_VALUE) {
- return 1;
- }
- if (DeviceIoControl (impl_->hCD, IOCTL_SCSI_GET_ADDRESS, NULL, 0, &sa, sizeof(SCSI_ADDRESS), &ol, NULL))
- {
- impl_->haid_ = sa.PortNumber;
- impl_->lun_ = sa.Lun;
- impl_->scsi_id_ = sa.TargetId;
- }
- else
- {
- CloseHandle (impl_->hCD);
- impl_->hCD = INVALID_HANDLE_VALUE;
- return 1;
- }
- if (DeviceIoControl (impl_->hCD, IOCTL_SCSI_GET_CAPABILITIES, NULL, 0, &ca, sizeof(IO_SCSI_CAPABILITIES), &ol, NULL))
- {
- maxDataLen_ = ca.MaximumTransferLength;
- }
- else
- {
- CloseHandle (impl_->hCD);
- impl_->hCD = INVALID_HANDLE_VALUE;
- return 1;
- }
- if (inquiry() != 0)
- return 2;
- return 0;
- }
- // Sets given timeout value in seconds and returns old timeout.
- // return: old timeout
- int ScsiIf::timeout (int t)
- {
- return 0;
- }
- // sends a scsi command and receives data
- // return 0: OK
- // 1: scsi command failed (os level, no sense data available)
- // 2: scsi command failed (sense data available)
- int ScsiIf::sendCmd (unsigned char *cmd, int cmdLen,
- unsigned char *dataOut, int dataOutLen,
- unsigned char *dataIn, int dataInLen,
- int showMessage)
- {
- int i = 10;
- DWORD er, il, ol;
- ZeroMemory (&impl_->sb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
- impl_->sb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
- impl_->sb.sptd.PathId = 0;
- impl_->sb.sptd.TargetId = impl_->scsi_id_;
- impl_->sb.sptd.Lun = impl_->lun_;
- impl_->sb.sptd.CdbLength = cmdLen;
- impl_->sb.sptd.SenseInfoLength = 32;
- impl_->sb.sptd.TimeOutValue = 4;
- impl_->sb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
- memcpy (impl_->sb.sptd.Cdb, cmd, cmdLen);
- if (dataOut && dataOutLen)
- {
- impl_->sb.sptd.DataIn = SCSI_IOCTL_DATA_OUT;
- impl_->sb.sptd.DataBuffer = dataOut;
- impl_->sb.sptd.DataTransferLength = dataOutLen;
- }
- else
- {
- impl_->sb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
- impl_->sb.sptd.DataBuffer = dataIn;
- impl_->sb.sptd.DataTransferLength = dataInLen;
- }
- il = sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
- // AM: what about sense data?
- if (DeviceIoControl (impl_->hCD, IOCTL_SCSI_PASS_THROUGH_DIRECT, &impl_->sb, il, &impl_->sb, il, &ol, NULL))
- {
- er = impl_->sb.sptd.ScsiStatus ? impl_->sb.sptd.ScsiStatus | 0x20000000 : 0;
- if (!er)
- return (0);
- }
- else
- return (1);
-
- return 0;
- }
- const unsigned char *ScsiIf::getSense(int &len) const
- {
- len = 32;
- return impl_->sb.ucSenseBuf;
- }
- void ScsiIf::printError()
- {
- decodeSense(impl_->sb.ucSenseBuf, 32);
- }
- int ScsiIf::inquiry()
- {
- unsigned char cmd[6];
- int i;
- SCSI_INQUIRY_DEVICE NTinqbuf;
- ZeroMemory (&NTinqbuf, sizeof(SCSI_INQUIRY_DEVICE));
- cmd[0] = 0x12; // INQUIRY
- cmd[1] = cmd[2] = cmd[3] = 0;
- cmd[4] = sizeof (NTinqbuf);
- cmd[5] = 0;
- if (sendCmd (cmd, 6, NULL, 0,
- (unsigned char *) &NTinqbuf, sizeof (NTinqbuf), 1) != 0) {
- message (-2, "Inquiry command failed on '%s': ", impl_->dev_);
- return 1;
- }
- strncpy(vendor_, (char *)(NTinqbuf.VendorId), 8);
- vendor_[8] = 0;
- strncpy(product_, (char *)(NTinqbuf.ProductId), 16);
- product_[16] = 0;
- strncpy(revision_, (char *)(NTinqbuf.ProductRevLevel), 4);
- revision_[4] = 0;
- for (i = 7; i >= 0 && vendor_[i] == ' '; i--)
- {
- vendor_[i] = 0;
- }
- for (i = 15; i >= 0 && product_[i] == ' '; i--)
- {
- product_[i] = 0;
- }
- for (i = 3; i >= 0 && revision_[i] == ' '; i--)
- {
- revision_[i] = 0;
- }
- return 0;
- }