mirror of
https://github.com/moibenko/mtx.git
synced 2025-12-23 05:55:13 +00:00
215 lines
5.5 KiB
C
215 lines
5.5 KiB
C
/* SCSI.C - Digital Unix-specific SCSI routines.
|
|
**
|
|
** TECSys Development, Inc., April 1998
|
|
**
|
|
** This module began life as a part of XMCD, an X-windows CD player
|
|
** program for many platforms. No real functionality from the original XMCD
|
|
** is present in this module, but in the interest of making certain that
|
|
** proper credit is given where it may be due, the copyrights and inclusions
|
|
** from the XMCD module OS_DEC.C are included below.
|
|
**
|
|
** The portions of coding in this module ascribable to TECSys Development
|
|
** are hereby also released under the terms and conditions of version 2
|
|
** of the GNU General Public License as described below....
|
|
*/
|
|
|
|
/*
|
|
* libdi - scsipt SCSI Device Interface Library
|
|
*
|
|
* Copyright (C) 1993-1997 Ti Kan
|
|
* E-mail: ti@amb.org
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
/*
|
|
* Digital UNIX (OSF/1) and Ultrix support
|
|
*
|
|
* Contributing author: Matt Thomas
|
|
* E-Mail: thomas@lkg.dec.com
|
|
*
|
|
* This software fragment contains code that interfaces the
|
|
* application to the Digital UNIX and Ultrix operating systems.
|
|
* The term Digital, Ultrix and OSF/1 are used here for identification
|
|
* purposes only.
|
|
*/
|
|
|
|
static int bus = -1,
|
|
target = -1,
|
|
lun = -1;
|
|
|
|
static int SCSI_OpenDevice(char *DeviceName)
|
|
{
|
|
int fd;
|
|
struct stat stbuf;
|
|
int saverr;
|
|
|
|
/* Check for validity of device node */
|
|
if (stat(DeviceName, &stbuf) < 0)
|
|
{
|
|
FatalError("cannot stat SCSI device '%s' - %m\n", DeviceName);
|
|
}
|
|
if (!S_ISCHR(stbuf.st_mode))
|
|
{
|
|
FatalError("device '%s': not appropriate device type - %m\n", DeviceName);
|
|
}
|
|
|
|
if ((fd = open(DeviceName, O_RDONLY | O_NDELAY, 0)) >= 0)
|
|
{
|
|
struct devget devget;
|
|
|
|
if (ioctl(fd, DEVIOCGET, &devget) >= 0)
|
|
{
|
|
#ifdef __osf__
|
|
lun = devget.slave_num % 8;
|
|
devget.slave_num /= 8;
|
|
#else
|
|
lun = 0;
|
|
#endif
|
|
target = devget.slave_num % 8;
|
|
devget.slave_num /= 8;
|
|
bus = devget.slave_num % 8;
|
|
(void) close(fd);
|
|
|
|
if ((fd = open(DEV_CAM, O_RDWR, 0)) >= 0 ||
|
|
(fd = open(DEV_CAM, O_RDONLY, 0)) >= 0)
|
|
{
|
|
return (fd);
|
|
}
|
|
fd = bus = target = lun = -1;
|
|
FatalError("error %d opening SCSI device '%s' - %m\n",
|
|
errno, DEV_CAM);
|
|
}
|
|
else
|
|
{
|
|
(void) close(fd);
|
|
fd = bus = target = lun = -1;
|
|
FatalError("error %d on DEVIOCGET ioctl for '%s' - %m\n",
|
|
errno, DeviceName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
saverr = errno;
|
|
fd = bus = target = lun = -1;
|
|
FatalError("cannot open SCSI device '%s', error %d - %m\n",
|
|
DeviceName, saverr);
|
|
}
|
|
|
|
fd = bus = target = lun = -1;
|
|
return -1;
|
|
}
|
|
|
|
|
|
static void SCSI_CloseDevice(char *DeviceName, int DeviceFD)
|
|
{
|
|
(void) close(DeviceFD);
|
|
bus = target = lun = -1;
|
|
}
|
|
|
|
|
|
static int SCSI_ExecuteCommand(int DeviceFD,
|
|
Direction_T Direction,
|
|
CDB_T *CDB,
|
|
int CDB_Length,
|
|
void *DataBuffer,
|
|
int DataBufferLength,
|
|
RequestSense_T *RequestSense)
|
|
{
|
|
UAGT_CAM_CCB uagt;
|
|
CCB_SCSIIO ccb;
|
|
|
|
if (DeviceFD < 0)
|
|
return -1;
|
|
|
|
(void) memset(&uagt, 0, sizeof(uagt));
|
|
(void) memset(&ccb, 0, sizeof(ccb));
|
|
|
|
/* Setup the user agent ccb */
|
|
uagt.uagt_ccb = (CCB_HEADER *) &ccb;
|
|
uagt.uagt_ccblen = sizeof(CCB_SCSIIO);
|
|
|
|
/* Setup the scsi ccb */
|
|
(void) memcpy((unsigned char *) ccb.cam_cdb_io.cam_cdb_bytes,
|
|
CDB, CDB_Length);
|
|
ccb.cam_cdb_len = CDB_Length;
|
|
ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb;
|
|
ccb.cam_ch.cam_ccb_len = sizeof(CCB_SCSIIO);
|
|
ccb.cam_ch.cam_func_code = XPT_SCSI_IO;
|
|
|
|
if (DataBuffer != NULL && DataBufferLength > 0)
|
|
{
|
|
ccb.cam_ch.cam_flags |= (Direction == Input) ?
|
|
CAM_DIR_IN : CAM_DIR_OUT;
|
|
uagt.uagt_buffer = (u_char *) DataBuffer;
|
|
uagt.uagt_buflen = DataBufferLength;
|
|
}
|
|
else
|
|
ccb.cam_ch.cam_flags |= CAM_DIR_NONE;
|
|
|
|
ccb.cam_ch.cam_flags |= CAM_DIS_AUTOSENSE;
|
|
ccb.cam_data_ptr = uagt.uagt_buffer;
|
|
ccb.cam_dxfer_len = uagt.uagt_buflen;
|
|
ccb.cam_timeout = 300; /* Timeout set to 5 minutes */
|
|
|
|
ccb.cam_sense_ptr = (u_char *) RequestSense;
|
|
ccb.cam_sense_len = sizeof(RequestSense_T);
|
|
|
|
ccb.cam_ch.cam_path_id = bus;
|
|
ccb.cam_ch.cam_target_id = target;
|
|
ccb.cam_ch.cam_target_lun = lun;
|
|
|
|
if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/* Check return status */
|
|
if ((ccb.cam_ch.cam_status & CAM_STATUS_MASK) != CAM_REQ_CMP)
|
|
{
|
|
if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN)
|
|
{
|
|
(void) memset(&ccb, 0, sizeof(ccb));
|
|
(void) memset(&uagt, 0, sizeof(uagt));
|
|
|
|
/* Setup the user agent ccb */
|
|
uagt.uagt_ccb = (CCB_HEADER *) &ccb;
|
|
uagt.uagt_ccblen = sizeof(CCB_RELSIM);
|
|
|
|
/* Setup the scsi ccb */
|
|
ccb.cam_ch.my_addr = (struct ccb_header *) &ccb;
|
|
ccb.cam_ch.cam_ccb_len = sizeof(CCB_RELSIM);
|
|
ccb.cam_ch.cam_func_code = XPT_REL_SIMQ;
|
|
|
|
ccb.cam_ch.cam_path_id = bus;
|
|
ccb.cam_ch.cam_target_id = target;
|
|
ccb.cam_ch.cam_target_lun = lun;
|
|
|
|
if (ioctl(DeviceFD, UAGT_CAM_IO, (caddr_t) &uagt) < 0)
|
|
return -1;
|
|
}
|
|
|
|
printf( "mtx: %s:\n%s=0x%x %s=0x%x\n",
|
|
"SCSI command fault",
|
|
"Opcode",
|
|
CDB[0],
|
|
"Status",
|
|
ccb.cam_scsi_status);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|