diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-03 02:15:56 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-03 02:15:56 +0000 |
commit | 50b48aec6ddd451a6d1709c0942477b503457663 (patch) | |
tree | a9ece53ec06fd0a2819de7a2a6de997193566626 /libk3bdevice/k3bscsicommand_bsd.cpp | |
download | k3b-50b48aec6ddd451a6d1709c0942477b503457663.tar.gz k3b-50b48aec6ddd451a6d1709c0942477b503457663.zip |
Added abandoned KDE3 version of K3B
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k3b@1084400 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'libk3bdevice/k3bscsicommand_bsd.cpp')
-rw-r--r-- | libk3bdevice/k3bscsicommand_bsd.cpp | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/libk3bdevice/k3bscsicommand_bsd.cpp b/libk3bdevice/k3bscsicommand_bsd.cpp new file mode 100644 index 0000000..84e12f9 --- /dev/null +++ b/libk3bdevice/k3bscsicommand_bsd.cpp @@ -0,0 +1,208 @@ +/* + * + * $Id: k3bscsicommand_bsd.cpp 679320 2007-06-23 15:57:22Z trueg $ + * Copyright (C) 2003-2007 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * 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. + * See the file "COPYING" for the exact licensing terms. + */ + +#include "k3bscsicommand.h" +#include "k3bdevice.h" + +#include <k3bdebug.h> + +#include <stdio.h> +#include <errno.h> +#include <camlib.h> +#include <cam/scsi/scsi_message.h> +#include <cam/scsi/scsi_pass.h> + +#define ERRCODE(s) ((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13])) +#define EMEDIUMTYPE EINVAL +#define ENOMEDIUM ENODEV +#define CREAM_ON_ERRNO(s) do { \ + switch ((s)[12]) \ + { case 0x04: errno=EAGAIN; break; \ + case 0x20: errno=ENODEV; break; \ + case 0x21: if ((s)[13]==0) errno=ENOSPC; \ + else errno=EINVAL; \ + break; \ + case 0x30: errno=EMEDIUMTYPE; break; \ + case 0x3A: errno=ENOMEDIUM; break; \ + } \ +} while(0) + + + +class K3bDevice::ScsiCommand::Private +{ +public: + union ccb ccb; +}; + + +void K3bDevice::ScsiCommand::clear() +{ + memset (&d->ccb,0,sizeof(ccb)); +} + + +unsigned char& K3bDevice::ScsiCommand::operator[]( size_t i ) +{ + if( d->ccb.csio.cdb_len < i+1 ) + d->ccb.csio.cdb_len = i+1; + return d->ccb.csio.cdb_io.cdb_bytes[i]; +} + +int K3bDevice::ScsiCommand::transport( TransportDirection dir, + void* data, + size_t len ) +{ + if( !m_device ) + return -1; + + m_device->usageLock(); + + bool needToClose = false; + if( !m_device->isOpen() ) { + needToClose = true; + } + + if( !m_device->open( true ) ) { + m_device->usageUnlock(); + return -1; + } + d->ccb.ccb_h.path_id = m_device->handle()->path_id; + d->ccb.ccb_h.target_id = m_device->handle()->target_id; + d->ccb.ccb_h.target_lun = m_device->handle()->target_lun; + + k3bDebug() << "(K3bDevice::ScsiCommand) transport command " << QString::number((int)d->ccb.csio.cdb_io.cdb_bytes[0], 16) << ", length: " << (int)d->ccb.csio.cdb_len << endl; + int ret=0; + int direction = CAM_DEV_QFRZDIS; + if (!len) + direction |= CAM_DIR_NONE; + else + direction |= (dir & TR_DIR_READ)?CAM_DIR_IN : CAM_DIR_OUT; + cam_fill_csio (&(d->ccb.csio), 1, 0 /* NULL */, direction, MSG_SIMPLE_Q_TAG, (u_int8_t *)data, len, sizeof(d->ccb.csio.sense_data), d->ccb.csio.cdb_len, 30*1000); + unsigned char * sense = (unsigned char *)&d->ccb.csio.sense_data; + + ret = cam_send_ccb(m_device->handle(), &d->ccb); + + if (ret < 0) { + k3bDebug() << "(K3bDevice::ScsiCommand) transport failed: " << ret << endl; + + if( needToClose ) + m_device->close(); + + m_device->usageUnlock(); + + struct scsi_sense_data* senset = (struct scsi_sense_data*)sense; + debugError( d->ccb.csio.cdb_io.cdb_bytes[0], + senset->error_code & SSD_ERRCODE, + senset->flags & SSD_KEY, + senset->add_sense_code, + senset->add_sense_code_qual ); + + int result = (((senset->error_code & SSD_ERRCODE)<<24) & 0xF000 | + ((senset->flags & SSD_KEY)<<16) & 0x0F00 | + (senset->add_sense_code<<8) & 0x00F0 | + (senset->add_sense_code_qual) & 0x000F ); + + return result ? result : ret; + } + + else if ((d->ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + if( needToClose ) + m_device->close(); + m_device->usageUnlock(); + return 0; + } + + errno = EIO; + // FreeBSD 5-CURRENT since 2003-08-24, including 5.2 fails to + // pull sense data automatically, at least for ATAPI transport, + // so I reach for it myself... + if ((d->ccb.csio.scsi_status==SCSI_STATUS_CHECK_COND) && + !(d->ccb.ccb_h.status&CAM_AUTOSNS_VALID)) + { + u_int8_t _sense[18]; + u_int32_t resid=d->ccb.csio.resid; + + memset(_sense,0,sizeof(_sense)); + + operator[](0) = 0x03; // REQUEST SENSE + d->ccb.csio.cdb_io.cdb_bytes[4] = sizeof(_sense); + d->ccb.csio.cdb_len = 6; + d->ccb.csio.ccb_h.flags |= CAM_DIR_IN|CAM_DIS_AUTOSENSE; + d->ccb.csio.data_ptr = _sense; + d->ccb.csio.dxfer_len = sizeof(_sense); + d->ccb.csio.sense_len = 0; + + ret = cam_send_ccb(m_device->handle(), &d->ccb); + + d->ccb.csio.resid = resid; + if (ret<0) + { + k3bDebug() << "(K3bDevice::ScsiCommand) transport failed (2): " << ret << endl; + ret = -1; + struct scsi_sense_data* senset = (struct scsi_sense_data*)sense; + debugError( d->ccb.csio.cdb_io.cdb_bytes[0], + senset->error_code & SSD_ERRCODE, + senset->flags & SSD_KEY, + senset->add_sense_code, + senset->add_sense_code_qual ); + + if( needToClose ) + m_device->close(); + m_device->usageUnlock(); + + return -1; + } + if ((d->ccb.ccb_h.status&CAM_STATUS_MASK) != CAM_REQ_CMP) + { + k3bDebug() << "(K3bDevice::ScsiCommand) transport failed (3): " << ret << endl; + errno=EIO,-1; + ret = -1; + struct scsi_sense_data* senset = (struct scsi_sense_data*)sense; + debugError( d->ccb.csio.cdb_io.cdb_bytes[0], + senset->error_code & SSD_ERRCODE, + senset->flags & SSD_KEY, + senset->add_sense_code, + senset->add_sense_code_qual ); + + if( needToClose ) + m_device->close(); + m_device->usageUnlock(); + + return -1; + } + + memcpy(sense,_sense,sizeof(_sense)); + } + + ret = ERRCODE(sense); + k3bDebug() << "(K3bDevice::ScsiCommand) transport failed (4): " << ret << endl; + if (ret == 0) + ret = -1; + else + CREAM_ON_ERRNO(((unsigned char *)&d->ccb.csio.sense_data)); + struct scsi_sense_data* senset = (struct scsi_sense_data*)sense; + debugError( d->ccb.csio.cdb_io.cdb_bytes[0], + senset->error_code & SSD_ERRCODE, + senset->flags & SSD_KEY, + senset->add_sense_code, + senset->add_sense_code_qual ); + + if( needToClose ) + m_device->close(); + m_device->usageUnlock(); + + return ret; +} |