home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer) / NeXT_Developer-3.3.iso / NextDeveloper / Examples / UNIX / SCSI_CD / scsi_commands.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-10  |  7.9 KB  |  362 lines

  1. /*
  2.  * scsi_commands.c: scsi command functions
  3.  *
  4.  * History
  5.  * -------
  6.  * 02-Feb-93    Erik Kay at NeXT
  7.  *    i386 support
  8.  * Tue Sep  3 15:00:13 PDT 1991 James C. Lee at NeXT
  9.  *  Created (copied a lot of data structures & functions calls from
  10.  *   perftest.c by Mike DeMoney)
  11.  */
  12.  
  13. #import "scsi_commands.h"
  14. #import <sys/time.h>
  15. #import <bsd/dev/disk.h>
  16. #import <bsd/dev/scsireg.h>
  17. #import <stdio.h>
  18. #import <libc.h>
  19. #import <stdlib.h>
  20.  
  21.  
  22. void fatal(const char *msg, ...)
  23. {
  24.     va_list ap;
  25.  
  26.     va_start(ap, msg);
  27. /*    fprintf(stderr, "%s: ", progname);*/
  28.     vfprintf(stderr, msg, ap);
  29.     fprintf(stderr, "\n");
  30.     va_end(ap);
  31.  
  32.     exit(1);
  33. }
  34.  
  35. inline int is_pow2(int i)
  36. {
  37.     return (i & (i - 1)) == 0;
  38. }
  39.  
  40. int do_inquiry(int fd, struct inquiry_reply *irp, struct esense_reply *erp)
  41. {
  42.     struct scsi_req sr;
  43.     struct cdb_6 *c6p;
  44.     int err;
  45.  
  46.     bzero((char *)&sr, sizeof(sr));
  47.  
  48.     c6p = (struct cdb_6 *)&sr.sr_cdb;
  49.     c6p->c6_opcode = C6OP_INQUIRY;
  50.     c6p->c6_len = sizeof(*irp);
  51.  
  52.     sr.sr_addr = (char *)irp;
  53.     sr.sr_dma_max = sizeof(*irp);
  54.     sr.sr_ioto = 5;
  55.     sr.sr_dma_dir = SR_DMA_RD;
  56.  
  57.     err = ioctl(fd, SDIOCSRQ, &sr);
  58.     *erp = sr.sr_esense;
  59.     return err | sr.sr_io_status;
  60. }
  61.  
  62. int do_testunitready(int fd, struct timeval *tvp, struct esense_reply *erp)
  63. {
  64.     struct scsi_req sr;
  65.     struct cdb_6 *c6p;
  66.     int err;
  67.  
  68.     bzero((char *)&sr, sizeof(sr));
  69.  
  70.     c6p = (struct cdb_6 *)&sr.sr_cdb;
  71.     c6p->c6_opcode = C6OP_TESTRDY;
  72.  
  73.     sr.sr_addr = NULL;
  74.     sr.sr_dma_max = 0;
  75.     sr.sr_ioto = 5;
  76.     sr.sr_dma_dir = SR_DMA_RD;
  77.  
  78.     err = ioctl(fd, SDIOCSRQ, &sr);
  79.  
  80.     *tvp = sr.sr_exec_time;
  81.  
  82.     *erp = sr.sr_esense;
  83.     return err | sr.sr_io_status;
  84. }
  85.  
  86. int do_modesense(int fd, struct mode_sense_reply *msrp, int page,
  87.     struct esense_reply *erp)
  88. {
  89.     struct scsi_req sr;
  90.     struct mode_sense_cmd *mscp;
  91.     int err;
  92.  
  93.     bzero((char *)&sr, sizeof(sr));
  94.  
  95.     mscp = (struct mode_sense_cmd *)&sr.sr_cdb;
  96.     mscp->msc_opcode = C6OP_MODESENSE;
  97.     mscp->msc_pcf = 0;    /* report current values */
  98.     mscp->msc_page = page;
  99.     mscp->msc_len = sizeof(*msrp);
  100.  
  101.     sr.sr_addr = (char *)msrp;
  102.     sr.sr_dma_max = sizeof(*msrp);
  103.     /*
  104.      * Extend timeout so Quantum drive works with test.
  105.      */
  106.     sr.sr_ioto = 50;
  107.     sr.sr_dma_dir = SR_DMA_RD;
  108.  
  109.     err = ioctl(fd, SDIOCSRQ, &sr);
  110.  
  111.     printf("sr.sr_io_status: %d\n", sr.sr_io_status);
  112.     *erp = sr.sr_esense;
  113.     return err | sr.sr_io_status;
  114. }
  115.  
  116. int do_readcapacity(int fd, struct capacity_reply *crp,
  117.     struct esense_reply *erp)
  118. {
  119.     struct scsi_req sr;
  120.     struct cdb_10 *c10p;
  121.     int err;
  122.  
  123.     bzero((char *)&sr, sizeof(sr.sr_cdb));
  124.  
  125.     c10p = (struct cdb_10 *)&sr.sr_cdb;
  126.     c10p->c10_opcode = C10OP_READCAPACITY;
  127.  
  128.     sr.sr_addr = (char *)crp;
  129.     sr.sr_dma_max = sizeof(*crp);
  130.     sr.sr_ioto = 5;
  131.     sr.sr_dma_dir = SR_DMA_RD;
  132.  
  133.     err = ioctl(fd, SDIOCSRQ, &sr);
  134.     *erp = sr.sr_esense;
  135.     return err | sr.sr_io_status;
  136. }
  137.  
  138. int do_seek(int fd, int lba, struct timeval *tvp, struct esense_reply *erp)
  139. {
  140.     struct scsi_req sr;
  141.     struct cdb_6 *c6p;
  142.     int err;
  143.  
  144.     bzero((char *)&sr, sizeof(sr));
  145.  
  146.     c6p = (struct cdb_6 *)&sr.sr_cdb;
  147.     c6p->c6_opcode = C6OP_SEEK;
  148. #ifdef i386
  149.     if (lba > 0) {
  150.         c6p->c6_lba0 = lba & 0xFF;
  151.         c6p->c6_lba1 = (lba >> 8) & 0xFF;
  152.         c6p->c6_lba2 = (lba >> 16) & 0xFF;
  153.     } else
  154.         c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
  155. #else
  156.     c6p->c6_lba = lba;
  157. #endif
  158.  
  159.     sr.sr_addr = 0;
  160.     sr.sr_dma_max = 0;    /* don't really do I/O to memory */
  161.     sr.sr_ioto = 5;
  162.     sr.sr_dma_dir = SR_DMA_RD;
  163.  
  164.     err = ioctl(fd, SDIOCSRQ, &sr);
  165.  
  166.     *tvp = sr.sr_exec_time;
  167.  
  168.     *erp = sr.sr_esense;
  169.     return err | sr.sr_io_status;
  170. }
  171.  
  172. int do_read(int fd, int lba, int nblks, struct timeval *tvp,
  173.     struct esense_reply *erp)
  174. {
  175.     struct scsi_req sr;
  176.     struct cdb_6 *c6p;
  177.     int err;
  178.  
  179.     if (nblks > 256)
  180.         fatal("Too many blocks for read: %d", nblks);
  181.     if (nblks == 256)
  182.         nblks = 0;
  183.  
  184.     bzero((char *)&sr, sizeof(sr));
  185.  
  186.     c6p = (struct cdb_6 *)&sr.sr_cdb;
  187.     c6p->c6_opcode = C6OP_READ;
  188. #ifdef i386
  189.     if (lba > 0) {
  190.         c6p->c6_lba0 = lba & 0xFF;
  191.         c6p->c6_lba1 = (lba >> 8) & 0xFF;
  192.         c6p->c6_lba2 = (lba >> 16) & 0xFF;
  193.     } else
  194.         c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
  195. #else
  196.     c6p->c6_lba = lba;
  197. #endif
  198.     c6p->c6_len = nblks;
  199.  
  200.     sr.sr_addr = NULL;
  201.     sr.sr_dma_max = 0;    /* don't really do I/O to memory */
  202.     sr.sr_ioto = 5;
  203.     sr.sr_dma_dir = SR_DMA_RD;
  204.  
  205.     err = ioctl(fd, SDIOCSRQ, &sr);
  206.  
  207.     *tvp = sr.sr_exec_time;
  208.  
  209.     if (sr.sr_dma_xfr != 0)
  210.         fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
  211.  
  212.     *erp = sr.sr_esense;
  213.     return err | sr.sr_io_status;
  214. }
  215.  
  216. int do_write(int fd, int lba, int nblks, struct timeval *tvp,
  217.     struct esense_reply *erp)
  218. {
  219.     struct scsi_req sr;
  220.     struct cdb_6 *c6p;
  221.     int err;
  222.  
  223.     if (nblks > 256)
  224.         fatal("Too many blocks for read: %d", nblks);
  225.     if (nblks == 256)
  226.         nblks = 0;
  227.  
  228.     bzero((char *)&sr, sizeof(sr));
  229.  
  230.     c6p = (struct cdb_6 *)&sr.sr_cdb;
  231.     c6p->c6_opcode = C6OP_WRITE;
  232. #ifdef i386
  233.     if (lba > 0) {
  234.         c6p->c6_lba0 = lba & 0xFF;
  235.         c6p->c6_lba1 = (lba >> 8) & 0xFF;
  236.         c6p->c6_lba2 = (lba >> 16) & 0xFF;
  237.     } else
  238.         c6p->c6_lba0 = c6p->c6_lba1 = c6p->c6_lba2 = 0;
  239. #else
  240.     c6p->c6_lba = lba;
  241. #endif
  242.     c6p->c6_len = nblks;
  243.  
  244.     sr.sr_addr = NULL;
  245.     sr.sr_dma_max = 0;    /* don't really do I/O to memory */
  246.     sr.sr_ioto = 5;
  247.     sr.sr_dma_dir = SR_DMA_WR;
  248.  
  249.     err = ioctl(fd, SDIOCSRQ, &sr);
  250.  
  251.     *tvp = sr.sr_exec_time;
  252.  
  253.     if (sr.sr_dma_xfr != 0)
  254.         fatal("scsi driver did transfer: %d", sr.sr_dma_xfr);
  255.  
  256.     *erp = sr.sr_esense;
  257.     return err | sr.sr_io_status;
  258. }
  259.  
  260. #if 0
  261. int do_readbuffer(int fd, int alloc_len, int *avail_len, struct timeval *tvp,
  262.     struct esense_reply *erp)
  263. {
  264.     struct scsi_req sr;
  265.     struct cdb_10 *c10p;
  266.     int err;
  267.  
  268.     bzero((char *)&sr, sizeof(sr));
  269.  
  270.     c10p = (struct cdb_10 *)&sr.sr_cdb;
  271.     c10p->c10_opcode = 0x3C;
  272.     c10p->c10_len = alloc_len;
  273.  
  274.     sr.sr_addr = (char *)avail_len;
  275.     sr.sr_dma_max = alloc_len > 4 ? 0 : alloc_len;
  276.     sr.sr_ioto = 5;
  277.     sr.sr_dma_dir = SR_DMA_RD;
  278.  
  279.     err = ioctl(fd, SDIOCSRQ, &sr);
  280.  
  281.     *tvp = sr.sr_exec_time;
  282.  
  283.     *erp = sr.sr_esense;
  284.     return err | sr.sr_io_status;
  285. }
  286.  
  287. int do_writebuffer(int fd, int alloc_len, struct timeval *tvp,
  288.     struct esense_reply *erp)
  289. {
  290.     struct scsi_req sr;
  291.     struct cdb_10 *c10p;
  292.     int err;
  293.  
  294.     bzero((char *)&sr, sizeof(sr));
  295.  
  296.     c10p = (struct cdb_10 *)&sr.sr_cdb;
  297.     c10p->c10_opcode = 0x3B;
  298.     c10p->c10_len = alloc_len;
  299.  
  300.     sr.sr_addr = NULL;
  301.     sr.sr_dma_max = 0;
  302.     sr.sr_ioto = 5;
  303.     sr.sr_dma_dir = SR_DMA_WR;
  304.  
  305.     err = ioctl(fd, SDIOCSRQ, &sr);
  306.  
  307.     *tvp = sr.sr_exec_time;
  308.  
  309.     *erp = sr.sr_esense;
  310.     return err | sr.sr_io_status;
  311. }
  312. #endif
  313.  
  314.  
  315. void sprint_er(char *string, struct esense_reply *erp)
  316. {
  317. #ifdef i386
  318.     unsigned int errinfo;
  319. #endif
  320.     sprintf(string,   "  Valid           : %d\n", erp->er_ibvalid);
  321.     sprintf(string, "%s  ErCode          : 0x%x\n", string,
  322.         erp->er_class << (4+erp->er_code));
  323.     sprintf(string, "%s  Segment         : %d\n", string, erp->er_segment);
  324.     sprintf(string, "%s  ILI             : %d\n", string, erp->er_badlen);
  325.     sprintf(string, "%s  SenseKey        : 0x%x\n", string, erp->er_sensekey);
  326. #ifdef i386
  327.     errinfo = erp->er_info2 << 16 + erp->er_info1 << 8 + erp->er_info0;
  328.     sprintf(string, "%s  Info            : 0x%x%x\n", string,
  329.         erp->er_info3, errinfo);
  330. #else
  331.     sprintf(string, "%s  Info            : 0x%x%x\n", string,
  332.         erp->er_infomsb, erp->er_info);
  333. #endif
  334.     sprintf(string, "%s  AddSenseLength  : %d\n", string, erp->er_addsenselen);
  335.     sprintf(string, "%s  CmdInfo         : %d\n", string, erp->er_rsvd8);
  336.     sprintf(string, "%s  AddSenseCode    : 0x%x\n", string,
  337.         erp->er_addsensecode);
  338.     sprintf(string, "%s  AddSenseCodeQual: 0x%x\n", string, erp->er_qualifier);
  339.  
  340.     return;
  341. }
  342.  
  343. #if 0
  344. void fprint_er(int fd, struct esense_reply *erp)
  345. {
  346.     fprintf(fd,   "  Valid           : %d\n", erp->er_ibvalid);
  347.     fprintf(fd, "  ErCode          : 0x%x\n",
  348.         erp->er_class<<4+erp->er_code);
  349.     fprintf(fd, "  Segment         : %d\n",  erp->er_segment);
  350.     fprintf(fd, "  ILI             : %d\n",  erp->er_badlen);
  351.     fprintf(fd, "  SenseKey        : 0x%x\n",  erp->er_sensekey);
  352.     fprintf(fd, "  Info            : 0x%x%x\n", erp->er_infomsb,
  353.         erp->er_info);
  354.     fprintf(fd, "  AddSenseLength  : %d\n",  erp->er_addsenselen);
  355.     fprintf(fd, "  CmdInfo         : %d\n",  erp->er_rsvd8);
  356.     fprintf(fd, "  AddSenseCode    : 0x%x\n", erp->er_addsensecode);
  357.     fprintf(fd, "  AddSenseCodeQual: 0x%x\n",  erp->er_qualifier);
  358.  
  359.     return;
  360. }
  361. #endif
  362.