home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / TAPE / scsiaspi.c < prev    next >
C/C++ Source or Header  |  1992-10-05  |  8KB  |  395 lines

  1. /*****************************************************************************
  2.  * $Id: scsiaspi.c,v 1.3 1992/10/04 22:15:38 ak Exp $
  3.  *****************************************************************************
  4.  * $Log: scsiaspi.c,v $
  5.  * Revision 1.3  1992/10/04  22:15:38  ak
  6.  * Updated DOS version, scsi_name() was missing. There seems to be some
  7.  * request for GTAK10x (DOS) with DAT.
  8.  *
  9.  * Revision 1.2  1992/09/02  19:05:35  ak
  10.  * Version 2.0
  11.  * - EMX version
  12.  * - AIX version
  13.  * - SCSI-2 commands
  14.  * - ADD Driver
  15.  * - blocksize support
  16.  *
  17.  * Revision 1.1.1.1  1992/01/06  20:27:32  ak
  18.  * Interface now based on ST01 and ASPI.
  19.  * AHA_DRVR no longer supported.
  20.  * Files reorganized.
  21.  *
  22.  * Revision 1.1  1992/01/06  20:27:30  ak
  23.  * Initial revision
  24.  *
  25.  *****************************************************************************/
  26.  
  27. static char *rcsid = "$Id: scsiaspi.c,v 1.3 1992/10/04 22:15:38 ak Exp $";
  28.  
  29. #include <stdio.h>
  30. #include <stdarg.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33.  
  34. #ifdef OS2
  35.  #error "ASPI interface not usable for OS/2"
  36. #endif
  37.  
  38. #include <io.h>
  39. #include <fcntl.h>
  40. #include <dos.h>
  41.  
  42. #include "aspi.h"
  43. #include "scsi.h"
  44.  
  45. static int        trace;
  46. static int        handle;
  47. static void        (_far * api)(SRB _far *);
  48. SenseMode        senseMode = SenseKey;
  49. static long        blocksize = 512;
  50.  
  51. #define ASPI(srb)    (*api)(srb)
  52.  
  53.  
  54. static void
  55. fatal(char *msg, ...)
  56. {
  57.     va_list ap;
  58.     fprintf(stderr, "Fatal SCSI error: ");
  59.     va_start(ap, msg);
  60.     vfprintf(stderr, msg, ap);
  61.     va_end (ap);
  62.     fprintf(stderr, "\n");
  63.     exit (2);
  64. }
  65.  
  66. static void
  67. command(SRB *srb)
  68. {
  69.     int i;
  70.     printf("SCSI op:");
  71.     for (i = 0; i < srb->u.cmd.cdb_len; ++i)
  72.         printf(" %02X", srb->u.cmd.cdb_st[i]);
  73.     printf("\n");
  74. }
  75.  
  76. static void
  77. status(SRB *srb)
  78. {
  79.     int i;
  80.     printf("SCSI status:");
  81.     for (i = 0; i < srb->u.cmd.sense_len; ++i) {
  82.         if (i && (i % 16) == 0)
  83.             printf("\n            ");
  84.         printf(" %02X", srb->u.cmd.cdb_st[srb->u.cmd.cdb_len + i]);
  85.     }
  86.     printf("\n");
  87. }
  88.  
  89. void
  90. scsi_init(void)
  91. {
  92.     union REGS    r;
  93.     struct SREGS    sr;
  94.     char        *cp;
  95.  
  96. #ifndef OS2
  97.     if (_osmajor >= 10)
  98.         fatal("Cannot use SCSI interface in OS/2 DOS mode\n");
  99. #endif
  100.  
  101.     if ((handle = open("SCSIMGR$", O_BINARY|O_RDWR)) < 0)
  102.         fatal("SCSI Manager not found\n");
  103.  
  104.     r.x.ax = 0x4402;            /* Ioctl Read */
  105.     sr.ds  = FP_SEG((void _far *)&api);
  106.     r.x.dx = FP_OFF((void _far *)&api);
  107.     r.x.cx = 4;
  108.     r.x.bx = handle;
  109.     intdosx(&r, &r, &sr);
  110.     if (r.x.cflag)
  111.         fatal("SCSI Manager Ioctl failure\n");
  112.  
  113.     if ((cp = getenv("TAPEMODE")) != NULL)
  114.         senseMode = atoi(cp);
  115. }
  116.  
  117. void
  118. scsi_file(int fd)
  119. {
  120.     scsi_init();
  121. }
  122.  
  123. void
  124. scsi_name(char *name)
  125. {
  126.     scsi_init();
  127. }
  128.  
  129. void
  130. scsi_term(void)
  131. {
  132.     close(handle);
  133. }
  134.  
  135. void
  136. scsi_trace(int level)
  137. {
  138.     trace = level;
  139. }
  140.  
  141. void *
  142. scsi_alloc(void)
  143. {
  144.     void *p = malloc(sizeof(SRB));
  145.     if (p == NULL)
  146.         fatal("No memory for SCSI Request Block\n");
  147. }
  148.  
  149. void
  150. scsi_free(void *p)
  151. {
  152.     free(p);
  153. }
  154.  
  155. int
  156. scsi_start(void *ctrl, 
  157.     int target, int lun,
  158.     void *cdb, int cdb_len, int sense_len,
  159.     void far *data, long data_len,
  160.     int readflag)
  161. {
  162.     SRB *srb = ctrl;
  163.  
  164.     srb->cmd        = SRB_Command;
  165.     srb->status        = SRB_Busy;
  166.     srb->ha_num        = 0;
  167.     srb->flags        = data_len ? readflag ? SRB_Read : SRB_Write
  168.                            : SRB_NoTransfer;
  169.     srb->u.cmd.target    = target;
  170.     srb->u.cmd.lun        = lun;
  171.     srb->u.cmd.data_len    = data_len;
  172.     srb->u.cmd.sense_len    = sense_len;
  173.     srb->u.cmd.data_ptr    = data;
  174.     srb->u.cmd.link_ptr    = 0;
  175.     srb->u.cmd.cdb_len    = cdb_len;
  176.     memcpy(srb->u.cmd.cdb_st+0, cdb, cdb_len);
  177.     memset(srb->u.cmd.cdb_st+cdb_len, 0, sense_len);
  178.  
  179.     if (trace)
  180.         command(srb);
  181.  
  182.     ASPI(srb);
  183.  
  184.     if (trace >= 2)
  185.         printf("SRB status: %02X\n", srb->status);
  186.  
  187.     switch (srb->status) {
  188.     case SRB_Busy:
  189.     case SRB_Error:
  190.         return ComeAgain;
  191.     case SRB_Done:
  192.         return NoError;
  193.     default:
  194.         return DriverError + srb->status;
  195.     }
  196. }
  197.  
  198. int
  199. scsi_wait(void *ctrl, void *sense, int wait)
  200. {
  201.     SRB *srb = ctrl;
  202.     int i, slen, ret;
  203.     unsigned char *sptr;
  204.  
  205.     for (;;) {
  206.         if (trace >= 2)
  207.             printf("SRB status: %02X\n", srb->status);
  208.  
  209.         switch (srb->status) {
  210.         case SRB_Busy:
  211.             if (wait) {
  212.                 union REGS r;
  213.  
  214.                 /* DESQview - give up timeslice */
  215.                 r.x.ax = 0x1000;
  216.                 int86(0x15, &r, &r);
  217.  
  218.                 /* Windows 3+ - give up timeslice */
  219.                 r.x.ax = 0x1680;
  220.                 int86(0x2F, &r, &r);
  221.  
  222.                 continue;
  223.             }
  224.             return ComeAgain;
  225.         case SRB_Error:
  226.             break;
  227.         case SRB_Done:
  228.             return NoError;
  229.         default:
  230.             return DriverError + srb->status;
  231.         }
  232.         break;
  233.     }
  234.  
  235.     if (srb->u.cmd.ha_status) {
  236.         if (trace)
  237.             printf("SCSI host adapter error: %02X\n",
  238.                 srb->u.cmd.ha_status);
  239.         return HostError + srb->u.cmd.ha_status;
  240.     }
  241.     switch (srb->u.cmd.target_status) {
  242.     case GoodStatus:
  243.         return NoError;
  244.     case CheckStatus:
  245.         break;
  246.     default:
  247.         if (trace)
  248.             printf("SCSI completion status: %02X\n",
  249.                 srb->u.cmd.target_status);
  250.         return StatusError + srb->u.cmd.target_status;
  251.     }
  252.  
  253.     slen = srb->u.cmd.sense_len ? srb->u.cmd.sense_len : 14;
  254.     memcpy(sense, srb->u.cmd.cdb_st + srb->u.cmd.cdb_len, slen);
  255.  
  256.     if (trace)
  257.         status(srb);
  258.  
  259.     sptr = (unsigned char *)sense;
  260.     if ((sptr[0] & 0x7E) != 0x70)
  261.         return ExtendedError + (sptr[0] & 0x7F);
  262.     if (srb->u.cmd.sense_len <= 2)
  263.         return UnknownError;
  264.     return SenseKey + (sptr[2] & 0x0F);
  265. }
  266.  
  267. int
  268. scsi_cmd(int target, int lun,
  269.     void *cdb, int cdb_len,    void *sense, int sense_len,
  270.     void far *data, long data_len,
  271.     int readflag)
  272. {
  273.     SRB srb;
  274.     int ret;
  275.  
  276.     ret = scsi_start(&srb,
  277.             target, lun,
  278.             cdb, cdb_len, sense_len,
  279.             data, data_len,
  280.             readflag);
  281.     while (ret == ComeAgain)
  282.         ret = scsi_wait(&srb, sense, 1);
  283.     return ret;
  284. }
  285.  
  286. int
  287. scsi_reset(int target, int lun, int bus)
  288. {
  289.     SRB srb;
  290.  
  291.     srb.cmd            = SRB_Reset;
  292.     srb.status        = SRB_Busy;
  293.     srb.ha_num        = 0;
  294.     srb.flags        = SRB_NoTransfer;
  295.     srb.u.res.target    = target;
  296.     srb.u.res.lun        = lun;
  297.  
  298.     ASPI(&srb);
  299.  
  300.     for (;;) {
  301.         switch (srb.status) {
  302.         case SRB_Busy:
  303.             continue;
  304.         case SRB_Done:
  305.             return NoError;
  306.         default:
  307.             return DriverError + srb.status;
  308.         }
  309.     }
  310. }
  311.  
  312. long
  313. scsi_get_blocksize(int target, int lun)
  314. {
  315.     return blocksize;
  316. }
  317.  
  318. long
  319. scsi_set_blocksize(int target, int lun, long size)
  320. {
  321.     long old = blocksize;
  322.     blocksize = size;
  323.     return old;
  324. }
  325.  
  326. int
  327. scsi_set_trace(int level)
  328. {
  329.     int old = trace;
  330.     trace = level;
  331.     return old;
  332. }
  333.  
  334. char *
  335. scsi_error(int code)
  336. {
  337.     static char text[80];
  338.     static ErrorTable driverTab[] = {
  339.         SRB_Aborted,    "Command aborted",
  340.         SRB_BadAbort,    "Could not abort",
  341.         SRB_InvalidCmd,    "Invalid ASPI request",
  342.         SRB_InvalidHA,    "Invalid host adapter",
  343.         SRB_BadDevice,    "Device not installed",
  344.         -1
  345.     };
  346.     static ErrorTable hostTab[] = {
  347.             /* Adaptec 154x host adapter status */
  348.         SRB_NoError,        "No error",
  349.         SRB_Timeout,        "Selection timeout",
  350.         SRB_DataLength,        "Data length error",
  351.         SRB_BusFree,        "Unexpected bus free",
  352.         SRB_BusSequence,    "Target bus sequence failure",
  353.         -1
  354.     };
  355.  
  356.     if (code == 0)
  357.         return "No error";
  358.     if (code == ComeAgain)
  359.         return "Busy";
  360.     switch (ErrorClass(code)) {
  361.     case SenseKey:
  362.         return senseTab[code & 0x0F];
  363.     case ExtendedError:
  364.         switch (senseMode) {
  365.         case TDC3600:
  366.             sprintf(text, "Error code: %s",
  367.                 find_error(tdc3600ercd, ErrorCode(code)));
  368.             break;
  369.         default:
  370.             sprintf(text, "Additional sense code: %02X",
  371.                 ErrorCode(code));
  372.         }
  373.         break;
  374.     case StatusError:
  375.         sprintf(text, "Target status: %s",
  376.             find_error(targetStatusTab, ErrorCode(code)));
  377.         break;
  378.     case DriverError:
  379.         sprintf(text, "Driver error: %s",
  380.             find_error(driverTab, ErrorCode(code)));
  381.         break;
  382.     case SystemError:
  383.         sprintf(text, "System error: %u", ErrorCode(code));
  384.         break;
  385.     case HostError:
  386.         sprintf(text, "Host adapter error: %s",
  387.             find_error(hostTab, ErrorCode(code)));
  388.         break;
  389.     default:
  390.         sprintf(text, "Other error: %04X", code);
  391.         break;
  392.     }
  393.     return text;
  394. }
  395.