home *** CD-ROM | disk | FTP | other *** search
/ Computer Installation Guide - Dragon Clan Series / CD2.iso / Audio / CDDA2WAV / ASPILIB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-14  |  24.3 KB  |  1,003 lines

  1. /*
  2.  * ASPILIB - communication with Advanced SCSI Programming Interface
  3.  *
  4.  * REFERENCES:
  5.  *   Ansi X3T9.2-86 (SCSI-2)
  6.  *   ASW1250 - Adaptec Spad-SRB/SCO
  7.  *   Adaptec - ASPI DOS Specification
  8.  *           Adaptec
  9.  *           Literature Departement - MS/40
  10.  *           691 South Milpitas Blvd.
  11.  *           Milpitas, CA 95035
  12.  *
  13.  * NOTES ON COMMAND LINKING:
  14.  *   In order to use Command-Linking (might be supported by some targets)
  15.  *   a chain of SRBs has to be build via array 'lpSrbLink'.
  16.  *   Flag SRBF_LINKED has to be set to one in all requests (except the last
  17.  *   one).
  18.  *   Same applies to the Link bit in the corresponding CDBs.
  19.  *
  20.  *   PS (from Adaptec!): It is strongly recommended that you do not use SCSI
  21.  *   linking (unless you have no other choice). (reason: too less targets as
  22.  *   well as host adapters do support these features!)
  23.  *
  24.  * COMPILING:
  25.  *   cl -c -Gy -O1 aspilib.c
  26.  *
  27.  * LAST CHANGE:
  28.  *   17.10.93 - first version,    OK
  29.  *   08.11.93 - supplement for POST support,  OK
  30.  *   22.12.93 - redesign and rewrite for SRB-oriented funktions,  OK
  31.  */
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36.  
  37. #include "uti.h"
  38. #include "aspidef.h"
  39.  
  40. #pragma warning (disable:4704) // inline assembly is valid!
  41.  
  42.  
  43. #if 0
  44.  
  45. /*
  46.  * SCSIREQ - SCSI request descriptor
  47.  *
  48.  * ELEMENTS:
  49.  *   datasent: Amount of data bytes actually transferred via SCSI bus.
  50.  *     There ought to be operating systems, not being able to determine this
  51.  *     value.
  52.  *     In this case 'datasent' is identical to 'ScsiRequest''s
  53.  *     parameter 'cbData'.
  54.  *   sensesent: amount of sense data received from target in 'sensebuf'.
  55.  *   sensebuf: buffer to receive target send SENSE data.
  56.  */
  57. typedef struct SCSIREQ {
  58.   long datasent;
  59.   long sensesent;
  60.   char sensebuf [CBSENSEBUF];
  61.  
  62.   /* internal */
  63.   u_char target_sts;
  64.   u_char driver_sts;
  65.   int fd;
  66.   long req;
  67. } SCSIREQ;
  68.  
  69. SCSIREQ *ScsiOpen (char *name);
  70. int ScsiClose (SCSIREQ *scsireq);
  71. int ScsiRequest (SCSIREQ *scsireq, int direction, u_char *pCmd, int cbCmd,
  72.   u_char *pData, int cbData);
  73. int ScsiTestUnitReady (SCSIREQ *scsireq);
  74. int ScsiInquire (SCSIREQ *scsireq, char *pBuf, int cbBuf);
  75. #endif
  76.  
  77.  
  78. typedef struct ASPIERROR {
  79.   int errorCode;
  80.   char *szError;
  81. } ASPIERROR;
  82.  
  83. static ASPIERROR aspiError [] = {
  84.   {ASPIE_SUCCESS,    "Ok"},
  85.   {ASPIE_PENDING,    "Pending SCSI request"},
  86.   {ASPIE_FATAL,     "Undefined ASPI error"},
  87.   {ASPIE_INVDEVICEID,    "SCSI device not installed"},
  88.   {ASPIE_INVSCSIREQ,    "Invalid SCSI request"},
  89.   {ASPIE_INVADAPTERID,    "Invalid host adapter number"},
  90.   {ASPIE_HOSTABORT,    "ASPI request aborted by host"},
  91.   {ASPIE_SELTIMEOUT,    "Selection timeout"},
  92.   {ASPIE_DATAOVERRUN,    "Data over-run/under-run"},
  93.   {ASPIE_BUSFREE,    "Unexpected bus free"},
  94.   {ASPIE_PHASEERR,    "Target bus phase sequence failure"},
  95.   {ASPIE_TARGETBUSY,    "Specified target is busy"},
  96.   {ASPIE_RESERVATION,    "Reservation conflict"},
  97.   {ASPIE_UNITNOTREADY,    "Unit not ready"},
  98.   {ASPIE_MEDIUM,    "Medium error"},
  99.   {ASPIE_HARDWARE,    "Non-recoverable hardware failure"},
  100.   {ASPIE_ILLEGALREQ,    "Illegal request"},
  101.   {ASPIE_UNITATTENTION, "Unit attention"},
  102.   {ASPIE_DATAPROTECT,    "Medium is write protected"},
  103.   {ASPIE_BLANKCHECK,    "Encountered non blank data"},
  104.   {ASPIE_TARGETABORT,    "Command aborted by target"},
  105.   {ASPIE_VOLOVERFLOW,    "Volume overflow"},
  106.   {ASPIE_IOERROR,    "Unknown I/O error"},
  107.   {ASPIE_ENDOFMEDIUM,    "End of medium detected"},
  108.   {1, "<<Error>>"}
  109. };
  110.  
  111.  
  112. char *AspiGetErrorText (int errorCode)
  113. /*
  114.  * This function returns an error text corresponding to error code of
  115.  * ASPI functions.
  116.  *
  117.  * PARAMETERS:
  118.  *   errorCode: error code from one of the 'Aspi...' functions, which return
  119.  *   ASPIE_...
  120.  *
  121.  * RETURN:
  122.  *   pointer to a static error text.
  123.  */
  124. {
  125.   ASPIERROR *pAspiError = aspiError;
  126.  
  127.   while (pAspiError -> errorCode < 1 && pAspiError -> errorCode != errorCode)
  128.     pAspiError++;
  129.   return pAspiError -> szError;
  130. }
  131.  
  132.  
  133. BOOL AspiInit (VOID)
  134. /*
  135.  * This function initialises internal structures of the ASPI library and
  136.  * opens the interface to the resident SCSI manager.
  137.  *
  138.  * RETURN:
  139.  *   FALSE: ASPI interface has not been installed,
  140.  *   TRUE: ASPI interface has been opened correctly.
  141.  */
  142. {
  143.   static char NEAR *szScsiMgr = "SCSIMGR$";
  144.  
  145. #ifndef TURBOC
  146.   _asm {
  147.     mov dx,szScsiMgr
  148.     mov ax,3D00h
  149.     int 21h
  150.     jc failed
  151.     mov bx,ax
  152.  
  153.     mov cx,4
  154.     lea dx,word ptr fnAspi
  155.     mov ax,4402h
  156.     int 21h
  157.  
  158.     mov ah,3Eh
  159.     int 21h
  160.   }
  161. #else
  162. asm    mov dx,szScsiMgr
  163. asm    mov ax,3D00h
  164. asm    int 21h
  165. asm    jc failed
  166. asm    mov bx,ax
  167.  
  168. asm    mov cx,4
  169. asm    lea dx,word ptr fnAspi
  170. asm    mov ax,4402h
  171. asm    int 21h
  172.  
  173. asm    mov ah,3Eh
  174. asm    int 21h
  175. #endif
  176. failed:
  177.  
  178.   return fnAspi != NULL;
  179. }
  180.  
  181.  
  182. int AspiPostRequest (SRB *srb)
  183. {
  184.   fnAspi (srb);
  185.   return srb -> bStatus;
  186. }
  187.  
  188.  
  189. int AspiGetError (SRB *srb)
  190. /*
  191.  * This function determines the error state from a SRB.
  192.  *
  193.  * PARAMETERS:
  194.  *   srb: pointer to the SRB handled by 'AspiRequest' or 'AspiRequestWait.'
  195.  *
  196.  * RETURN:
  197.  *   On successful operation on 'srb' ASPIE_SUCCESS, values smaller zero
  198.  *   indicate an ASPIE_... error.
  199.  *
  200.  * BUGS:
  201.  *   the calling function is in charge to ensure the value of 'bStatus'
  202.  *   in SRB is no more SRBS_PENDING.
  203.  */
  204. {
  205.   BYTE *sense;
  206.   const SRB_IO *srbIo = (SRB_IO *)srb;
  207.  
  208.   switch (srb -> bStatus) {
  209.     case SRBS_PENDING: return ASPIE_PENDING;
  210.     case SRBS_COMPLETE: return ASPIE_SUCCESS;
  211.     case SRBS_ABORTED: return ASPIE_HOSTABORT;
  212.  
  213.     case SRBS_ERROR:
  214.       if (srb -> bCmd != SRBC_EXECIO) return ASPIE_FATAL;
  215.  
  216.       /* SCSI-IO-Error: more data about error? */
  217.       switch (srbIo -> bAdapterStatus) {
  218.  
  219.     case 0x00: /* not an error by adapter, anything from target? */
  220.       switch (srbIo -> bTargetStatus) {
  221.  
  222.         case 0x02: /* target said Check Sense */
  223.           sense = srbIo -> cdb.raw + srbIo -> cCdb;
  224.           switch (sense [2] & 0x0F) {
  225.         case 0x00:
  226.           if (sense [2] & 0x40) return ASPIE_ENDOFMEDIUM;
  227.           break;
  228.         case 0x01: return ASPIE_SUCCESS; /* recovered error */
  229.         case 0x02: return ASPIE_UNITNOTREADY;
  230.         case 0x03: return ASPIE_MEDIUM;
  231.         case 0x04: return ASPIE_HARDWARE;
  232.         case 0x05: return ASPIE_ILLEGALREQ;
  233.         case 0x06: return ASPIE_UNITATTENTION;
  234.         case 0x07: return ASPIE_DATAPROTECT;
  235.         case 0x08: return ASPIE_BLANKCHECK;
  236.         case 0x0B: return ASPIE_TARGETABORT;
  237.         case 0x0D: return ASPIE_VOLOVERFLOW;
  238.           }
  239.           break;
  240.  
  241.         case 0x08: return ASPIE_TARGETBUSY;
  242.         case 0x18: return ASPIE_RESERVATION;
  243.       }
  244.       break;
  245.  
  246.     case 0x11: return ASPIE_SELTIMEOUT;
  247.     case 0x12: return ASPIE_DATAOVERRUN;
  248.     case 0x13: return ASPIE_BUSFREE;
  249.     case 0x14: return ASPIE_PHASEERR;
  250.       }
  251.       return ASPIE_IOERROR;
  252.  
  253.     case SRBS_INVSCSIREQ: return ASPIE_INVSCSIREQ;
  254.     case SRBS_INVADAPTERID: return ASPIE_INVADAPTERID;
  255.     case SRBS_INVDEVICEID: return ASPIE_INVDEVICEID;
  256.   }
  257.  
  258.   return ASPIE_FATAL;
  259. }
  260.  
  261.  
  262. int AspiRequestWait (SRB *srb)
  263. {
  264.   int cnt = 10;
  265.  
  266.   fnAspi (srb);
  267.   while (cnt--) while (not srb -> bStatus);
  268.  
  269.   return AspiGetError (srb);
  270. }
  271.  
  272.  
  273. int AspiAbortRequest (SRB *srb)
  274. /*
  275.  * this function aborts a command, which was initiated by 'AspiRequest'.
  276.  *
  277.  * PARAMETERS:
  278.  *   srb: pointer to command to be aborted.
  279.  *
  280.  * RETURN:
  281.  *   On success: ASPIE_SUCCESS, values smaller zero indicate an error.
  282.  *
  283.  * BUGS:
  284.  *   We don't know for sure, whether the command has been aborted.
  285.  *   command state might be SRBS_COMPLETE already when calling
  286.  *   'AspiAbortRequest'.
  287.  *
  288.  *   Function 'AspiAbortRequest' may not called from inside a POST-Routine.
  289.  */
  290. {
  291.   SRB_ABORT srbAbort;
  292.  
  293.   memzero (srbAbort);
  294.  
  295.   srbAbort.srb.bCmd = SRBC_ABORTSRB;
  296.   srbAbort.srb.bAdapterId = srb -> bAdapterId;
  297.   srbAbort.lpSrbToAbort = srb;
  298.  
  299.   return AspiRequestWait (&srbAbort.srb);
  300. }
  301.  
  302.  
  303. int AspiHostAdapterInquiry (int adapterId, HA_INQUIRY *pInquiry)
  304. /*
  305.  * this function returns informations on an installed host adapter.
  306.  *
  307.  * PARAMETERS:
  308.  *   adapterId: number of adapter to query. The first adapter has number zero.
  309.  *   pInquiry: pointer on adapter information structure to fill.
  310.  *
  311.  * RETURN:
  312.  *   on succes: ASPIE_SUCCESS, values smaller zero indicate errors.
  313.  *
  314.  * BUGS:
  315.  *   'adapterId' has to have valid adapter numbers.
  316.  *   Invalid values in 'adapterId' do not return SRBS_COMPLETE in
  317.  *   'srb'.'bStatus'
  318.  */
  319. {
  320.   int i;
  321.   int err;
  322.   SRB_INQUIRY srbInquiry;
  323.  
  324.   memzero (srbInquiry);
  325.  
  326.   srbInquiry.srb.bCmd = SRBC_INQUIRY;
  327.   srbInquiry.srb.bAdapterId = (BYTE)adapterId;
  328.  
  329.   err = AspiRequestWait (&srbInquiry.srb);
  330.   if (err) return err;
  331.  
  332.   for (i=0; i<16; i++) {
  333.     pInquiry -> szManager [i] = srbInquiry.achManager [i];
  334.     pInquiry -> szAdapter [i] = srbInquiry.achAdapter [i];
  335.   }
  336.  
  337.   pInquiry -> szManager [16] = '\0';
  338.   pInquiry -> szAdapter [16] = '\0';
  339.   pInquiry -> nAdapters = srbInquiry.nAdapters;
  340.   pInquiry -> adapterTargetId = srbInquiry.adapterTargetId;
  341.  
  342.   return ASPIE_SUCCESS;
  343. }
  344.  
  345.  
  346. int AspiGetDeviceType (int adapterId, int targetId, int lun)
  347. /*
  348.  * This function returns the device type of a connected SCSI device.
  349.  *
  350.  * PARAMETERS:
  351.  *   adapterId: Number of adapter.
  352.  *   targetId: SCSI ID of device to inquire.
  353.  *   lun: Logical Unit Number of device to inquire.
  354.  *
  355.  * RETURN:
  356.  *   If greater or equal zero: the SCSI Device Type Code (DTC_...) of
  357.  *   target 'targetId'. Values smaller zero indicate an error.
  358.  *
  359.  * BUGS:
  360.  *   This function returns correct information only about devices, having
  361.  *   been connected at boot time. Devices turned on after booting
  362.  *   are not supported and return an error code smaller zero.
  363.  */
  364. {
  365.   int err;
  366.   SRB_GETDEVTYPE srbGetDevType;
  367.  
  368.   memzero (srbGetDevType);
  369.  
  370.   srbGetDevType.srb.bCmd = SRBC_GETDEVTYPE;
  371.   srbGetDevType.srb.bAdapterId = (BYTE)adapterId;
  372.   srbGetDevType.bTargetId = (BYTE)targetId;
  373.   srbGetDevType.bLun = (BYTE)lun;
  374.  
  375.   err = AspiRequestWait (&srbGetDevType.srb);
  376.   if (err) return err;
  377.  
  378.   return srbGetDevType.bDeviceTypeCode;
  379. }
  380.  
  381.  
  382. int AspiResetDevice (int adapterId, int targetId, int lun)
  383. /*
  384.  * This function resets an scsi device.
  385.  *
  386.  * PARAMETERS:
  387.  *   adapterId, targetId, lun: address of device to reset.
  388.  *
  389.  * RETURN:
  390.  *   On success:ASPIE_SUCCESS, Values smaller zero indicate an error.
  391.  */
  392. {
  393.   SRB_RESET srbReset;
  394.  
  395.   memzero (srbReset);
  396.   srbReset.srb.bCmd = SRBC_RESETDEVICE;
  397.   srbReset.srb.bAdapterId = (BYTE)adapterId;
  398.   srbReset.bTargetId = (BYTE)targetId;
  399.   srbReset.bLun = (BYTE)lun;
  400.  
  401.   return AspiRequestWait (&srbReset.srb);
  402. }
  403.  
  404.  
  405. int AspiGetDiskDriveInfo (int adapterId, int targetId, int lun,
  406.   HA_DRIVEINFO *pDriveInfo)
  407. /*
  408.  * This function returns informations about disk for usage by DOS and BIOS.
  409.  *
  410.  * PARAMETERS:
  411.  *   adapterId, targetId, lun: address of device to query.
  412.  *   pDriveInfo: pointer to result of query structure.
  413.  *
  414.  * RETURN:
  415.  *   On success:ASPIE_SUCCESS, Values smaller zero indicate an error.
  416.  */
  417. {
  418.   SRB_GETDRIVEINFO srbGetDriveInfo;
  419.  
  420.   memzero (srbGetDriveInfo);
  421.  
  422.   srbGetDriveInfo.srb.bCmd = SRBC_GETDRIVEINFO;
  423.   srbGetDriveInfo.srb.bAdapterId = (BYTE)adapterId;
  424.   srbGetDriveInfo.bTargetId = (BYTE)targetId;
  425.   srbGetDriveInfo.bLun = (BYTE)lun;
  426.  
  427.   *pDriveInfo = srbGetDriveInfo.driveInfo;
  428.  
  429.   return AspiRequestWait (&srbGetDriveInfo.srb);
  430. }
  431.  
  432.  
  433. int ScsiTestUnitReady (int adapterId, int targetId, int lun)
  434. /*
  435.  * This function checks the accessability of an scsi device.
  436.  *
  437.  * PARAMETERS:
  438.  *   adapterId, targetId, lun:  address of device to check.
  439.  *
  440.  * RETURN:
  441.  *   If device is ready: ASPIE_SUCCESS, Values smaller zero indicate
  442.  *   an error.
  443.  */
  444. {
  445.   SRB_IO srbIo;
  446.  
  447.   memzero (srbIo);
  448.  
  449.   srbIo.srb.bCmd = SRBC_EXECIO;
  450.   srbIo.srb.bAdapterId = (BYTE)adapterId;
  451.   srbIo.srb.bFlags = SRBF_NOXFER;
  452.   srbIo.bTargetId = (BYTE)targetId;
  453.   srbIo.bLun = (BYTE)lun;
  454.   srbIo.lpData = NULL;
  455.   srbIo.cbData = 0;
  456.   srbIo.cbSense = 14;
  457.   srbIo.cCdb = 6;
  458.  
  459.   return AspiRequestWait (&srbIo.srb);
  460. }
  461.  
  462.  
  463. int ScsiInquiry (int adapterId, int targetId, int lun, SCSI_INQUIRY *pInquiry)
  464. /*
  465.  * This function requests SCSI Inquire data from an scsi device.
  466.  *
  467.  * PARAMETERS:
  468.  *   adapterId, targetId, lun: address of device to inquire.
  469.  *   pInquiry: pointer to structure to fill in inquire data.
  470.  *
  471.  * RETURN:
  472.  *   On success: ASPIE_SUCCESS, Values smaller zero indicate an error.
  473.  */
  474. {
  475.   SRB_IO srbIo;
  476.  
  477.   memzero (srbIo);
  478.  
  479.   srbIo.srb.bCmd = SRBC_EXECIO;
  480.   srbIo.srb.bAdapterId = (BYTE)adapterId;
  481.   srbIo.srb.bFlags = SRBF_READ;
  482.   srbIo.bTargetId = (BYTE)targetId;
  483.   srbIo.bLun = (BYTE)lun;
  484.   srbIo.lpData = pInquiry;
  485.   srbIo.cbData = sizeof (SCSI_INQUIRY);
  486.   srbIo.cbSense = 14;
  487.   srbIo.cCdb = 6;
  488.   srbIo.cdb.inquiry.bCmd = 0x12;
  489.   srbIo.cdb.inquiry.bLun = lun;
  490.   srbIo.cdb.inquiry.bLen = sizeof (SCSI_INQUIRY);
  491.  
  492.   return AspiRequestWait (&srbIo.srb);
  493. }
  494.  
  495.  
  496. int ScsiRead (int adapterId, int targetId, int lun, VOID *pBuffer,
  497.   int firstBlock, int nBlocks)
  498. {
  499.   SRB_IO srbIo;
  500.  
  501.   srbIo.srb.bCmd = SRBC_EXECIO;
  502.   srbIo.srb.bAdapterId = adapterId;
  503.   srbIo.srb.bFlags = SRBF_READ;
  504.   srbIo.bTargetId = targetId;
  505.   srbIo.bLun = lun;
  506.   srbIo.cbData = nBlocks * 512;
  507.   srbIo.cbSense = 14;
  508.   srbIo.lpData = pBuffer;
  509.   srbIo.cCdb = 6;
  510.   srbIo.cdb.cdb6.bCmd = 0x08;
  511.   srbIo.cdb.cdb6.bLun = lun;
  512.   srbIo.cdb.cdb6.b2 = (BYTE)(firstBlock >> 8);
  513.   srbIo.cdb.cdb6.b3 = (BYTE)firstBlock;
  514.   srbIo.cdb.cdb6.b4 = (BYTE)nBlocks;
  515.   srbIo.cdb.cdb6.b5 = 0;
  516.  
  517.   return AspiRequestWait (&srbIo.srb);
  518. }
  519.  
  520.  
  521. int ScsiWrite (int adapterId, int targetId, int lun, VOID *pBuffer,
  522.   int firstBlock, int nBlocks)
  523. {
  524.   SRB_IO srbIo;
  525.  
  526.   srbIo.srb.bCmd = SRBC_EXECIO;
  527.   srbIo.srb.bAdapterId = adapterId;
  528.   srbIo.srb.bFlags = SRBF_WRITE;
  529.   srbIo.bTargetId = targetId;
  530.   srbIo.bLun = lun;
  531.   srbIo.cbData = nBlocks * 512;
  532.   srbIo.cbSense = 14;
  533.   srbIo.lpData = pBuffer;
  534.   srbIo.cCdb = 6;
  535.   srbIo.cdb.cdb6.bCmd = 0x0A;
  536.   srbIo.cdb.cdb6.bLun = lun;
  537.   srbIo.cdb.cdb6.b2 = (BYTE)(firstBlock >> 8);
  538.   srbIo.cdb.cdb6.b3 = (BYTE)firstBlock;
  539.   srbIo.cdb.cdb6.b4 = (BYTE)nBlocks;
  540.   srbIo.cdb.cdb6.b5 = 0;
  541.  
  542.   return AspiRequestWait (&srbIo.srb);
  543. }
  544.  
  545. #ifdef TEST_READ
  546.  
  547. VOID StopUnit (int targetId)
  548. {
  549.   int err;
  550.   SRB_IO srbIo;
  551.  
  552.   memzero (srbIo);
  553.  
  554.   srbIo.srb.bCmd = SRBC_EXECIO;
  555.   srbIo.srb.bAdapterId = 0;
  556.   srbIo.srb.bFlags = SRBF_READ;
  557.   srbIo.bTargetId = (BYTE)targetId;
  558.   srbIo.bLun = 0;
  559.   srbIo.lpData = NULL;
  560.   srbIo.cbData = 0;
  561.   srbIo.cbSense = 14;
  562.   srbIo.cCdb = 6;
  563.   srbIo.cdb.ssunit.bCmd = 0x1B;
  564.   srbIo.cdb.ssunit.fImmed = 0;
  565.   srbIo.cdb.ssunit.fStart = 0;
  566.  
  567.   err = AspiRequestWait (&srbIo.srb);
  568.   printf ("start stop = %s\n", AspiGetErrorText (err));
  569. }
  570.  
  571.  
  572. BYTE buffer [1024];
  573.  
  574. int main (int argc, char *argv [])
  575. {
  576.   int i;
  577.   int err;
  578.  
  579.   if (not AspiInit ()) {
  580.     puts ("ASPI interface not installed.");
  581.     return 1;
  582.   }
  583.  
  584.   memset (buffer, 0xAA, sizeof (buffer));
  585.   err = AspiResetDevice (0, 2, 0);
  586.   puts (AspiGetErrorText (err));
  587.  
  588.   getch ();
  589.   err = ScsiRead (0, 2, 0, buffer, 1, 1);
  590.   if (err) {
  591.     puts (AspiGetErrorText (err));
  592.   }
  593.  
  594.   for (i=0; i<128; i+=16) {
  595.     int j;
  596.  
  597.     for (j=0; j<16; j++)
  598.       printf (" %.2X", buffer [i+j]);
  599.     printf ("\n");
  600.   }
  601.  
  602.   StopUnit (2);
  603.  
  604.   return 0;
  605. }
  606.  
  607.  
  608. #endif
  609.  
  610. #ifdef TEST_DUMP
  611.  
  612. int cxLabel = 30;
  613.  
  614. VOID Label (char *szLabel, char *szFormat, ...)
  615. {
  616.   int x = -4;
  617.  
  618.   if (szLabel) {
  619.     x = strlen (szLabel);
  620.     if (x > cxLabel) szLabel [cxLabel] = '\0';
  621.     fputs (szLabel, stdout);
  622.   }
  623.  
  624.   if (szLabel) {
  625.     putchar (' ');
  626.     while (x++ < cxLabel) putchar ('.');
  627.     fputs (" : ", stdout);
  628.   } else {
  629.     while (x++ < cxLabel) putchar (' ');
  630.   }
  631.  
  632.   if (szFormat) {
  633.     vprintf (szFormat, (va_list)(&szFormat+1));
  634.     putchar ('\n');
  635.   }
  636. }
  637.  
  638.  
  639. typedef struct DEVICEINFO {
  640.   int adapterId;
  641.   int targetId;
  642.   int lun;
  643.   SCSI_INQUIRY scsiInquiry;
  644. } DEVICEINFO;
  645.  
  646. #define CDEVICEINFO 16
  647. DEVICEINFO deviceInfo [CDEVICEINFO];
  648. int nDeviceInfos = 0;
  649.  
  650.  
  651. VOID GetDeviceInfo (int nAdapters)
  652. {
  653.   int err;
  654.   int adapterId;
  655.   int targetId;
  656.   int lun;
  657.   DEVICEINFO *pDeviceInfo = deviceInfo;
  658.  
  659.   printf ("\nList of SCSI devices:\n");
  660.   printf (" Id     Vendor    Product name      Revision\n");
  661.  
  662.   for (adapterId=0; adapterId<nAdapters; adapterId++) {
  663.     for (targetId=0; targetId<8; targetId++) {
  664.       for (lun=0; lun<8; lun++) {
  665.     err = AspiGetDeviceType (adapterId, targetId, lun);
  666.     if (err == ASPIE_INVDEVICEID) continue;
  667.  
  668.     err = ScsiInquiry (adapterId, targetId, lun,
  669.       &pDeviceInfo -> scsiInquiry);
  670.     printf (" %d:%d:%d  ", adapterId, targetId, lun);
  671.     if (err < 0) {
  672.       puts (AspiGetErrorText (err));
  673.       continue;
  674.     }
  675.  
  676.     pDeviceInfo -> adapterId = adapterId;
  677.     pDeviceInfo -> targetId = targetId;
  678.     pDeviceInfo -> lun = lun;
  679.     printf ("%.8s  %.16s  %.4s\n", pDeviceInfo -> scsiInquiry.achVendor,
  680.       pDeviceInfo -> scsiInquiry.achProduct,
  681.       pDeviceInfo -> scsiInquiry.achRevision);
  682.  
  683.     pDeviceInfo++;
  684.     nDeviceInfos++;
  685.     if (nDeviceInfos == CDEVICEINFO) return;
  686.       }
  687.     }
  688.   }
  689. }
  690.  
  691.  
  692. VOID PrintDeviceTypeCode (int deviceTypeCode)
  693. {
  694.   static char *szDeviceTypeCode [] = {
  695.     "Disk", "Tape", "Printer", "CPU", "Worm", "CD-ROM", "Scanner",
  696.     "Optical", "Jukebox", "Comm", "Prepress", "Prepress", "Unknown"};
  697.  
  698.   if (deviceTypeCode > 12)
  699.     deviceTypeCode = 12;
  700.   printf ("%-8s ", szDeviceTypeCode [deviceTypeCode]);
  701. }
  702.  
  703.  
  704. VOID PrintYesNo (BOOL fYes)
  705. {
  706.   printf ("%-8s ", fYes ? "Yes" : "No");
  707. }
  708.  
  709.  
  710. int main (VOID)
  711. {
  712.   int i;
  713.   int err;
  714.   HA_INQUIRY haInquiry;
  715.  
  716.   if (not AspiInit ()) {
  717.     puts ("ASPI interface not installed.");
  718.     return 1;
  719.   }
  720.  
  721.   err = AspiHostAdapterInquiry (0, &haInquiry);
  722.   if (err) {
  723.     printf ("adapter0: %s\n", AspiGetErrorText (err));
  724.   }
  725.  
  726.   printf ("Host adapter information:\n");
  727.   Label (" Number of adapters", "%d", haInquiry.nAdapters);
  728.   Label (" Type of adapter 0", "%s", haInquiry.szAdapter);
  729.   Label (" SCSI manager 0", "%s", haInquiry.szManager);
  730.   Label (" Adapter 0 target-id", "%d", haInquiry.adapterTargetId);
  731.  
  732.   GetDeviceInfo (haInquiry.nAdapters);
  733.   cxLabel = 22; /* reicht für 6 Geräte */
  734.  
  735.   printf ("\nDevice information:");
  736.   Label ("\n SCSI-Id", NULL);
  737.   for (i=0; i<nDeviceInfos; i++)
  738.     printf ("%d:%d:%d    ", deviceInfo [i].adapterId,
  739.       deviceInfo [i].bTargetId, deviceInfo [i].bLun);
  740.  
  741.   Label ("\n Manufacturer", NULL);
  742.   for (i=0; i<nDeviceInfos; i++)
  743.     printf ("%.8s ", deviceInfo [i].scsiInquiry.achVendor);
  744.  
  745.   Label ("\n Device type", NULL);
  746.   for (i=0; i<nDeviceInfos; i++)
  747.     PrintDeviceTypeCode (deviceInfo [i].scsiInquiry.deviceTypeCode);
  748.  
  749.   Label ("\n Removable medium", NULL);
  750.   for (i=0; i<nDeviceInfos; i++)
  751.     PrintYesNo (deviceInfo [i].scsiInquiry.fRemovableMedium);
  752.  
  753.   Label ("\n SCSI version", NULL);
  754.   for (i=0; i<nDeviceInfos; i++)
  755.     printf ("SCSI-%d   ", deviceInfo [i].scsiInquiry.scsiVersion);
  756.  
  757.   Label ("\n Command queueing", NULL);
  758.   for (i=0; i<nDeviceInfos; i++)
  759.     PrintYesNo (deviceInfo [i].scsiInquiry.fCmdQueueing);
  760.  
  761.   Label ("\n Linked commands", NULL);
  762.   for (i=0; i<nDeviceInfos; i++)
  763.   PrintYesNo (deviceInfo [i].scsiInquiry.fLinkedCommands);
  764.  
  765.   Label ("\n Sync transfer", NULL);
  766.   for (i=0; i<nDeviceInfos; i++)
  767.   PrintYesNo (deviceInfo [i].scsiInquiry.fSynchronousTransfer);
  768.  
  769.   printf ("\n");
  770.  
  771.   return 0;
  772. }
  773.  
  774. #endif
  775.  
  776.  
  777. #ifdef TEST_BENCH
  778.  
  779. #include <dos.h>
  780.  
  781. static volatile DWORD FAR *sysTime = (DWORD FAR *)0x0040006CL;
  782. DWORD _startTime;
  783. BYTE buffer [64L*1024];
  784.  
  785.  
  786. VOID ResetTimer (VOID)
  787. {
  788.   _disable ();
  789.   _startTime = *sysTime;
  790.   _enable ();
  791.   while (_startTime == *sysTime);
  792.   _startTime++;
  793. }
  794.  
  795.  
  796. DWORD GetTimer (VOID)
  797. /*
  798.  * Returns passed time since last call of 'ResetTimer' in milli seconds.
  799.  */
  800. {
  801.   DWORD stopTime;
  802.  
  803.   _disable ();
  804.   stopTime = *sysTime;
  805.   _enable ();
  806.   return (stopTime - _startTime) * 28125 / 512;
  807. }
  808.  
  809.  
  810. /* size of read buffer in kbytes */
  811. #define TEST_SIZE 64
  812.  
  813. VOID ScsiReadBlocks (int adapterId, int targetId, int kByteStart, int kBytes)
  814. {
  815.   int block;
  816.  
  817.   block = kByteStart * 2;
  818.   while (kBytes > TEST_SIZE) {
  819.     ScsiRead (adapterId, targetId, /*lun*/ 0, buffer, block, TEST_SIZE*2);
  820.     block += TEST_SIZE*2;
  821.     kBytes -= TEST_SIZE;
  822.   }
  823.   if (kBytes > 0)
  824.     ScsiRead (adapterId, targetId, /*lun*/ 0, buffer, block, kBytes*2);
  825. }
  826.  
  827.  
  828. int main (int argc, char *argv [])
  829. {
  830.   int i;
  831.   int err;
  832.   DWORD time;
  833.   int deviceType;
  834.   int adapterId = 0;
  835.   int targetId = 0;
  836.   SCSI_INQUIRY scsiInquiry;
  837.  
  838.   if (not AspiInit ()) {
  839.     puts ("ASPI interface not installed.");
  840.     return 1;
  841.   }
  842.  
  843.   if (argc == 2) {
  844.     targetId = argv [1][0] - '0';
  845.     if (targetId < 0 || targetId > 7) targetId = 0;
  846.   }
  847.  
  848.   deviceType = AspiGetDeviceType (adapterId, targetId, /*lun*/ 0);
  849.   if (deviceType != DTC_DISK && deviceType != DTC_CDROM) {
  850.     printf ("Target %d:%d:0 is not a disk drive.\n", adapterId, targetId);
  851.     return 1;
  852.   }
  853.   err = ScsiInquiry (adapterId, targetId, /*lun*/0, &scsiInquiry);
  854.   if (err) {
  855.     puts (AspiGetErrorText (err));
  856.     return 1;
  857.   }
  858.   printf ("Device %d:%d:%d ........... : %.8s %.16s %.4s\n",
  859.     adapterId, targetId, /*lun*/0, scsiInquiry.achVendor,
  860.     scsiInquiry.achProduct, scsiInquiry.achRevision);
  861.  
  862.   err = ScsiTestUnitReady (adapterId, targetId, /*lun*/0);
  863.   if (err) {
  864.     puts (AspiGetErrorText (err));
  865.     return 1;
  866.   }
  867.  
  868.   /* flush disk cache */
  869.   ScsiReadBlocks (adapterId, targetId, 0, 1024);
  870.  
  871.   ResetTimer ();
  872.   ScsiReadBlocks (adapterId, targetId, 1024, 10240);
  873.   time = GetTimer () + 1;
  874.   printf ("Time to read 10MB ...... : %ld ms\n", time);
  875.   printf ("Real performance ....... : %ld KB/s\n",  10240L * 1000 / time);
  876.  
  877.   for (i=1; i<=4; i++) {
  878.     int j;
  879.  
  880.     ScsiReadBlocks (adapterId, targetId, 0, i*16);
  881.     ScsiReadBlocks (adapterId, targetId, 0, i*16);
  882.     ResetTimer ();
  883.     for (j=0; j<99; j++)
  884.       ScsiReadBlocks (adapterId, targetId, 0, i*16);
  885.     time = GetTimer ();
  886.     printf ("Read from cache %dKB ... : ", i*16);
  887.     if (time == 0) {
  888.       printf ("oops\n");
  889.     } else {
  890.       printf ("%ld KB/s\n", 99 * i * 16L * 1000 / time);
  891.     }
  892.   }
  893.  
  894.   return 0;
  895. }
  896.  
  897. #endif
  898.  
  899.  
  900. #ifdef TEST_PATCHSQ
  901.  
  902. typedef struct BOOTSECTOR {
  903.   BYTE bsJump [3];
  904.   char bsOemName [8];
  905.   WORD wBytesPerSector;
  906.   BYTE bSectorsPerCluster;
  907.   WORD wReservedSectors;
  908.   BYTE nFats;
  909.   WORD nRootDirEntries;
  910.   WORD wTotalSectors;
  911.   BYTE bMediaDescriptor;
  912.   WORD wSectorsPerFAT;
  913.   WORD wSectorsPerTrack;
  914.   WORD nHeads;
  915.   DWORD dwHiddenSectors;
  916.   /* extended ... */
  917.   DWORD dwTotalSectors;
  918.   WORD wPhysicalDriveNumber;
  919.   BYTE bExtBoot29h;
  920.   DWORD dwVolumeID;
  921.   char strVolumeLable [11];
  922.   char strFileSysType [7];
  923.   char _reserved [451];
  924. } BOOTSECTOR;
  925.  
  926. BOOTSECTOR bootSector;
  927.  
  928.  
  929. int main (int argc, char *argv [])
  930. {
  931.   int i;
  932.   int targetId;
  933.   int err;
  934.   SCSI_INQUIRY scsiInquiry;
  935.  
  936.   if (not AspiInit ()) {
  937.     puts ("ASPI interface not installed.");
  938.     return 1;
  939.   }
  940.  
  941.   for (targetId=0; targetId<8; targetId++) {
  942.     if (AspiGetDeviceType (0, targetId, 0) != DTC_DISK) continue;
  943.     err = ScsiInquiry (0, targetId, 0, &scsiInquiry);
  944.     if (err) {
  945.       puts (AspiGetErrorText (err));
  946.       continue;
  947.     }
  948.     if (strncmp (scsiInquiry.achVendor, "SyQuest ", 8) == 0) break;
  949.   }
  950.   if (targetId == 8) {
  951.     puts ("No SyQuest drive connected to adapter0.");
  952.     return 1;
  953.   }
  954.  
  955.   fputs ("target", stdout);
  956.   fputc (targetId + '0', stdout);
  957.   puts (": reading boot sector...");
  958.   memset (&bootSector, 0xFF, sizeof (bootSector));
  959.   err = ScsiRead (0, targetId, 0, &bootSector, 17, 1);
  960.   if (err) {
  961.     puts (AspiGetErrorText (err));
  962.     return 2;
  963.   }
  964.  
  965.   if (bootSector.wSectorsPerTrack == 32 &&
  966.       bootSector.nHeads == 64 &&
  967.       bootSector.dwHiddenSectors == 32) {
  968.     puts ("This cartridge is already patched.");
  969.     return 0;
  970.   }
  971.  
  972.   if (bootSector.wSectorsPerTrack != 17 ||
  973.       bootSector.nHeads != 8 ||
  974.       bootSector.dwHiddenSectors != 17) {
  975.     puts ("Valid boot sector not found.");
  976.     return 3;
  977.   }
  978.  
  979.   fputs ("Boot sector written by: ", stdout);
  980.   for (i=0; i<8; i++) fputc (bootSector.bsOemName [i], stdout);
  981.   fputc ('\n', stdout);
  982.  
  983.   puts ("Cartridge needs patching. Type 'y' to patch cartridge:");
  984.   i = fgetc (stdin);
  985.   if (i == 'y' || i == 'Y' || i == 'j' || i == 'J') {
  986.     bootSector.wSectorsPerTrack = 32;
  987.     bootSector.nHeads = 64;
  988.     bootSector.dwHiddenSectors = 32;
  989.     err = ScsiWrite (0, targetId, 0, &bootSector, 17, 1);
  990.     if (err) {
  991.       puts (AspiGetErrorText (err));
  992.       return 4;
  993.     }
  994.     puts ("Cartridge successfully patched.");
  995.   } else {
  996.     puts ("Cartridge not modified.");
  997.   }
  998.  
  999.   return 0;
  1000. }
  1001.  
  1002. #endif
  1003.