home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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
-