|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.