1
0
Files
irix-657m-src/eoe/cmd/fcman/scsi.c
2022-09-29 17:59:04 +03:00

293 lines
6.3 KiB
C

#include "options.h"
#include <stdio.h>
#include <sys/types.h>
#include <stdarg.h> /* For varargs */
#include <stdlib.h> /* For string conversion routines */
#include <string.h>
#include <bstring.h>
#include <errno.h>
#include <fcntl.h> /* for I/O functions */
#include <unistd.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/major.h>
#include <sys/scsi.h>
/*
* DEVSCSI definitions
*/
#if !HWG_AVAIL
#define DS_UNIT_MASK 0xF
#define DS_UNIT_SHIFT 0
#define DS_LUN_MASK 0x7
#define DS_LUN_SHIFT 4
#define DS_CTLR_MASK 0x7F
#define DS_CTLR_SHIFT 7
#define DSCSI_MAJOR 195
#endif
#ifndef SCEXT
#define SCEXT(_ctlr) (((_ctlr) >> 3) * 10 + ((_ctlr) & 7))
#endif
#ifndef SCINT
#define SCINT(_ctlr) (((_ctlr) % 10) + (((_ctlr) / 10) << 3))
#endif
#include "dslib.h"
#include "debug.h"
#include "scsi.h"
/*
******************************************************************************
* make_devscsi_path()
******************************************************************************
*/
char *make_devscsi_path(int cid, int tid, int lun, char *filename)
{
char dir_name[128];
struct stat buf;
dev_t dev, min, maj;
#if HWG_AVAIL
sprintf(dir_name, "/dev/scsi");
#else
sprintf(dir_name, "/tmp/%d", getpid());
#endif
sprintf(filename, "%s/sc%dd%dl%d", dir_name, cid, tid, lun);
#if !HWG_AVAIL
if (stat(dir_name, &buf) == -1)
mkdir(dir_name, S_IRWXU);
maj = DSCSI_MAJOR;
min = (((dev_t)SCINT(cid) & DS_CTLR_MASK) << DS_CTLR_SHIFT) |
(((dev_t)tid & DS_UNIT_MASK) << DS_UNIT_SHIFT) |
(((dev_t)lun & DS_LUN_MASK) << DS_LUN_SHIFT);
dev = makedev(maj, min);
if (mknod(filename, S_IFCHR | S_IRWXU, dev)) {
fatal("mknod(%s) failed : %s\n", filename, strerror(errno));
}
#endif
return(filename);
}
/*
******************************************************************************
* make_scsiha_path()
******************************************************************************
*/
char *make_scsiha_path(int cid, char *filename)
{
char dir_name[128];
struct stat buf;
dev_t dev, min, maj;
#if HWG_AVAIL
sprintf(dir_name, "/hw/scsi_ctlr");
#else
sprintf(dir_name, "/tmp/%d", getpid());
#endif
sprintf(filename, "%s/%d", dir_name, cid);
#if !HWG_AVAIL
if (stat(dir_name, &buf) == -1)
mkdir(dir_name, S_IRWXU);
maj = SCSIBUS_MAJOR;
min = cid;
dev = makedev(maj, min);
if (mknod(filename, S_IFCHR | S_IRWXU, dev)) {
fatal("mknod(%s) failed : %s\n", filename, strerror(errno));
}
#endif
return(filename);
}
/*
******************************************************************************
* inquiry()
******************************************************************************
*/
int inquiry(char *devname, inq_struct_t *inqdata)
{
struct dsreq *dsp = NULL;
int rc;
int retry = 3;
if ((dsp = dsopen(devname, O_RDONLY)) == NULL) {
return(-1);
}
fillg0cmd(dsp, CMDBUF(dsp),
G0_INQU,
0,
0,
0,
B1(sizeof(inq_struct_t)),
B1(0));
filldsreq(dsp, (u_char *)inqdata, sizeof(inq_struct_t), DSRQ_READ|DSRQ_SENSE);
while (retry--) {
rc = doscsireq(getfd(dsp), dsp);
if (rc == 0)
break;
}
dsclose(dsp);
return(rc);
}
/*
******************************************************************************
* recv_diagnostics()
******************************************************************************
*/
int recv_diagnostics(char *devname, u_char pagecode, u_char *buf, u_int *buflen)
{
struct dsreq *dsp = NULL;
int rc;
int retry = 3;
if ((dsp = dsopen(devname, O_RDONLY)) == NULL) {
printf("dsopen(%s) failed : %s\n", devname, strerror(errno));
return(-1);
}
fillg0cmd(dsp, CMDBUF(dsp),
G0_RDR,
#if PCV_BIT_REQUIRED
1,
#else
0,
#endif
B1(pagecode),
B2(*buflen),
B1(0));
filldsreq(dsp, buf, *buflen, DSRQ_READ|DSRQ_SENSE);
while (retry--) {
rc = doscsireq(getfd(dsp), dsp);
if (rc == 0) {
*buflen = DATASENT(dsp);
break;
}
}
dsclose(dsp);
return(rc);
}
/*
******************************************************************************
* send_diagnostics()
******************************************************************************
*/
int send_diagnostics(char *devname, u_char *buf, u_int buflen)
{
struct dsreq *dsp = NULL;
int rc;
int retry = 3;
if ((dsp = dsopen(devname, O_RDONLY)) == NULL) {
printf("dsopen(%s) failed : %s\n", devname, strerror(errno));
return(-1);
}
fillg0cmd(dsp, CMDBUF(dsp),
G0_SD,
0x10,
0,
B2(buflen),
B1(0));
filldsreq(dsp, buf, buflen, DSRQ_WRITE|DSRQ_SENSE);
while (retry--) {
rc = doscsireq(getfd(dsp), dsp);
if (rc == 0)
break;
}
dsclose(dsp);
return(rc);
}
int startstop_drive(char *devname, char start)
{
struct dsreq *dsp = NULL;
int rc;
int retry = 3;
if ((dsp = dsopen(devname, O_RDONLY)) == NULL) {
printf("dsopen(%s) failed : %s\n", devname, strerror(errno));
return(-1);
}
fillg0cmd(dsp,
CMDBUF(dsp),
G0_STOP,
1,
0,
0,
start,
0);
filldsreq(dsp, NULL, 0, DSRQ_READ|DSRQ_SENSE);
dsp->ds_time = 1000 * 90; /* 90 seconds */
while (retry--) {
rc = doscsireq(getfd(dsp), dsp);
if (rc == 0)
break;
}
dsclose(dsp);
return(rc);
}
/*
******************************************************************************
* enable_pbc()
******************************************************************************
*/
int enable_pbc(char *devname, u_int tid)
{
#if SCSIHA_AVAIL
struct scsi_ha_op ha;
int fd;
if ((fd = open(devname, O_RDONLY)) == -1) {
printf("open(%s) failed: %s\n", devname, strerror(errno));
return(-1);
}
ha.sb_opt = tid;
return(ioctl(fd, SOP_ENABLE_PBC, &ha));
#else
printf("SCSIHA Enable Bypass not implemented yet.\n");
return(0);
#endif
}
/*
******************************************************************************
* disable_pbc()
******************************************************************************
*/
int disable_pbc(char *devname, u_int tid)
{
#if SCSIHA_AVAIL
struct scsi_ha_op ha;
int fd;
if ((fd = open(devname, O_RDONLY)) == -1) {
printf("open(%s) failed: %s\n", devname, strerror(errno));
return(-1);
}
ha.sb_opt = tid;
return(ioctl(fd, SOP_DISABLE_PBC, &ha));
#else
printf("SCSIHA Disable Bypass not implemented yet.\n");
return(0);
#endif
}