File:  [NeXTSTEP 3.3 examples] / Examples / UNIX / SCSI_CD / scsi_commands.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:48:25 2018 UTC (8 years, 1 month ago) by root
Branches: NeXT, MAIN
CVS tags: NeXTSTEP33, HEAD
Sample Programs from NeXSTEP 3.3

/*
 * scsi_commands.c: scsi command functions
 *
 * History
 * -------
 * 02-Feb-93	Erik Kay at NeXT
 *	i386 support
 * Tue Sep  3 15:00:13 PDT 1991 James C. Lee at NeXT
 *  Created (copied a lot of data structures & functions calls from
 *   perftest.c by Mike DeMoney)
 */

#import "scsi_commands.h"
#import <sys/time.h>
#import <bsd/dev/disk.h>
#import <bsd/dev/scsireg.h>
#import <stdio.h>
#import <libc.h>
#import <stdlib.h>


void fatal(const char *msg, ...)
{
	va_list ap;

	va_start(ap, msg);
/*	fprintf(stderr, "%s: ", progname);*/
	vfprintf(stderr, msg, ap);
	fprintf(stderr, "\n");
	va_end(ap);

	exit(1);
}

inline int is_pow2(int i)
{
	return (i & (i - 1)) == 0;
}

int do_inquiry(int fd, struct inquiry_reply *irp, struct esense_reply *erp)
{
	struct scsi_req sr;
	struct cdb_6 *c6p;
	int err;

	bzero((char *)&sr, sizeof(sr));

	c6p = (struct cdb_6 *)&sr.sr_cdb;
	c6p->c6_opcode = C6OP_INQUIRY;
	c6p->c6_len = sizeof(*irp);

	sr.sr_addr = (char *)irp;
	sr.sr_dma_max = sizeof(*irp);
	sr.sr_ioto = 5;
	sr.sr_dma_dir = SR_DMA_RD;

	err = ioctl(fd, SDIOCSRQ, &sr);
	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}

int do_testunitready(int fd, struct timeval *tvp, struct esense_reply *erp)
{
	struct scsi_req sr;
	struct cdb_6 *c6p;
	int err;

	bzero((char *)&sr, sizeof(sr));

	c6p = (struct cdb_6 *)&sr.sr_cdb;
	c6p->c6_opcode = C6OP_TESTRDY;

	sr.sr_addr = NULL;
	sr.sr_dma_max = 0;
	sr.sr_ioto = 5;
	sr.sr_dma_dir = SR_DMA_RD;

	err = ioctl(fd, SDIOCSRQ, &sr);

	*tvp = sr.sr_exec_time;

	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}

int do_modesense(int fd, struct mode_sense_reply *msrp, int page,
	struct esense_reply *erp)
{
	struct scsi_req sr;
	struct mode_sense_cmd *mscp;
	int err;

	bzero((char *)&sr, sizeof(sr));

	mscp = (struct mode_sense_cmd *)&sr.sr_cdb;
	mscp->msc_opcode = C6OP_MODESENSE;
	mscp->msc_pcf = 0;	/* report current values */
	mscp->msc_page = page;
	mscp->msc_len = sizeof(*msrp);

	sr.sr_addr = (char *)msrp;
	sr.sr_dma_max = sizeof(*msrp);
	/*
	 * Extend timeout so Quantum drive works with test.
	 */
	sr.sr_ioto = 50;
	sr.sr_dma_dir = SR_DMA_RD;

	err = ioctl(fd, SDIOCSRQ, &sr);

	printf("sr.sr_io_status: %d\n", sr.sr_io_status);
	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}

int do_readcapacity(int fd, struct capacity_reply *crp,
	struct esense_reply *erp)
{
	struct scsi_req sr;
	struct cdb_10 *c10p;
	int err;

	bzero((char *)&sr, sizeof(sr.sr_cdb));

	c10p = (struct cdb_10 *)&sr.sr_cdb;
	c10p->c10_opcode = C10OP_READCAPACITY;

	sr.sr_addr = (char *)crp;
	sr.sr_dma_max = sizeof(*crp);
	sr.sr_ioto = 5;
	sr.sr_dma_dir = SR_DMA_RD;

	err = ioctl(fd, SDIOCSRQ, &sr);
	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}

int do_seek(int fd, int lba, struct timeval *tvp, struct esense_reply *erp)
{
	struct scsi_req sr;
	struct cdb_6 *c6p;
	int err;

	bzero((char *)&sr, sizeof(sr));

	c6p = (struct cdb_6 *)&sr.sr_cdb;
	c6p->c6_opcode = C6OP_SEEK;
#ifdef i386
	if (lba > 0) {
	    c6p->c6_lba0 = lba & 0xFF;
	    c6p->c6_lba1 = (lba >> 8) & 0xFF;
	    c6p->c6_lba2 = (lba >> 16) & 0xFF;
	} else
	    c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
#else
	c6p->c6_lba = lba;
#endif

	sr.sr_addr = 0;
	sr.sr_dma_max = 0;	/* don't really do I/O to memory */
	sr.sr_ioto = 5;
	sr.sr_dma_dir = SR_DMA_RD;

	err = ioctl(fd, SDIOCSRQ, &sr);

	*tvp = sr.sr_exec_time;

	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}

int do_read(int fd, int lba, int nblks, struct timeval *tvp,
	struct esense_reply *erp)
{
	struct scsi_req sr;
	struct cdb_6 *c6p;
	int err;

	if (nblks > 256)
		fatal("Too many blocks for read: %d", nblks);
	if (nblks == 256)
		nblks = 0;

	bzero((char *)&sr, sizeof(sr));

	c6p = (struct cdb_6 *)&sr.sr_cdb;
	c6p->c6_opcode = C6OP_READ;
#ifdef i386
	if (lba > 0) {
	    c6p->c6_lba0 = lba & 0xFF;
	    c6p->c6_lba1 = (lba >> 8) & 0xFF;
	    c6p->c6_lba2 = (lba >> 16) & 0xFF;
	} else
	    c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
#else
	c6p->c6_lba = lba;
#endif
	c6p->c6_len = nblks;

	sr.sr_addr = NULL;
	sr.sr_dma_max = 0;	/* don't really do I/O to memory */
	sr.sr_ioto = 5;
	sr.sr_dma_dir = SR_DMA_RD;

	err = ioctl(fd, SDIOCSRQ, &sr);

	*tvp = sr.sr_exec_time;

	if (sr.sr_dma_xfr != 0)
		fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);

	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}

int do_write(int fd, int lba, int nblks, struct timeval *tvp,
	struct esense_reply *erp)
{
	struct scsi_req sr;
	struct cdb_6 *c6p;
	int err;

	if (nblks > 256)
		fatal("Too many blocks for read: %d", nblks);
	if (nblks == 256)
		nblks = 0;

	bzero((char *)&sr, sizeof(sr));

	c6p = (struct cdb_6 *)&sr.sr_cdb;
	c6p->c6_opcode = C6OP_WRITE;
#ifdef i386
	if (lba > 0) {
	    c6p->c6_lba0 = lba & 0xFF;
	    c6p->c6_lba1 = (lba >> 8) & 0xFF;
	    c6p->c6_lba2 = (lba >> 16) & 0xFF;
	} else
	    c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
#else
	c6p->c6_lba = lba;
#endif
	c6p->c6_len = nblks;

	sr.sr_addr = NULL;
	sr.sr_dma_max = 0;	/* don't really do I/O to memory */
	sr.sr_ioto = 5;
	sr.sr_dma_dir = SR_DMA_WR;

	err = ioctl(fd, SDIOCSRQ, &sr);

	*tvp = sr.sr_exec_time;

	if (sr.sr_dma_xfr != 0)
		fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);

	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}

#if 0
int do_readbuffer(int fd, int alloc_len, int *avail_len, struct timeval *tvp,
	struct esense_reply *erp)
{
	struct scsi_req sr;
	struct cdb_10 *c10p;
	int err;

	bzero((char *)&sr, sizeof(sr));

	c10p = (struct cdb_10 *)&sr.sr_cdb;
	c10p->c10_opcode = 0x3C;
	c10p->c10_len = alloc_len;

	sr.sr_addr = (char *)avail_len;
	sr.sr_dma_max = alloc_len > 4 ? 0 : alloc_len;
	sr.sr_ioto = 5;
	sr.sr_dma_dir = SR_DMA_RD;

	err = ioctl(fd, SDIOCSRQ, &sr);

	*tvp = sr.sr_exec_time;

	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}

int do_writebuffer(int fd, int alloc_len, struct timeval *tvp,
	struct esense_reply *erp)
{
	struct scsi_req sr;
	struct cdb_10 *c10p;
	int err;

	bzero((char *)&sr, sizeof(sr));

	c10p = (struct cdb_10 *)&sr.sr_cdb;
	c10p->c10_opcode = 0x3B;
	c10p->c10_len = alloc_len;

	sr.sr_addr = NULL;
	sr.sr_dma_max = 0;
	sr.sr_ioto = 5;
	sr.sr_dma_dir = SR_DMA_WR;

	err = ioctl(fd, SDIOCSRQ, &sr);

	*tvp = sr.sr_exec_time;

	*erp = sr.sr_esense;
	return err | sr.sr_io_status;
}
#endif


void sprint_er(char *string, struct esense_reply *erp)
{
#ifdef i386
	unsigned int errinfo;
#endif
	sprintf(string,   "  Valid           : %d\n", erp->er_ibvalid);
	sprintf(string, "%s  ErCode          : 0x%x\n", string,
		erp->er_class << (4+erp->er_code));
	sprintf(string, "%s  Segment         : %d\n", string, erp->er_segment);
	sprintf(string, "%s  ILI             : %d\n", string, erp->er_badlen);
	sprintf(string, "%s  SenseKey        : 0x%x\n", string, erp->er_sensekey);
#ifdef i386
	errinfo = erp->er_info2 << 16 + erp->er_info1 << 8 + erp->er_info0;
	sprintf(string, "%s  Info            : 0x%x%x\n", string,
		erp->er_info3, errinfo);
#else
	sprintf(string, "%s  Info            : 0x%x%x\n", string,
		erp->er_infomsb, erp->er_info);
#endif
	sprintf(string, "%s  AddSenseLength  : %d\n", string, erp->er_addsenselen);
	sprintf(string, "%s  CmdInfo         : %d\n", string, erp->er_rsvd8);
	sprintf(string, "%s  AddSenseCode    : 0x%x\n", string,
		erp->er_addsensecode);
	sprintf(string, "%s  AddSenseCodeQual: 0x%x\n", string, erp->er_qualifier);

	return;
}

#if 0
void fprint_er(int fd, struct esense_reply *erp)
{
	fprintf(fd,   "  Valid           : %d\n", erp->er_ibvalid);
	fprintf(fd, "  ErCode          : 0x%x\n",
		erp->er_class<<4+erp->er_code);
	fprintf(fd, "  Segment         : %d\n",  erp->er_segment);
	fprintf(fd, "  ILI             : %d\n",  erp->er_badlen);
	fprintf(fd, "  SenseKey        : 0x%x\n",  erp->er_sensekey);
	fprintf(fd, "  Info            : 0x%x%x\n", erp->er_infomsb,
		erp->er_info);
	fprintf(fd, "  AddSenseLength  : %d\n",  erp->er_addsenselen);
	fprintf(fd, "  CmdInfo         : %d\n",  erp->er_rsvd8);
	fprintf(fd, "  AddSenseCode    : 0x%x\n", erp->er_addsensecode);
	fprintf(fd, "  AddSenseCodeQual: 0x%x\n",  erp->er_qualifier);

	return;
}
#endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.