home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / scsipg.zip / SCSITEST.ZIP / SCSITEST.C < prev    next >
C/C++ Source or Header  |  1994-05-18  |  99KB  |  2,769 lines

  1. /*********************************
  2. **  Include files               **
  3. *********************************/
  4. #pragma pack(1)         /* Pack the structures */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #define INCL_DOS
  10. #include <OS2.h>
  11.  
  12. /*****************************************************************************/
  13. /*                                                                           */
  14. /* TSB                                                                       */
  15. /*                                                                           */
  16. /* This is the Termination Status Block - it tells how an SCB completed      */
  17. /* and what went wrong when it dodn't.  I've not had a lot of luck           */
  18. /* interpreting these things.  They are documented in the SCSI adapter       */
  19. /* tech reference.                                                           */
  20. /*                                                                           */
  21. /*****************************************************************************/
  22. typedef struct tsb_def {
  23.    USHORT  SCB_status;
  24.    USHORT  retry_counts;
  25.    ULONG   residual_buffer_byte_count;
  26.    ULONG   residual_buffer_address;
  27.    USHORT  additional_status_length;
  28.    unsigned int   bit0                    : 1;
  29.    unsigned int   SCSI_status_code        : 4;
  30.    unsigned int   bit5                    : 1;
  31.    unsigned int   bit6                    : 1;
  32.    unsigned int   bit7                    : 1;
  33.    unsigned int   command_status          : 8;
  34.    unsigned int   device_error_code       : 8;
  35.    unsigned int   command_error_code      : 8;
  36.    USHORT  error_modifier;
  37.    USHORT  cache_info;
  38.    ULONG   last_SCB_address_processed;
  39.    } tsb_type;
  40.  
  41. /*****************************************************************************/
  42. /*                                                                           */
  43. /* Inquiry block                                                             */
  44. /*                                                                           */
  45. /* This is the structure returned by a device in response to an Inquiry      */
  46. /* SCSI command.  It gives some interesting information like device type     */
  47. /* (cdrom, tape, etc), is the media removeable, what standards the device    */
  48. /* conforms to and generally, the device's manufacturer and model numbers.   */
  49. /*                                                                           */
  50. /*****************************************************************************/
  51. typedef struct inq_def {
  52.    UCHAR   device_type;
  53.    UCHAR   removable;
  54.    UCHAR   standards;
  55.    UCHAR   reserved;
  56.    UCHAR   extra_length;
  57.    UCHAR   res[3];
  58.    CHAR    manufacturer[2];
  59.    } inq_type;
  60.  
  61.  
  62. /*****************************************************************************/
  63. /*                                                                           */
  64. /* SCBs                                                                      */
  65. /*                                                                           */
  66. /* These are the definitions of the SCSI Command Block used by the IBM SCSI  */
  67. /* adapters.  There are 2 blocks defined - the standard SCB and the 'long'   */
  68. /* SCB that has a SCSI command imbedded in it.  These are documented in the  */
  69. /* IBM SCSI adapter technical references.                                    */
  70. /*                                                                           */
  71. /*****************************************************************************/
  72. typedef struct scb_def {
  73.    USHORT   command;                /* Command to the SCSI card              */
  74.    USHORT   enable;                 /* Control bits to modify the command    */
  75.    ULONG    block_number;           /* Starting block in SCSI device         */
  76.    UCHAR * _Seg16 system_buf_adr;   /* Buffer address to transfer to/from    */
  77.    ULONG    system_buf_cnt;         /* How big is the system buffer in bytes */
  78.    tsb_type * _Seg16 tsb_adr;          /* Where to store the TSB                */
  79.    UCHAR * _Seg16 chain_adr;        /* Where the next SCB is                 */
  80.    USHORT   block_count;            /* How many blocks to transfer           */
  81.    USHORT   block_length;           /* How big is a block in bytes           */
  82.    } scb_type;
  83.  
  84. typedef struct long_scb_def {
  85.    USHORT   command;                /* Command to the SCSI card              */
  86.    USHORT   enable;                 /* Control bits to modify the command    */
  87.    UCHAR    cmd_len;                /* How long is the SCSI command in bytes */
  88.    UCHAR    reserved1;              /* Reserved space                        */
  89.    USHORT   reserved2;              /* Reserved space                        */
  90.    UCHAR * _Seg16 system_buf_adr;   /* Buffer address to transfer to/from    */
  91.    ULONG    system_buf_cnt;         /* How big is the system buffer in bytes */
  92.    tsb_type * _Seg16 tsb_adr;          /* Where to store the TSB                */
  93.    UCHAR * _Seg16 chain_adr;        /* Pointer to next SCB                   */
  94.    UCHAR    scsi_cmd[12];           /* The imbedded SCSI command (6-12 bytes)*/
  95.    } long_scb_type;
  96.  
  97.  
  98. /*****************************************************************************/
  99. /*                                                                           */
  100. /* SCB Headers                                                               */
  101. /*                                                                           */
  102. /* These are the definitions of the SCB Headers as described in the OEMBASE  */
  103. /* document.  There are 2 blocks defined - one for the standard SCB and one  */
  104. /* for the 'long' scb.                                                       */
  105. /*                                                                           */
  106. /*****************************************************************************/
  107. typedef struct scb_hdr_def {
  108.    USHORT    reserved1;                 /* Reserved space                    */
  109.    char     * _Seg16 next_scb_hdr;      /* Ptr to next SCB hdr - never used  */
  110.    USHORT    reserved2;                 /* Reserved space                    */
  111.    USHORT    reserved3;                 /* Reserved space                    */
  112.    tsb_type * _Seg16 tsb_adr;           /* Pointer to TSB                    */
  113.    USHORT    reserved4;                 /* Reserved space                    */
  114.    scb_type  scb;                       /* The 'short' SCB itself            */
  115.    } scb_hdr_type;
  116.  
  117. typedef struct long_scb_hdr_def {
  118.    USHORT         reserved1;            /* Reserved space                    */
  119.    char          * _Seg16 next_scb_hdr; /* Ptr to next SCB hdr - never used  */
  120.    USHORT         reserved2;            /* Reserved space                    */
  121.    USHORT         reserved3;            /* Reserved space                    */
  122.    tsb_type      * _Seg16  tsb_adr;     /* Pointer to the TSB                */
  123.    USHORT         reserved4;            /* Reserved space                    */
  124.    long_scb_type  scb;                  /* The 'long' SCB                    */
  125.    } long_scb_hdr_type;
  126.  
  127.  
  128. /*****************************************************************************/
  129. /*                                                                           */
  130. /* Transfer SCB Parm buffer definition                                       */
  131. /*                                                                           */
  132. /* This block is passed to GENSCSI and then on to OS2SCSI via the Transfer   */
  133. /* SCB command.  It is documented in the OEMBASE document                    */
  134. /*                                                                           */
  135. /*****************************************************************************/
  136. typedef struct xfer_scb_def {
  137.    USHORT  dev_handle;          /* The device handle returned from Allocate  */
  138.    USHORT  sense_size;          /* How big is the sense buffer in bytes      */
  139.    ULONG   scb_phys;            /* Physical addr of SCB, GENSCSI will calc   */
  140.    scb_hdr_type * _Seg16 scb_header;   /* Virtual pointer to the SCB header         */
  141.    UCHAR   flags;               /* Is this a 'long' SCB or a 'short' SCB     */
  142.    } xfer_scb_type;
  143.  
  144. typedef struct xfer_lscb_def {
  145.    USHORT  dev_handle;          /* The device handle returned from Allocate  */
  146.    USHORT  sense_size;          /* How big is the sense buffer in bytes      */
  147.    ULONG   scb_phys;            /* Physical addr of SCB, GENSCSI will calc   */
  148.    long_scb_hdr_type * _Seg16 scb_header;   /* Virtual pointer to the SCB header         */
  149.    UCHAR   flags;               /* Is this a 'long' SCB or a 'short' SCB     */
  150.    } xfer_lscb_type;
  151.  
  152. /*****************************************************************************/
  153. /*                                                                           */
  154. /* Timeout block                                                             */
  155. /*                                                                           */
  156. /* This is the block sent and returned with the Set/Read device timeout      */
  157. /* commands.  I haven't found these commmands to be very reliable.           */
  158. /* but then again, I didn't check it out very well either.  There may be a   */
  159. /* bug here.                                                                 */
  160. /*                                                                           */
  161. /*****************************************************************************/
  162. typedef struct timeout_def {
  163.    USHORT    handle;
  164.    ULONG     timeout;
  165.    } timeout_type;
  166.  
  167. /*****************************************************************************/
  168. /*                                                                           */
  169. /* Device parms record                                                       */
  170. /*                                                                           */
  171. /* This is the block used in the Read Devcie Parms command.  As with the     */
  172. /* Timeout commands, I haven't been able to make these return useful info,   */
  173. /* but then again, I didn't check it out very well either.  There may be a   */
  174. /* bug here.                                                                 */
  175. /*                                                                           */
  176. /*****************************************************************************/
  177. typedef struct devparm_def {
  178.    USHORT    dev_key_index;
  179.    UCHAR     scb_arch_lvl;
  180.    UCHAR     adapter_index;
  181.    USHORT    device_flags;
  182.    UCHAR     lun;
  183.    UCHAR     pun;
  184.    } devparm_type;
  185.  
  186. int     reset_dev(USHORT handle);
  187. int     free_dev(USHORT handle);
  188. int     copy_all(USHORT handle);
  189. int     read_dev(USHORT handle);
  190. int     write_dev(USHORT handle);
  191. int     write_trk_dev(USHORT handle);
  192. int     dev_capacity(USHORT handle,int quiet);
  193. int     read_sense(USHORT handle);
  194. int     other(USHORT handle);
  195. int     start_drive(USHORT handle);
  196. int     timeout_dev(USHORT handle);
  197. int     time_read(USHORT handle);
  198. int     read_timeout_dev(USHORT handle);
  199. int     allocate_dev(USHORT *handle);
  200. int     read_dev_parms(USHORT handle);
  201. int     set_mode(USHORT handle);
  202. int     set_blk(USHORT handle);
  203. int     gen_cmd(USHORT handle);
  204. int     inquiry(USHORT handle);
  205. int     open_drawer(USHORT handle);
  206. int     close_drawer(USHORT handle);
  207. void    syntax(void);
  208. void    show_sense_x(void);
  209. int     get_toc(USHORT handle);
  210. void    write_toc(void);
  211. void    show_toc(void);
  212. int     get_toc_m(USHORT handle);
  213. void    write_toc_m(void);
  214. void    show_toc_m(void);
  215. void    show_sense(void);
  216. void    show_data(void);
  217. void    save_datab(void);
  218. void    save_data(void);
  219. void    show_tsb(void);
  220. void    show_tsb_x(void);
  221. void    count_dev(void);
  222. void    hexdisp(UCHAR *, int);
  223. void    clear_sense(void);
  224. ULONG   swap32(ULONG);
  225. USHORT  swap16(USHORT);
  226. FILE   *get_file(char *);
  227.  
  228. /*********************************
  229. **  Global variables            **
  230. *********************************/
  231. #define   SENSE_SIZE    32    /* How much sense data do we deal with */
  232. UCHAR     sense[SENSE_SIZE];  /* This is the sense buffer            */
  233. tsb_type  tsb;                /* The Termination Status Block        */
  234. UCHAR    *buffer;             /* The data buffer                     */
  235. int       bufsize      = 0;   /* How big is the buffer - start empty */
  236. HFILE     dh;                 /* The File Handle from DosOpen        */
  237. int       retval;             /* A generic Return Code variable      */
  238. int       alloced = 0;        /* Have we allocated a device flag     */
  239. ULONG     last_block;         /* The last block number                     */
  240. ULONG     block_len;          /* The size of each block                    */
  241.  
  242. char      adr_msg[][80] =  {"Subchannel Q mode information not supplied",
  243.                            "Subchannel Q encodes current position data",
  244.                            "Subchannel Q encodes media catalog number",
  245.                            "Subchannel Q encodes International Standard Recording Code"};
  246.  
  247. char ctl_msg[][80] =  {"2 channel audio W/O pre-emphasis, copying prohibited",
  248.                        "2 channel audio W/pre-emphasis, copying prohibited",
  249.                        "2 channel audio W/O pre-emphasis, copying allowed",
  250.                        "2 channel audio W/pre-emphasis, copying allowed",
  251.                        "Data track",
  252.                        "Data track",
  253.                        "Data track",
  254.                        "Data track",
  255.                        "4 channel audio W/O pre-emphasis, copying prohibited",
  256.                        "4 channel audio W/pre-emphasis, copying prohibited",
  257.                        "4 channel audio W/O pre-emphasis, copying allowed",
  258.                        "4 channel audio W/pre-emphasis, copying allowed",
  259.                        "Data track",
  260.                        "Data track",
  261.                        "Data track",
  262.                        "Data track"};
  263.  
  264. /***************************************************************************/
  265. /*                                                                         */
  266. /* The main subroutine.  We get a handle from the DD and if it worked,     */
  267. /* show all the commands.  Then we go into a forever loop that waits for   */
  268. /* a command from stdin and executes it, and goes back to waiting.  The    */
  269. /* way out of this loop is the 'quit' command which exits after freeing    */
  270. /* the allocated device.                                                   */
  271. /*                                                                         */
  272. /***************************************************************************/
  273. main( int argc, char *argv[], char *envp[])
  274. {
  275.  
  276.    ULONG          acted;             /* action taken on OPEN               */
  277.    USHORT         dhandle;           /* Device handle from Allocate        */
  278.    HFILE          keyboard;          /* File handle for Standard Input     */
  279.    UCHAR          input_string[100]; /* Buffer for command string          */
  280.    ULONG          bytes_read;        /* Number of bytes read from stdin    */
  281.    int            command;           /* Command number                     */
  282.  
  283.    /* Open the DD */
  284.    retval = DosOpen (
  285.       (char *)"$GENSCSI",               /* File path name */
  286.       &dh,                              /* New file's handle */
  287.       &acted,                           /* Action taken - 1=file existed, */
  288.                                         /* 2=file was created */
  289.       (ULONG)0,                         /* File primary allocation */
  290.       (USHORT)0x0000,                   /* File attributes */
  291.       (USHORT)0x0001,                   /* Open function type */
  292.       (USHORT)0x60C2,                   /* Open mode of the file */
  293.       (ULONG)0                          /* Reserved (must be zero) */
  294.       );
  295.  
  296.    /* If it went OK, show the commands */
  297.    if (retval == 0) { syntax(); }
  298.    else {
  299.       printf("Device open failed, retval=%d, action taken=%x\n",(UCHAR)retval,acted);
  300.       return (-1);
  301.       }
  302.  
  303.    /* Do forever */
  304.    keyboard = 0;
  305.    for (;;) {
  306.  
  307.       /* Get a command from the standard input */
  308.       DosRead(keyboard, (void *)input_string, 100, &bytes_read);
  309.  
  310.       /* Figure out what the command was */
  311.       command = -1;
  312.       if (0 == strnicmp(input_string,"alloc",    5))    command = 0;
  313.       if (0 == strnicmp(input_string,"parms",    5))    command = 1;
  314.       if (0 == strnicmp(input_string,"timeout",  7))    command = 2;
  315.       if (0 == strnicmp(input_string,"read",     4))    command = 3;
  316.       if (0 == strnicmp(input_string,"reset",    5))    command = 4;
  317.       if (0 == strnicmp(input_string,"free",     4))    command = 5;
  318.       if (0 == strnicmp(input_string,"quit",     4))    command = 6;
  319.       if (0 == strnicmp(input_string,"exit",     4))    command = 6;
  320.       if (0 == strnicmp(input_string,"p_sns",    5))    command = 7;
  321.       if (0 == strnicmp(input_string,"p_tsb",    5))    command = 8;
  322.       if (0 == strnicmp(input_string,"p_data",   6))    command = 9;
  323.       if (0 == strnicmp(input_string,"count",    5))    command = 10;
  324.       if (0 == strnicmp(input_string,"rtime",    5))    command = 11;
  325.       if (0 == strnicmp(input_string,"sense",    5))    command = 12;
  326.       if (0 == strnicmp(input_string,"general",  7))    command = 13;
  327.       if (0 == strnicmp(input_string,"xp_tsb",   6))    command = 14;
  328.       if (0 == strnicmp(input_string,"inq",      3))    command = 15;
  329.       if (0 == strnicmp(input_string,"other",    5))    command = 16;
  330.       if (0 == strnicmp(input_string,"xp_sns",   6))    command = 17;
  331.       if (0 == strnicmp(input_string,"write",    5))    command = 18;
  332.       if (0 == strnicmp(input_string,"capac",    5))    command = 19;
  333.       if (0 == strnicmp(input_string,"w_dat",    5))    command = 20;
  334.       if (0 == strnicmp(input_string,"xw_dat",   6))    command = 21;
  335.       if (0 == strnicmp(input_string,"toc",      3))    command = 22;
  336.       if (0 == strnicmp(input_string,"p_toc",    5))    command = 23;
  337.       if (0 == strnicmp(input_string,"w_toc",    5))    command = 24;
  338.       if (0 == strnicmp(input_string,"mode_set", 8))    command = 25;
  339.       if (0 == strnicmp(input_string,"blk_size", 8))    command = 26;
  340.       if (0 == strnicmp(input_string,"toc_m",    5))    command = 27;
  341.       if (0 == strnicmp(input_string,"p_toc_m",  7))    command = 28;
  342.       if (0 == strnicmp(input_string,"w_toc_m",  7))    command = 29;
  343.       if (0 == strnicmp(input_string,"rd_all",   6))    command = 30;
  344.       if (0 == strnicmp(input_string,"rd_some",  7))    command = 31;
  345.       if (0 == strnicmp(input_string,"speed",    5))    command = 32;
  346.  
  347.       /* Do the command */
  348.       switch(command) {
  349.  
  350.         /* alloc = allocate the device */
  351.         case 0:
  352.            retval = allocate_dev(&dhandle);
  353.            break;
  354.  
  355.         /* parms = read device parms */
  356.         case 1:
  357.            clear_sense();
  358.            retval = read_dev_parms(dhandle);
  359.            break;
  360.  
  361.         /* timeout = set timeout */
  362.         case 2:
  363.            clear_sense();
  364.            retval = timeout_dev(dhandle);
  365.            break;
  366.  
  367.         /* read = read from device */
  368.         case 3:
  369.            clear_sense();
  370.            read_dev(dhandle);
  371.            break;
  372.  
  373.         /* reset = initialize the device */
  374.         case 4:
  375.            clear_sense();
  376.            reset_dev(dhandle);
  377.            break;
  378.  
  379.         /* free = free the device */
  380.         case 5:
  381.            free_dev(dhandle);
  382.            break;
  383.  
  384.         /* quit = quit */
  385.         case 6:
  386.            if (alloced) free_dev(dhandle);
  387.            exit(0);
  388.            break;
  389.  
  390.         /* print sense */
  391.         case 7:
  392.            show_sense();
  393.            break;
  394.  
  395.         /* print TSB */
  396.         case 8:
  397.            show_tsb();
  398.            break;
  399.  
  400.         /* print data */
  401.         case 9:
  402.            show_data();
  403.            break;
  404.  
  405.         /* count = count devices */
  406.         case 10:
  407.            clear_sense();
  408.            count_dev();
  409.            break;
  410.  
  411.         /* rtime = set timeout */
  412.         case 11:
  413.            clear_sense();
  414.            retval = read_timeout_dev(dhandle);
  415.            break;
  416.  
  417.         /* sense = read sense */
  418.         case 12:
  419.            clear_sense();
  420.            retval = read_sense(dhandle);
  421.            break;
  422.  
  423.         /* general = general SCSI command*/
  424.         case 13:
  425.            clear_sense();
  426.            retval = gen_cmd(dhandle);
  427.            break;
  428.  
  429.         /* print TSB hex */
  430.         case 14:
  431.            show_tsb_x();
  432.            break;
  433.  
  434.         /* inquiry = device inquiry*/
  435.         case 15:
  436.            clear_sense();
  437.            retval = inquiry(dhandle);
  438.            break;
  439.  
  440.         /* other = Send other SCSI command */
  441.         case 16:
  442.            clear_sense();
  443.            retval = other(dhandle);
  444.            break;
  445.  
  446.         /* print sense hex */
  447.         case 17:
  448.            show_sense_x();
  449.            break;
  450.  
  451.         /* write = write to device */
  452.         case 18:
  453.            clear_sense();
  454.            write_dev(dhandle);
  455.            break;
  456.  
  457.         /* capac = Device capacity */
  458.         case 19:
  459.            clear_sense();
  460.            dev_capacity(dhandle,0);
  461.            break;
  462.  
  463.         /* w_dat = Write data to file */
  464.         case 20:
  465.            save_data();
  466.            break;
  467.  
  468.         /* xw_dat = Write data to file - binary */
  469.         case 21:
  470.            save_datab();
  471.            break;
  472.  
  473.         /* toc = Read CDROM TOC */
  474.         case 22:
  475.            clear_sense();
  476.            get_toc(dhandle);
  477.            break;
  478.  
  479.         /* p_toc = Show CDROM TOC */
  480.         case 23:
  481.            show_toc();
  482.            break;
  483.  
  484.         /* w_toc = Write CDROM TOC */
  485.         case 24:
  486.            write_toc();
  487.            break;
  488.  
  489.         /* Mode Set */
  490.         case 25:
  491.            set_mode(dhandle);
  492.            break;
  493.  
  494.         /* Block Size */
  495.         case 26:
  496.            set_blk(dhandle);
  497.            break;
  498.  
  499.         /* Open drawer */
  500.         case 27:
  501.            clear_sense();
  502.            get_toc_m(dhandle);
  503.            break;
  504.  
  505.         /* p_toc_m = Show CDROM TOC */
  506.         case 28:
  507.            show_toc_m();
  508.            break;
  509.  
  510.         /* w_toc_m = Write CDROM TOC */
  511.         case 29:
  512.            write_toc_m();
  513.            break;
  514.  
  515.         /* Copy all of the device to file */
  516.         case 30:
  517.            clear_sense();
  518.            copy_all(dhandle);
  519.            break;
  520.  
  521.         /* Copy some of the device to file*/
  522.         case 31:
  523.            clear_sense();
  524.            copy_some(dhandle);
  525.            break;
  526.  
  527.         /* Time the device */
  528.         case 32:
  529.            clear_sense();
  530.            time_read(dhandle);
  531.            break;
  532.  
  533.         /* If here, the command was invalid - display the help */
  534.         default:
  535.            syntax();
  536.            break;
  537.  
  538.         }
  539.      }
  540.    return (0);
  541.  
  542. }
  543.  
  544. /*******************************************************/
  545. /* This commands free's the currently allocated device */
  546. /* It issues a Deallocate Device IOCtl to GENSCSI      */
  547. /*******************************************************/
  548. int free_dev(USHORT handle)
  549. {
  550.    ULONG  psize;
  551.    ULONG  dsize;
  552.    USHORT pbuf;
  553.    USHORT dbuf;
  554.  
  555.    /* Release the device */
  556.    pbuf = handle;
  557.    psize = 2;
  558.    dsize = 2;
  559.    dbuf = 0;
  560.    retval = DosDevIOCtl (
  561.       dh,                               /* Device handle returned by Open */
  562.       (ULONG)0x80,                      /* Device category */
  563.       (ULONG)0x54,                      /* Device-specific function code */
  564.       (PVOID *)&pbuf,                   /* Command-specific argument list */
  565.       2,                                /* length of parm list  */
  566.       &psize,                           /* length of parm list  */
  567.       (PVOID *)&dbuf,                   /* Data area */
  568.       2,                                /* length of data area  */
  569.       &dsize                            /* Data area */
  570.       );
  571.  
  572.    /* Tell how it went */
  573.    if (retval == 0) { printf("Dealloc device OK\n"); }
  574.    else {
  575.       printf("Dealloc device failed, retval=%d\n",(UCHAR)retval);
  576.       dbuf = 0;
  577.       }
  578.  
  579.    alloced = 0;
  580.    return(retval);
  581.  
  582.  
  583. }
  584.  
  585. /**************************************************************************/
  586. /* This function does the Device Inquiry cmd.  It uses the Device Inquiry */
  587. /* SCB instead of issuing the Inquiry CDB to the device.  If the command  */
  588. /* worked, it displays the interpreted data.                              */
  589. /**************************************************************************/
  590. int    inquiry(USHORT handle)
  591. {
  592.  
  593.    int            s_size;     /* How big a buffer to use */
  594.    inq_type      *inq;        /* Pointer to the INQUIRY data for display */
  595.    int            i;          /* Just a counter */
  596.    xfer_scb_type  xfer;       /* Data buffer for Transfer SCB cmd    */
  597.    scb_hdr_type   hdr;        /* An SCB/header pair                  */
  598.    ULONG          psize;      /* Parm buffer size variable for IOCTL */
  599.    ULONG          dsize;      /* Data buffer size variable for IOCTL */
  600.  
  601.    /* Set the device data block size */
  602.    s_size = 255;
  603.  
  604.    /* allocate the buffer and fill it with zeros */
  605.    if (bufsize) { free(buffer); }
  606.    buffer = malloc(s_size);
  607.    bufsize = s_size;
  608.    for (i=0; i<bufsize; i++) { *(buffer+i) = '\0'; }
  609.  
  610.    /* Put something in psize and dsize */
  611.    psize = 4;
  612.    dsize = 2;
  613.  
  614.    /* Fill in the transfer SCB control block */
  615.    xfer.dev_handle = handle;
  616.    xfer.sense_size = SENSE_SIZE;
  617.    xfer.scb_header = &hdr;
  618.    xfer.flags      = 0;
  619.    xfer.scb_phys   = 0;
  620.  
  621.    /* Fill in the SCB header */
  622.    hdr.next_scb_hdr = NULL;
  623.    hdr.tsb_adr = &tsb;
  624.    hdr.reserved1          = 0;
  625.    hdr.reserved2          = 0;
  626.    hdr.reserved3          = 0;
  627.    hdr.reserved4          = 0;
  628.  
  629.    /* Fill in the SCB */
  630.    hdr.scb.tsb_adr        = &tsb;
  631.    hdr.scb.block_count    = 0;
  632.    hdr.scb.block_length   = 0;
  633.    hdr.scb.chain_adr      = NULL;
  634.    hdr.scb.block_number   = 0;
  635.    hdr.scb.system_buf_cnt = s_size;
  636.    hdr.scb.system_buf_adr = buffer;
  637.    hdr.scb.command        = 0x1C4B;    /* This is the Inquiry command   */
  638.    hdr.scb.enable         = 0xE600;    /* Along with these enable bits  */
  639.  
  640.    /* Do the command */
  641.    retval = DosDevIOCtl (
  642.       dh,                               /* Device handle returned by Open */
  643.       (ULONG)0x80,                      /* Device category */
  644.       (ULONG)0x52,                      /* Device-specific function code */
  645.       (PVOID *)&xfer,                   /* Command-specific argument list */
  646.       13,                               /* length of parm list  */
  647.       &psize,                           /* length of parm list  */
  648.       (PVOID *)&sense,                  /* Data area */
  649.       SENSE_SIZE,                       /* length of data area  */
  650.       &dsize                            /* Data area */
  651.       );
  652.  
  653.    /* Tell how it went */
  654.    if (retval == 0) {
  655.       printf("Inquiry went OK\n");
  656.       inq = (inq_type *)buffer;
  657.       printf("Device type  = %02X\n",inq->device_type);
  658.       printf("Removable    = %02X\n",inq->removable);
  659.       printf("Standards    = %02X\n",inq->standards);
  660.       printf("Extra data   = %02X\n",inq->extra_length);
  661.       printf("Mfg info     = %s\n",  inq->manufacturer);
  662.       }
  663.    else {
  664.       printf("Inquiry failed, retval=%d\n",(UCHAR)retval);
  665.       }
  666.    return(retval);
  667.  
  668. }
  669.  
  670. /**************************************************************************/
  671. /* This function reads up to 64K bytes from the device.  It asks the user */
  672. /* for the starting sector (block), how many sectors (blocks) to read and */
  673. /* how big each block is.  It then builds the READ SCB and sends it to    */
  674. /* GENSCSI who will pass it on to OS2SCSI.  If it was successful, the     */
  675. /* data is pointed to by the global variable 'buffer'.                    */
  676. /*                                                                        */
  677. /* Note that it doesn't check for the 64K limit imposed by GENSCSI.       */
  678. /**************************************************************************/
  679. int    read_dev(USHORT handle)
  680. {
  681.    char           sector_char[10];
  682.    char          *stopstr;
  683.    int            sector;
  684.    char           count_char[10];
  685.    int            count;
  686.    char           size_char[10];
  687.    int            s_size;
  688.    ULONG          psize;
  689.    ULONG          dsize;
  690.    xfer_scb_type  xfer;
  691.    scb_hdr_type   hdr;
  692.  
  693.    /* Get the start, number, and size of sectors */
  694.    printf("Enter sector to read: ");
  695.    fflush(stdout);
  696.    gets(sector_char);
  697.    sector = strtoul(sector_char, &stopstr, 0);
  698.  
  699.    printf("Enter number of sectors to read: ");
  700.    fflush(stdout);
  701.    gets(count_char);
  702.    count = strtoul(count_char, &stopstr, 0);
  703.  
  704.    printf("Enter number of bytes per sector: ");
  705.    fflush(stdout);
  706.    gets(size_char);
  707.    s_size = strtoul(size_char, &stopstr, 0);
  708.    if (count > 1) { printf("Reading %d sectors\n",count); }
  709.    else           { printf("Reading %d sector\n",count); }
  710.  
  711.    /* allocate the buffer */
  712.    if (bufsize) { free(buffer); }
  713.    buffer = malloc(s_size * count);
  714.    bufsize = count * s_size;
  715.  
  716.    /* Set some dummy values in psize and dsize */
  717.    psize = 4;
  718.    dsize = 2;
  719.  
  720.    /* Fill in the Transfer SCB record */
  721.    xfer.dev_handle = handle;
  722.    xfer.sense_size = SENSE_SIZE;
  723.    xfer.scb_header = &hdr;
  724.    xfer.flags      = 0;
  725.    xfer.scb_phys   = 0;
  726.  
  727.    /* Fill in the SCB Header */
  728.    hdr.next_scb_hdr = NULL;
  729.    hdr.tsb_adr = &tsb;
  730.    hdr.reserved1          = 0;
  731.    hdr.reserved2          = 0;
  732.    hdr.reserved3          = 0;
  733.    hdr.reserved4          = 0;
  734.  
  735.    /* Fill in the SCB */
  736.    hdr.scb.tsb_adr        = &tsb;
  737.    hdr.scb.block_count    = count;
  738.    hdr.scb.block_length   = s_size;
  739.    hdr.scb.chain_adr      = NULL;
  740.    hdr.scb.block_number   = sector;
  741.    hdr.scb.system_buf_cnt = s_size * count;
  742.    hdr.scb.system_buf_adr = buffer;
  743.    hdr.scb.command        = 0x1C41;  /* This is the READ command      */
  744.    hdr.scb.enable         = 0xE000;  /* Along with these enable bits  */
  745.  
  746.    /* Do the command  */
  747.    retval = DosDevIOCtl (
  748.       dh,                               /* Device handle returned by Open */
  749.       (ULONG)0x80,                      /* Device category */
  750.       (ULONG)0x52,                      /* Device-specific function code */
  751.       (PVOID *)&xfer,                   /* Command-specific argument list */
  752.       13,                               /* length of parm list  */
  753.       &psize,                           /* length of parm list  */
  754.       (PVOID *)&sense,                  /* Data area */
  755.       SENSE_SIZE,                       /* length of data area  */
  756.       &dsize                            /* Data area */
  757.       );
  758.  
  759.    /* Tell how it went */
  760.    if (retval == 0) { printf("READ went OK\n"); }
  761.    else { printf("READ failed, retval=%d\n",(UCHAR)retval); }
  762.    return(retval);
  763.  
  764. }
  765.  
  766. int    read_many(USHORT handle, int sector, int count, int s_size, FILE *ofile)
  767. {
  768.    ULONG          psize;
  769.    ULONG          dsize;
  770.    xfer_scb_type  xfer;
  771.    scb_hdr_type   hdr;
  772.    int            remaining;
  773.    int            wrote;
  774.  
  775.    /* allocate the buffer */
  776.    if (bufsize) { free(buffer); }
  777.    buffer = malloc(s_size * 25);
  778.    bufsize = 25 * s_size;
  779.  
  780.    remaining = count;
  781.  
  782.    while (remaining) {
  783.       if (remaining > 25) count = 25;
  784.       else                count = remaining;
  785.  
  786.       /* Set some dummy values in psize and dsize */
  787.       psize = 4;
  788.       dsize = 2;
  789.  
  790.       /* Fill in the Transfer SCB record */
  791.       xfer.dev_handle = handle;
  792.       xfer.sense_size = SENSE_SIZE;
  793.       xfer.scb_header = &hdr;
  794.       xfer.flags      = 0;
  795.       xfer.scb_phys   = 0;
  796.  
  797.       /* Fill in the SCB Header */
  798.       hdr.next_scb_hdr = NULL;
  799.       hdr.tsb_adr = &tsb;
  800.       hdr.reserved1          = 0;
  801.       hdr.reserved2          = 0;
  802.       hdr.reserved3          = 0;
  803.       hdr.reserved4          = 0;
  804.  
  805.       /* Fill in the SCB */
  806.       hdr.scb.tsb_adr        = &tsb;
  807.       hdr.scb.block_count    = count;
  808.       hdr.scb.block_length   = s_size;
  809.       hdr.scb.chain_adr      = NULL;
  810.       hdr.scb.block_number   = sector;
  811.       hdr.scb.system_buf_cnt = s_size * count;
  812.       hdr.scb.system_buf_adr = buffer;
  813.       hdr.scb.command        = 0x1C41;  /* This is the READ command      */
  814.       hdr.scb.enable         = 0xE000;  /* Along with these enable bits  */
  815.  
  816.       /* Do the command  */
  817.       retval = DosDevIOCtl (
  818.          dh,                               /* Device handle returned by Open */
  819.          (ULONG)0x80,                      /* Device category */
  820.          (ULONG)0x52,                      /* Device-specific function code */
  821.          (PVOID *)&xfer,                   /* Command-specific argument list */
  822.          13,                               /* length of parm list  */
  823.          &psize,                           /* length of parm list  */
  824.          (PVOID *)&sense,                  /* Data area */
  825.          SENSE_SIZE,                       /* length of data area  */
  826.          &dsize                            /* Data area */
  827.          );
  828.  
  829.       if (retval) {
  830.          printf("READ failed, retval=%d\n",(UCHAR)retval);
  831.          return(retval);
  832.          }
  833.  
  834.       wrote = fwrite(buffer, 1, count*s_size, ofile);
  835.       if (wrote != count * s_size) {
  836.          printf("Error writing data to disk \n");
  837.          return(-1);
  838.          }
  839.  
  840.       remaining -= count;
  841.       sector += count;
  842.       }
  843.  
  844.    return(0);
  845. }
  846.  
  847. int    read_many_nofile(USHORT handle, int sector, int count, int s_size)
  848. {
  849.    ULONG          psize;
  850.    ULONG          dsize;
  851.    xfer_scb_type  xfer;
  852.    scb_hdr_type   hdr;
  853.    int            remaining;
  854.    int            wrote;
  855.  
  856.    /* allocate the buffer */
  857.    if (bufsize) { free(buffer); }
  858.    buffer = malloc(s_size * 25);
  859.    bufsize = 25 * s_size;
  860.  
  861.    remaining = count;
  862.  
  863.    while (remaining) {
  864.       if (remaining > 25) count = 25;
  865.       else                count = remaining;
  866.  
  867.       /* Set some dummy values in psize and dsize */
  868.       psize = 4;
  869.       dsize = 2;
  870.  
  871.       /* Fill in the Transfer SCB record */
  872.       xfer.dev_handle = handle;
  873.       xfer.sense_size = SENSE_SIZE;
  874.       xfer.scb_header = &hdr;
  875.       xfer.flags      = 0;
  876.       xfer.scb_phys   = 0;
  877.  
  878.       /* Fill in the SCB Header */
  879.       hdr.next_scb_hdr = NULL;
  880.       hdr.tsb_adr = &tsb;
  881.       hdr.reserved1          = 0;
  882.       hdr.reserved2          = 0;
  883.       hdr.reserved3          = 0;
  884.       hdr.reserved4          = 0;
  885.  
  886.       /* Fill in the SCB */
  887.       hdr.scb.tsb_adr        = &tsb;
  888.       hdr.scb.block_count    = count;
  889.       hdr.scb.block_length   = s_size;
  890.       hdr.scb.chain_adr      = NULL;
  891.       hdr.scb.block_number   = sector;
  892.       hdr.scb.system_buf_cnt = s_size * count;
  893.       hdr.scb.system_buf_adr = buffer;
  894.       hdr.scb.command        = 0x1C41;  /* This is the READ command      */
  895.       hdr.scb.enable         = 0xE000;  /* Along with these enable bits  */
  896.  
  897.       /* Do the command  */
  898.       retval = DosDevIOCtl (
  899.          dh,                               /* Device handle returned by Open */
  900.          (ULONG)0x80,                      /* Device category */
  901.          (ULONG)0x52,                      /* Device-specific function code */
  902.          (PVOID *)&xfer,                   /* Command-specific argument list */
  903.          13,                               /* length of parm list  */
  904.          &psize,                           /* length of parm list  */
  905.          (PVOID *)&sense,                  /* Data area */
  906.          SENSE_SIZE,                       /* length of data area  */
  907.          &dsize                            /* Data area */
  908.          );
  909.  
  910.       if (retval) {
  911.          printf("READ failed, retval=%d\n",(UCHAR)retval);
  912.          return(retval);
  913.          }
  914.  
  915.       remaining -= count;
  916.       sector += count;
  917.       }
  918.  
  919.    return(0);
  920. }
  921.  
  922. /**************************************************************************/
  923. /* This function writes up to 64K bytes to the device from a file.  It    */
  924. /* asks the same questions as read_dev, but also asks for the name of the */
  925. /* file containing the data.  Then, it opens the file and reads as much   */
  926. /* as needed into the buffer.  The results of the read are ignored (hey,  */
  927. /* this is a test and demo program, whadayawant!?).  The write SCB is     */
  928. /* then built and sent to OS2SCSI and the results displayed.              */
  929. /*                                                                        */
  930. /* As in read_dev, the 64K limit is not checked.                          */
  931. /**************************************************************************/
  932. int    write_dev(USHORT handle)
  933. {
  934.    char           sector_char[10];
  935.    int            sector;
  936.    char           count_char[10];
  937.    int            count;
  938.    char           size_char[10];
  939.    int            s_size;
  940.    char           fname[100];
  941.    FILE          *ifile;
  942.    int            i;
  943.    ULONG          psize;
  944.    ULONG          dsize;
  945.    xfer_scb_type  xfer;
  946.    scb_hdr_type   hdr;
  947.  
  948.    /* Get the start, number, and size of sectors */
  949.    printf("Enter starting sector to write: ");
  950.    fflush(stdout);
  951.    gets(sector_char);
  952.    sector = atoi(sector_char);
  953.  
  954.    printf("Enter number of sectors to write: ");
  955.    fflush(stdout);
  956.    gets(count_char);
  957.    count = atoi(count_char);
  958.  
  959.    printf("Enter number of bytes per sector: ");
  960.    fflush(stdout);
  961.    gets(size_char);
  962.    s_size = atoi(size_char);
  963.    printf("Reading %d sectors\n",count);
  964.  
  965.    /* Get the name of the file holding the data */
  966.    printf("Enter name of file to get data from: ");
  967.    fflush(stdout);
  968.    gets(fname);
  969.  
  970.    /* allocate the buffer (if needed) */
  971.    if (bufsize) { free(buffer); }
  972.    buffer = malloc(s_size * count);
  973.    bufsize = count * s_size;
  974.    for (i=0; i<bufsize; i++) { *(buffer+i) = '\0'; }
  975.  
  976.    /* Load the file into the buffer */
  977.    ifile = fopen(fname,"rb");
  978.    fread(buffer,1,bufsize,ifile);
  979.    fclose(ifile);
  980.  
  981.    /* The usual variable settings ... dummy sizes */
  982.    psize = 4;
  983.    dsize = 2;
  984.  
  985.    /* Fill the transfer SCB */
  986.    xfer.dev_handle = handle;
  987.    xfer.sense_size = SENSE_SIZE;
  988.    xfer.scb_header = &hdr;
  989.    xfer.flags      = 0;
  990.    xfer.scb_phys   = 0;
  991.  
  992.    /* Fill the SCB Header */
  993.    hdr.next_scb_hdr = NULL;
  994.    hdr.tsb_adr = &tsb;
  995.    hdr.reserved1          = 0;
  996.    hdr.reserved2          = 0;
  997.    hdr.reserved3          = 0;
  998.    hdr.reserved4          = 0;
  999.  
  1000.    /* Fill the SCB */
  1001.    hdr.scb.tsb_adr        = &tsb;
  1002.    hdr.scb.block_count    = count;
  1003.    hdr.scb.block_length   = s_size;
  1004.    hdr.scb.chain_adr      = NULL;
  1005.    hdr.scb.block_number   = sector;
  1006.    hdr.scb.system_buf_cnt = s_size * count;
  1007.    hdr.scb.system_buf_adr = buffer;
  1008.    hdr.scb.command        = 0x1C42;      /* This is the write command     */
  1009.    hdr.scb.enable         = 0x6000;      /* Along with these enable bits  */
  1010.  
  1011.    /* Do it */
  1012.    retval = DosDevIOCtl (
  1013.       dh,                               /* Device handle returned by Open */
  1014.       (ULONG)0x80,                      /* Device category */
  1015.       (ULONG)0x52,                      /* Device-specific function code */
  1016.       (PVOID *)&xfer,                   /* Command-specific argument list */
  1017.       13,                               /* length of parm list  */
  1018.       &psize,                           /* length of parm list  */
  1019.       (PVOID *)&sense,                  /* Data area */
  1020.       SENSE_SIZE,                       /* length of data area  */
  1021.       &dsize                            /* Data area */
  1022.       );
  1023.  
  1024.    /* Tell how it went */
  1025.    if (retval == 0) {
  1026.       printf("WRITE went OK\n");
  1027.       }
  1028.    else {
  1029.       printf("WRITE failed, retval=%d\n",(UCHAR)retval);
  1030.       }
  1031.    return(retval);
  1032.  
  1033. }
  1034.  
  1035. /*****************************************************************************/
  1036. /*                                                                           */
  1037. /*  This function reads the current sense data from the device into the      */
  1038. /*  global sense buffer.  It uses the SENSE SCB instead of the 0x03 command. */
  1039. /*                                                                           */
  1040. /*****************************************************************************/
  1041. int    read_sense(USHORT handle)
  1042. {
  1043.  
  1044.    char          tempsense[100]; /* This is the sense buffer for this cmd    */
  1045.    int           i;              /* Just a counter                           */
  1046.    ULONG         psize;          /* The usual 4 variables : dummy sizes      */
  1047.    ULONG         dsize;          /*                                          */
  1048.    xfer_scb_type xfer;           /* The transfer SCB and the SCB header      */
  1049.    scb_hdr_type  hdr;            /*    (which holds the SCB, as well)        */
  1050.  
  1051.    /* Empty the temporary sense buffer */
  1052.    for (i=0; i<100; i++) {tempsense[i] = '\0'; }
  1053.  
  1054.    /* The usual filling of variables   */
  1055.    psize = 4;
  1056.    dsize = 2;
  1057.  
  1058.    /* Fill the transfer SCB   */
  1059.    xfer.dev_handle = handle;
  1060.    xfer.sense_size = 0;
  1061.    xfer.scb_header = &hdr;
  1062.    xfer.flags      = 0;
  1063.    xfer.scb_phys   = 0;
  1064.  
  1065.    /* Fill the SCB Header */
  1066.    hdr.next_scb_hdr = NULL;
  1067.    hdr.tsb_adr = &tsb;
  1068.    hdr.reserved1          = 0;
  1069.    hdr.reserved2          = 0;
  1070.    hdr.reserved3          = 0;
  1071.    hdr.reserved4          = 0;
  1072.  
  1073.    /* Fill the SCB itself */
  1074.    hdr.scb.tsb_adr        = &tsb;
  1075.    hdr.scb.block_count    = 0;
  1076.    hdr.scb.block_length   = 0;
  1077.    hdr.scb.chain_adr      = NULL;
  1078.    hdr.scb.block_number   = 0;
  1079.    hdr.scb.system_buf_cnt = 255;
  1080.    hdr.scb.system_buf_adr = sense;
  1081.    hdr.scb.command        = 0x1C48;   /* This is the sense command     */
  1082.    hdr.scb.enable         = 0xE600;   /* Along with these enable bits  */
  1083.  
  1084.    /* Do it */
  1085.    retval = DosDevIOCtl (
  1086.       dh,                               /* Device handle returned by Open */
  1087.       (ULONG)0x80,                      /* Device category */
  1088.       (ULONG)0x52,                      /* Device-specific function code */
  1089.       (PVOID *)&xfer,                   /* Command-specific argument list */
  1090.       13,                               /* length of parm list  */
  1091.       &psize,                           /* length of parm list  */
  1092.       (PVOID *)&tempsense,              /* Data area */
  1093.       100,                              /* length of data area  */
  1094.       &dsize                            /* Data area */
  1095.       );
  1096.  
  1097.    /* Tell how it went */
  1098.    if (retval == 0) { printf("Sense went OK\n"); }
  1099.    else {
  1100.       printf("Sense failed, retval=%d\n",(UCHAR)retval);
  1101.       printf("Sense data = ");
  1102.       hexdisp(tempsense, 16);
  1103.       }
  1104.    return(retval);
  1105.  
  1106. }
  1107.  
  1108. /*****************************************************************************/
  1109. /*                                                                           */
  1110. /*  This function returns the number of blocks and the size of each block    */
  1111. /*  for the media currently in the device.  It uses the Device Capacity SCB. */
  1112. /*                                                                           */
  1113. /*****************************************************************************/
  1114. int    dev_capacity(USHORT handle, int quiet)
  1115. {
  1116.  
  1117.    ULONG         cap[2];        /* A block to hold the returned data         */
  1118.    int           i;             /* A counter                                 */
  1119.    ULONG         psize;         /* A holder for the parm buffer size         */
  1120.    ULONG         dsize;         /* A holder for the data buffer size         */
  1121.    xfer_scb_type xfer;          /* The Transfer SCB                          */
  1122.    scb_hdr_type  hdr;           /* The SCB                                   */
  1123.  
  1124.    /* Zero the target block */
  1125.    for (i=0; i<2; i++) {cap[i] = 0; }
  1126.  
  1127.    /* Set some variables to dummy values */
  1128.    psize = 4;
  1129.    dsize = 2;
  1130.  
  1131.    /* Fill in the Transfer SCB */
  1132.    xfer.dev_handle = handle;
  1133.    xfer.sense_size = 0;
  1134.    xfer.scb_header = &hdr;
  1135.    xfer.flags      = 0;
  1136.    xfer.scb_phys   = 0;
  1137.  
  1138.    /* Fill in the SCB Header */
  1139.    hdr.next_scb_hdr = NULL;
  1140.    hdr.tsb_adr = &tsb;
  1141.    hdr.reserved1          = 0;
  1142.    hdr.reserved2          = 0;
  1143.    hdr.reserved3          = 0;
  1144.    hdr.reserved4          = 0;
  1145.  
  1146.    /* Fill in the SCB itself */
  1147.    hdr.scb.tsb_adr        = &tsb;
  1148.    hdr.scb.block_count    = 0;
  1149.    hdr.scb.block_length   = 0;
  1150.    hdr.scb.chain_adr      = NULL;
  1151.    hdr.scb.block_number   = 0;
  1152.    hdr.scb.system_buf_cnt = 8;
  1153.    hdr.scb.system_buf_adr = (UCHAR *)cap;
  1154.    hdr.scb.command        = 0x1C49;     /* This is the Capacity command  */
  1155.    hdr.scb.enable         = 0xE400;     /* Along with these enable bits  */
  1156.  
  1157.    /* Do the command (transfer SCB) */
  1158.    retval = DosDevIOCtl (
  1159.       dh,                               /* Device handle returned by Open */
  1160.       (ULONG)0x80,                      /* Device category */
  1161.       (ULONG)0x52,                      /* Device-specific function code */
  1162.       (PVOID *)&xfer,                   /* Command-specific argument list */
  1163.       13,                               /* length of parm list  */
  1164.       &psize,                           /* length of parm list  */
  1165.       (PVOID *)&sense,                  /* Data area */
  1166.       100,                              /* length of data area  */
  1167.       &dsize                            /* Data area */
  1168.       );
  1169.  
  1170.    /* If it worked, make the values little-endian and display them */
  1171.    if (retval == 0) {
  1172.       last_block = swap32(cap[0]);
  1173.       block_len = swap32(cap[1]);
  1174.       if (!quiet) {
  1175.          printf("Device Capacity went OK\n");
  1176.          printf("Last block = %d, Block length = %d bytes\n",last_block, block_len);
  1177.          }
  1178.       }
  1179.    else {
  1180.       if (!quiet) {
  1181.          printf("Device capacity failed, retval=%d\n",(UCHAR)retval);
  1182.          }
  1183.       }
  1184.    return(retval);
  1185.  
  1186. }
  1187.  
  1188. /*****************************************************************************/
  1189. /*                                                                           */
  1190. /*  This function sets the timeout value for a particular device.  It issues */
  1191. /*  the Set Timeout command to OS2SCSI.                                      */
  1192. /*                                                                           */
  1193. /*****************************************************************************/
  1194. int  timeout_dev(USHORT handle)
  1195. {
  1196.  
  1197.    int           timeval;     /* The timeout (in millisec)                  */
  1198.    char          entry[10];   /* A place to hold the input string           */
  1199.    ULONG         psize;       /* The size of the parm buffer                */
  1200.    ULONG         dsize;       /* The size of the data buffer                */
  1201.    timeout_type  tmt;         /* The record sent to OS2SCSI                 */
  1202.  
  1203.    /* Get the timeout value */
  1204.    printf("Enter timeout value in milliseconds: ");
  1205.    fflush(stdout);
  1206.    gets(entry);
  1207.    timeval = atoi(entry);
  1208.  
  1209.    /* Store it and the device handle in the buffer to be sent */
  1210.    tmt.handle = handle;
  1211.    tmt.timeout = timeval;
  1212.  
  1213.    /* Set the parm and data buffer sizes */
  1214.    psize = 6;
  1215.    dsize = 0;
  1216.  
  1217.    /* Do the request */
  1218.    retval = DosDevIOCtl (
  1219.       dh,                               /* Device handle returned by Open */
  1220.       (ULONG)0x80,                      /* Device category */
  1221.       (ULONG)0x50,                      /* Device-specific function code */
  1222.       (PVOID *)&tmt,                    /* Command-specific argument list */
  1223.       6,                                /* length of parm list  */
  1224.       &psize,                           /* length of parm list  */
  1225.       (PVOID *)NULL,                    /* Data area */
  1226.       0,                                /* length of data area  */
  1227.       &dsize                            /* Data area */
  1228.       );
  1229.  
  1230.    /* Tell how it went */
  1231.    if (retval == 0) {
  1232.       printf("Set Timeout (0x%08X milliseconds) went OK\n",tmt.timeout);
  1233.       }
  1234.    else {
  1235.       printf("Set timeout failed, retval=%d\n",(UCHAR)retval);
  1236.       }
  1237.  
  1238.    return(retval);
  1239.  
  1240. }
  1241.  
  1242. /*****************************************************************************/
  1243. /*                                                                           */
  1244. /*  This function reads the timeout value for a particular device.  It does  */
  1245. /*  the Get Timeout command to OS2SCSI.                                      */
  1246. /*                                                                           */
  1247. /*****************************************************************************/
  1248. int  read_timeout_dev(USHORT handle)
  1249. {
  1250.  
  1251.    int          timeval;  /* Where the answer is going to go                 */
  1252.    ULONG        psize;    /* The size of the parm buffer                     */
  1253.    ULONG        dsize;    /* The size of the data buffer                     */
  1254.    timeout_type tmt;      /* The structure we are going to send to OS2SCSI   */
  1255.  
  1256.    /* Clear the target variable */
  1257.    timeval = 0;
  1258.  
  1259.    /* Set the device handle into the structure to be sent */
  1260.    tmt.handle = handle;
  1261.  
  1262.    /* Set the parm and data buffer sizes */
  1263.    psize = 2;
  1264.    dsize = 4;
  1265.  
  1266.    /* Do the command */
  1267.    retval = DosDevIOCtl (
  1268.       dh,                               /* Device handle returned by Open */
  1269.       (ULONG)0x80,                      /* Device category */
  1270.       (ULONG)0x51,                      /* Device-specific function code */
  1271.       (PVOID *)&tmt,                    /* Command-specific argument list */
  1272.       4,                                /* length of parm list  */
  1273.       &psize,                           /* length of parm list  */
  1274.       (PVOID *)&timeval,                /* Data area */
  1275.       4,                                /* length of data area  */
  1276.       &dsize                            /* Data area */
  1277.       );
  1278.  
  1279.    /* Tell how it went */
  1280.    if (retval == 0) {
  1281.       printf("Device timeout = 0x%08X milliseconds\n",timeval);
  1282.       }
  1283.    else {
  1284.       printf("Read timeout failed, retval=%d\n",(UCHAR)retval);
  1285.       }
  1286.  
  1287.    return(retval);
  1288.  
  1289. }
  1290.  
  1291. /*****************************************************************************/
  1292. /*                                                                           */
  1293. /*  This function requests that a device of a given type be allocated to     */
  1294. /*  this application.  It asks the user for the peripheral type (cdrom,      */
  1295. /*  tape, etc) and whether the media is removable.  It then builds the       */
  1296. /*  request and sends it to OS2SCSI.  If the results are successful, it      */
  1297. /*  returns the handle.                                                      */
  1298. /*                                                                           */
  1299. /*****************************************************************************/
  1300. int  allocate_dev(USHORT *handle)
  1301. {
  1302.  
  1303.    int    dev_type, periph_type;
  1304.    char   entry[10];
  1305.    ULONG  psize;
  1306.    ULONG  dsize;
  1307.    USHORT dbuf;
  1308.    USHORT alloc_pbuf[2];
  1309.  
  1310.    /* Get the device type and peripheral type values */
  1311.    printf("Enter device type: ");
  1312.    fflush(stdout);
  1313.    gets(entry);
  1314.    periph_type = atoi(entry);
  1315.    printf("Removable (y/n)?: ");
  1316.    fflush(stdout);
  1317.    gets(entry);
  1318.    dev_type = 0;
  1319.    if (121 == (UCHAR)entry[0]) { dev_type  = 0x8000; }
  1320.    if ( 89 == (UCHAR)entry[0]) { dev_type  = 0x8000; }
  1321.  
  1322.    /* Fill the parm buffer with the requested device info */
  1323.    alloc_pbuf[0] = (USHORT)(dev_type + periph_type);
  1324.    alloc_pbuf[1] = 0x0000;
  1325.  
  1326.    /* Set the parm and data buffer sizes */
  1327.    psize = 4;
  1328.    dsize = 2;
  1329.  
  1330.    /* Zero the target buffer (where the device handle will go */
  1331.    dbuf = 0;
  1332.  
  1333.    /* Do the command */
  1334.    retval = DosDevIOCtl (
  1335.       dh,                               /* Device handle returned by Open */
  1336.       (ULONG)0x80,                      /* Device category */
  1337.       (ULONG)0x55,                      /* Device-specific function code */
  1338.       (PVOID *)&alloc_pbuf,             /* Command-specific argument list */
  1339.       4,                                /* length of parm list  */
  1340.       &psize,                           /* length of parm list  */
  1341.       (PVOID *)&dbuf,                   /* Data area */
  1342.       2,                                /* length of data area  */
  1343.       &dsize                            /* Data area */
  1344.       );
  1345.  
  1346.    /* Tell how it went */
  1347.    if (retval == 0) {
  1348.       printf("Allocate device went OK, handle = %d\n",dbuf);
  1349.       }
  1350.    else {
  1351.       printf("Allocate device failed, retval=%d\n",(UCHAR)retval);
  1352.       dbuf = 0;
  1353.       return(-1);
  1354.       }
  1355.  
  1356.    /* If it worked, note that we have a device allocated and return the */
  1357.    /* handle to the caller                                              */
  1358.    alloced = 1;
  1359.    *handle = dbuf;
  1360.    return(retval);
  1361.  
  1362. }
  1363.  
  1364. /*****************************************************************************/
  1365. /*                                                                           */
  1366. /*  This function asks how many devices of a certain type are known or       */
  1367. /*  defined to OS2SCSI.  It does this by issuing the Device Count command    */
  1368. /*  for both removable and non-removable media after asking the user for the */
  1369. /*  device type.                                                             */
  1370. /*                                                                           */
  1371. /*  Note that some systems will return the number of devices defined to      */
  1372. /*  BIOS, not how many are really in the system.                             */
  1373. /*                                                                           */
  1374. /*****************************************************************************/
  1375. void count_dev(void)
  1376. {
  1377.  
  1378.    int    dev_type;
  1379.    char   entry[10];
  1380.    ULONG  psize;
  1381.    ULONG  dsize;
  1382.    USHORT pbuf;
  1383.    USHORT dbuf;
  1384.  
  1385.    /* Get the device type and peripheral type values */
  1386.    printf("Enter device type: ");
  1387.    fflush(stdout);
  1388.    gets(entry);
  1389.    dev_type = atoi(entry);
  1390.  
  1391.    /* Ask for non-removable media count */
  1392.    pbuf = (USHORT)(dev_type);
  1393.    psize = 2;
  1394.    dsize = 2;
  1395.    dbuf = 0;
  1396.    retval = DosDevIOCtl (
  1397.       dh,                               /* Device handle returned by Open */
  1398.       (ULONG)0x80,                      /* Device category */
  1399.       (ULONG)0x56,                      /* Device-specific function code */
  1400.       (PVOID *)&pbuf,                   /* Command-specific argument list */
  1401.       2,                                /* length of parm list  */
  1402.       &psize,                           /* length of parm list  */
  1403.       (PVOID *)&dbuf,                   /* Data area */
  1404.       2,                                /* length of data area  */
  1405.       &dsize                            /* Data area */
  1406.       );
  1407.  
  1408.    /* Tell how it went */
  1409.    if (retval == 0) {
  1410.       printf("Device type count OK, count = %d non-removable\n",dbuf);
  1411.       }
  1412.    else {
  1413.       printf("Device type count failed, retval=%d\n",(UCHAR)retval);
  1414.       }
  1415.  
  1416.    /* Now do removable media count */
  1417.    pbuf = (USHORT)(0x8000+dev_type);
  1418.    psize = 2;
  1419.    dsize = 2;
  1420.    dbuf = 0;
  1421.    retval = DosDevIOCtl (
  1422.       dh,                               /* Device handle returned by Open */
  1423.       (ULONG)0x80,                      /* Device category */
  1424.       (ULONG)0x56,                      /* Device-specific function code */
  1425.       (PVOID *)&pbuf,                   /* Command-specific argument list */
  1426.       2,                                /* length of parm list  */
  1427.       &psize,                           /* length of parm list  */
  1428.       (PVOID *)&dbuf,                   /* Data area */
  1429.       2,                                /* length of data area  */
  1430.       &dsize                            /* Data area */
  1431.       );
  1432.  
  1433.    /* Tell how it went */
  1434.    if (retval == 0) {
  1435.       printf("Device type count OK, count = %d removable\n",dbuf);
  1436.       }
  1437.    else {
  1438.       printf("Device type count failed, retval=%d\n",(UCHAR)retval);
  1439.       }
  1440.  
  1441.    return;
  1442.  
  1443. }
  1444.  
  1445. /*****************************************************************************/
  1446. /*                                                                           */
  1447. /*  This function issues the Reset command to OS2SCSI for a given device     */
  1448. /*  handle.                                                                  */
  1449. /*                                                                           */
  1450. /*  Note that I've seen this command hang the system, for some unknown       */
  1451. /*  reason.  It seems to make the call to OS2SCSI, but it never returns.     */
  1452. /*  Other times, the command works just fine.                                */
  1453. /*                                                                           */
  1454. /*****************************************************************************/
  1455. int  reset_dev(USHORT handle)
  1456. {
  1457.    ULONG   psize;
  1458.    ULONG   dsize;
  1459.    USHORT  alloc_pbuf[2];
  1460.  
  1461.    alloc_pbuf[0] = handle;
  1462.    alloc_pbuf[1] = SENSE_SIZE;
  1463.    psize = 4;
  1464.    dsize = SENSE_SIZE;
  1465.    retval = DosDevIOCtl (
  1466.       dh,                               /* Device handle returned by Open */
  1467.       (ULONG)0x80,                      /* Device category */
  1468.       (ULONG)0x45,                      /* Device-specific function code */
  1469.       (PVOID *)&alloc_pbuf,             /* Command-specific argument list */
  1470.       4,                                /* length of parm list  */
  1471.       &psize,                           /* length of parm list  */
  1472.       (PVOID *)&sense,                  /* Data area */
  1473.       SENSE_SIZE,                       /* length of data area  */
  1474.       &dsize                            /* Data area */
  1475.       );
  1476.  
  1477.    /* Tell how it went */
  1478.    if (retval == 0) {
  1479.       printf("Reset device went OK\n");
  1480.       }
  1481.    else {
  1482.       printf("Reset device failed, retval=%d\n",(UCHAR)retval);
  1483.       }
  1484.    return(retval);
  1485.  
  1486. }
  1487.  
  1488. /*****************************************************************************/
  1489. /*                                                                           */
  1490. /*  This function issues the Return Device Parms command for a given device  */
  1491. /*  handle.                                                                  */
  1492. /*                                                                           */
  1493. /*  Note that I've not seen this command return useful (or even accurate)    */
  1494. /*  information.                                                             */
  1495. /*                                                                           */
  1496. /*****************************************************************************/
  1497. int  read_dev_parms(USHORT handle)
  1498. {
  1499.    devparm_type      devparms;
  1500.    ULONG             psize;
  1501.    ULONG             dsize;
  1502.    USHORT            pbuf;
  1503.  
  1504.    /* Fill the buffer with junk to prove that something happened */
  1505.    devparms.dev_key_index   = 0xFFFF;
  1506.    devparms.scb_arch_lvl    = 0xFF;
  1507.    devparms.adapter_index   = 0xFF;
  1508.    devparms.device_flags    = 0xFFFF;
  1509.    devparms.lun             = 0xFF;
  1510.    devparms.pun             = 0xFF;
  1511.  
  1512.    /* Build the command */
  1513.    pbuf = handle;
  1514.    psize = 2;
  1515.    dsize = 8;
  1516.  
  1517.    /* Do it */
  1518.    retval = DosDevIOCtl (
  1519.       dh,                               /* Device handle returned by Open */
  1520.       (ULONG)0x80,                      /* Device category */
  1521.       (ULONG)0x43,                      /* Device-specific function code */
  1522.       (PVOID *)&pbuf,                   /* Command-specific argument list */
  1523.       2,                                /* length of parm list  */
  1524.       &psize,                           /* length of parm list  */
  1525.       (PVOID *)&devparms,               /* Data area */
  1526.       8,                                /* length of data area  */
  1527.       &dsize                            /* Data area */
  1528.       );
  1529.  
  1530.    /* Tell how it went */
  1531.    if (retval == 0) {
  1532.       printf("Read device parms went OK\n");
  1533.       printf("  Device key index = %04X\n",devparms.dev_key_index);
  1534.       printf("  SCB Arch level   = %02X\n",devparms.scb_arch_lvl);
  1535.       printf("  Adapter index    = %02X\n",devparms.adapter_index);
  1536.       printf("  Device flags     = %04X\n",devparms.device_flags);
  1537.       printf("  Logical Unit #   = %02X\n",devparms.lun);
  1538.       printf("  Physical Unit #  = %02X\n",devparms.pun);
  1539.       }
  1540.    else {
  1541.       printf("Read device parms failed, retval=%d\n",(UCHAR)retval);
  1542.       }
  1543.    return(retval);
  1544.  
  1545. }
  1546.  
  1547. /*****************************************************************************/
  1548. /*                                                                           */
  1549. /*  This function lets the user build any 'short' SCB and send it to OS2SCSI */
  1550. /*  for execution.  It's basic operation is to ask the user for each element */
  1551. /*  of the SCB and to put that value into the control block.  When it is     */
  1552. /*  done building it, it displays the SCB and then sends it to OS2SCSI.      */
  1553. /*                                                                           */
  1554. /*****************************************************************************/
  1555. int    gen_cmd(USHORT handle)
  1556. {
  1557.    char           entry[10];
  1558.    char          *stopstr;
  1559.    ULONG          ent_val;
  1560.    ULONG          psize;
  1561.    ULONG          dsize;
  1562.    xfer_scb_type  xfer;
  1563.    scb_hdr_type   hdr;
  1564.  
  1565.    /* SCB Command word */
  1566.    printf("Command Word: ");
  1567.    fflush(stdout);
  1568.    gets(entry);
  1569.    ent_val = strtoul(entry, &stopstr, 0);
  1570.    hdr.scb.command        = ent_val;
  1571.  
  1572.    /* SCB Enable word */
  1573.    printf("Enable Word: ");
  1574.    fflush(stdout);
  1575.    gets(entry);
  1576.    ent_val = strtoul(entry, &stopstr, 0);
  1577.    hdr.scb.enable         = ent_val;
  1578.  
  1579.    /* The Logical Address (what bock to read/write/seek to,modify,whatever) */
  1580.    printf("Logical Address: ");
  1581.    fflush(stdout);
  1582.    gets(entry);
  1583.    ent_val = strtoul(entry, &stopstr, 0);
  1584.    hdr.scb.block_number  = ent_val;
  1585.  
  1586.    /* How big is the buffer */
  1587.    printf("Buffer size: ");
  1588.    fflush(stdout);
  1589.    gets(entry);
  1590.    ent_val = strtoul(entry, &stopstr, 0);
  1591.    hdr.scb.system_buf_cnt = ent_val;
  1592.  
  1593.    /* How big is a block */
  1594.    printf("Block size: ");
  1595.    fflush(stdout);
  1596.    gets(entry);
  1597.    ent_val = strtoul(entry, &stopstr, 0);
  1598.    hdr.scb.block_length = ent_val;
  1599.  
  1600.    /* How many blocks are involved */
  1601.    printf("Block count: ");
  1602.    fflush(stdout);
  1603.    gets(entry);
  1604.    ent_val = strtoul(entry, &stopstr, 0);
  1605.    hdr.scb.block_count = ent_val;
  1606.  
  1607.    /* allocate the buffer */
  1608.    if (bufsize) { free(buffer); }
  1609.    buffer = malloc(ent_val);
  1610.    bufsize = ent_val;
  1611.  
  1612.    /* Here is our normal Transfer SCB operation */
  1613.    psize = 4;
  1614.    dsize = 2;
  1615.    xfer.dev_handle = handle;
  1616.    xfer.sense_size = SENSE_SIZE;
  1617.    xfer.scb_header = &hdr;
  1618.    xfer.flags      = 0;
  1619.    xfer.scb_phys   = 0;
  1620.  
  1621.    hdr.next_scb_hdr = NULL;
  1622.    hdr.tsb_adr = &tsb;
  1623.  
  1624.    hdr.reserved1          = 0;
  1625.    hdr.reserved2          = 0;
  1626.    hdr.reserved3          = 0;
  1627.    hdr.reserved4          = 0;
  1628.    hdr.scb.tsb_adr        = &tsb;
  1629.    hdr.scb.chain_adr      = NULL;
  1630.    hdr.scb.system_buf_adr = buffer;
  1631.  
  1632.    /* Display the SCB prior to execution */
  1633.    printf("Attempting GENERAL SCSI command :\n");
  1634.    printf("Command word = %04X\n",hdr.scb.command);
  1635.    printf("Enable word  = %04X\n",hdr.scb.enable);
  1636.    printf("Buffer size  = %08X\n",hdr.scb.system_buf_cnt);
  1637.    printf("Block number = %08X\n",hdr.scb.block_number);
  1638.    printf("Block length = %04X\n",hdr.scb.block_length);
  1639.    printf("Block count  = %04X\n",hdr.scb.block_count);
  1640.  
  1641.    /* Do it */
  1642.    retval = DosDevIOCtl (
  1643.       dh,                               /* Device handle returned by Open */
  1644.       (ULONG)0x80,                      /* Device category */
  1645.       (ULONG)0x52,                      /* Device-specific function code */
  1646.       (PVOID *)&xfer,                   /* Command-specific argument list */
  1647.       13,                               /* length of parm list  */
  1648.       &psize,                           /* length of parm list  */
  1649.       (PVOID *)&sense,                  /* Data area */
  1650.       SENSE_SIZE,                       /* length of data area  */
  1651.       &dsize                            /* Data area */
  1652.       );
  1653.  
  1654.    /* Tell how it went */
  1655.    if (retval == 0) {
  1656.       printf("GEN_CMD went OK\n");
  1657.       }
  1658.    else {
  1659.       printf("GEN_CMD failed, retval=%d\n",(UCHAR)retval);
  1660.       }
  1661.    return(retval);
  1662.  
  1663. }
  1664.  
  1665. /*****************************************************************************/
  1666. /*                                                                           */
  1667. /*  This function lets the user build a SCSI command and send it to the      */
  1668. /*  device via the Send Other SCB subcommand of the Transfer SCB command.    */
  1669. /*  It asks the user for the size of the SCSI command (in bytes) and then    */
  1670. /*  for each byte of the command,  It then allocates a buffer, builds the    */
  1671. /*  Send Other SCB and sends it.                                             */
  1672. /*                                                                           */
  1673. /*****************************************************************************/
  1674. int    other(USHORT handle)
  1675. {
  1676.    char              entry[10];
  1677.    char             *stopstr;
  1678.    ULONG             ent_val;
  1679.    ULONG             cmd_len;
  1680.    int               i;
  1681.    ULONG             psize;
  1682.    ULONG             dsize;
  1683.    xfer_lscb_type    xfer;
  1684.    long_scb_hdr_type lhdr;
  1685.  
  1686.    /* Fill in the SCB */
  1687.    lhdr.scb.command        = 0x245F;   /* This is the Send Other SCB    */
  1688.    lhdr.scb.enable         = 0x6600;   /* Along with these enable bits  */
  1689.  
  1690.    /* Ask for the number of bytes */
  1691.    printf("Number of bytes in command: ");
  1692.    fflush(stdout);
  1693.    gets(entry);
  1694.    ent_val = strtoul(entry, &stopstr, 0);
  1695.    lhdr.scb.cmd_len  = (UCHAR)ent_val;
  1696.    cmd_len = ent_val;
  1697.  
  1698.    /* Get the SCSI command */
  1699.    for (i=0; i<cmd_len; i++) {
  1700.        printf("Command byte %1d: ",i);
  1701.        fflush(stdout);
  1702.        gets(entry);
  1703.        ent_val = strtoul(entry, &stopstr, 0);
  1704.        lhdr.scb.scsi_cmd[i]  = (UCHAR)ent_val;
  1705.        }
  1706.  
  1707.    /* Get the buffer size and allocate it if needed */
  1708.    printf("Buffer size: ");
  1709.    fflush(stdout);
  1710.    gets(entry);
  1711.    ent_val = strtoul(entry, &stopstr, 0);
  1712.    lhdr.scb.system_buf_cnt = ent_val;
  1713.    if (bufsize) { free(buffer); }
  1714.    buffer = malloc(ent_val);
  1715.    bufsize = ent_val;
  1716.  
  1717.    /* Figure out how to set the rd/wr bit in the SCB enable word */
  1718.    printf("Read/Write (w/r)? ");
  1719.    fflush(stdout);
  1720.    gets(entry);
  1721.    if (114 == (UCHAR)entry[0]) { lhdr.scb.enable |= 0x8000; }
  1722.    if ( 82 == (UCHAR)entry[0]) { lhdr.scb.enable |= 0x8000; }
  1723.  
  1724.    /* Our normal transfer SCB processing */
  1725.    psize = 4;
  1726.    dsize = 2;
  1727.    xfer.dev_handle = handle;
  1728.    xfer.sense_size = SENSE_SIZE;
  1729.    xfer.scb_header = &lhdr;
  1730.    xfer.flags      = 1;
  1731.    xfer.scb_phys   = 0;
  1732.  
  1733.    lhdr.next_scb_hdr = NULL;
  1734.    lhdr.tsb_adr = &tsb;
  1735.  
  1736.    lhdr.reserved1          = 0;
  1737.    lhdr.reserved2          = 0;
  1738.    lhdr.reserved3          = 0;
  1739.    lhdr.reserved4          = 0;
  1740.    lhdr.scb.tsb_adr        = &tsb;
  1741.    lhdr.scb.chain_adr      = NULL;
  1742.    lhdr.scb.system_buf_adr = buffer;
  1743.  
  1744.    /* Display the command before processing */
  1745.    printf("Attempting OTHER SCSI command :\n");
  1746.    for (i=0; i<cmd_len; i++) {
  1747.       printf("Command byte %02X = %02X\n",i,lhdr.scb.scsi_cmd[i]);
  1748.       }
  1749.  
  1750.    /* Do it */
  1751.    retval = DosDevIOCtl (
  1752.       dh,                               /* Device handle returned by Open */
  1753.       (ULONG)0x80,                      /* Device category */
  1754.       (ULONG)0x52,                      /* Device-specific function code */
  1755.       (PVOID *)&xfer,                   /* Command-specific argument list */
  1756.       13,                               /* length of parm list  */
  1757.       &psize,                           /* length of parm list  */
  1758.       (PVOID *)&sense,                  /* Data area */
  1759.       SENSE_SIZE,                       /* length of data area  */
  1760.       &dsize                            /* Data area */
  1761.       );
  1762.  
  1763.    /* Tell how it went */
  1764.    if (retval == 0) {
  1765.       printf("OTHER went OK\n");
  1766.       }
  1767.    else {
  1768.       printf("OTHER failed, retval=%d\n",(UCHAR)retval);
  1769.       }
  1770.    return(retval);
  1771.  
  1772. }
  1773.  
  1774. /*****************************************************************************/
  1775. /*                                                                           */
  1776. /*****************************************************************************/
  1777. int    set_mode(USHORT handle)
  1778. {
  1779.    char              entry[10];
  1780.    char             *stopstr;
  1781.    ULONG             ent_val;
  1782.    ULONG             buf_len;
  1783.    int               i;
  1784.    ULONG             psize;
  1785.    ULONG             dsize;
  1786.    xfer_lscb_type    xfer;
  1787.    long_scb_hdr_type lhdr;
  1788.  
  1789.    /* Fill in the SCB */
  1790.    lhdr.scb.command        = 0x245F;   /* This is the Send Other SCB    */
  1791.    lhdr.scb.enable         = 0x6600;   /* Along with these enable bits  */
  1792.  
  1793.    /* The command is 6 bytes long */
  1794.    lhdr.scb.cmd_len  = 6;
  1795.  
  1796.    /* Get the SCSI command */
  1797.    lhdr.scb.scsi_cmd[0]  = 0x15;
  1798.    lhdr.scb.scsi_cmd[1]  = 0x00;
  1799.    lhdr.scb.scsi_cmd[2]  = 0x00;
  1800.    lhdr.scb.scsi_cmd[3]  = 0x00;
  1801.    lhdr.scb.scsi_cmd[4]  = 0x00;
  1802.    lhdr.scb.scsi_cmd[5]  = 0x00;
  1803.  
  1804.    /* Ask for the number of bytes */
  1805.    printf("Number of bytes to send: ");
  1806.    fflush(stdout);
  1807.    gets(entry);
  1808.    ent_val = strtoul(entry, &stopstr, 0);
  1809.    buf_len = ent_val;
  1810.    lhdr.scb.system_buf_cnt = buf_len;
  1811.    lhdr.scb.scsi_cmd[4]  = (UCHAR)buf_len;
  1812.  
  1813.    /* Allocate the buffer */
  1814.    if (bufsize) { free(buffer); }
  1815.    buffer = malloc(buf_len);
  1816.    bufsize = buf_len;
  1817.  
  1818.    /* Fill the buffer */
  1819.    for (i=0; i<buf_len; i++) {
  1820.        printf("Buffer byte %2d: ",i);
  1821.        fflush(stdout);
  1822.        gets(entry);
  1823.        ent_val = strtoul(entry, &stopstr, 0);
  1824.        buffer[i]  = (UCHAR)ent_val;
  1825.        }
  1826.  
  1827.    /* Our normal transfer SCB processing */
  1828.    psize = 4;
  1829.    dsize = 2;
  1830.    xfer.dev_handle = handle;
  1831.    xfer.sense_size = SENSE_SIZE;
  1832.    xfer.scb_header = &lhdr;
  1833.    xfer.flags      = 1;
  1834.    xfer.scb_phys   = 0;
  1835.  
  1836.    lhdr.next_scb_hdr = NULL;
  1837.    lhdr.tsb_adr = &tsb;
  1838.  
  1839.    lhdr.reserved1          = 0;
  1840.    lhdr.reserved2          = 0;
  1841.    lhdr.reserved3          = 0;
  1842.    lhdr.reserved4          = 0;
  1843.    lhdr.scb.tsb_adr        = &tsb;
  1844.    lhdr.scb.chain_adr      = NULL;
  1845.    lhdr.scb.system_buf_adr = buffer;
  1846.  
  1847.    /* Do it */
  1848.    retval = DosDevIOCtl (
  1849.       dh,                               /* Device handle returned by Open */
  1850.       (ULONG)0x80,                      /* Device category */
  1851.       (ULONG)0x52,                      /* Device-specific function code */
  1852.       (PVOID *)&xfer,                   /* Command-specific argument list */
  1853.       13,                               /* length of parm list  */
  1854.       &psize,                           /* length of parm list  */
  1855.       (PVOID *)&sense,                  /* Data area */
  1856.       SENSE_SIZE,                       /* length of data area  */
  1857.       &dsize                            /* Data area */
  1858.       );
  1859.  
  1860.    /* Tell how it went */
  1861.    if (retval == 0) {
  1862.       printf("Mode Set went OK\n");
  1863.       }
  1864.    else {
  1865.       printf("Mode Set failed, retval=%d\n",(UCHAR)retval);
  1866.       }
  1867.    return(retval);
  1868.  
  1869. }
  1870.  
  1871. /*****************************************************************************/
  1872. /*                                                                           */
  1873. /*****************************************************************************/
  1874. int    set_blk(USHORT handle)
  1875. {
  1876.    char              entry[10];
  1877.    char             *stopstr;
  1878.    ULONG             ent_val;
  1879.    ULONG             buf_len;
  1880.    int               i;
  1881.    ULONG             psize;
  1882.    ULONG             dsize;
  1883.    xfer_lscb_type    xfer;
  1884.    long_scb_hdr_type lhdr;
  1885.  
  1886.    /* Fill in the SCB */
  1887.    lhdr.scb.command        = 0x245F;   /* This is the Send Other SCB    */
  1888.    lhdr.scb.enable         = 0x6600;   /* Along with these enable bits  */
  1889.  
  1890.    /* The command is 6 bytes long */
  1891.    lhdr.scb.cmd_len  = 6;
  1892.  
  1893.    /* Set the buffer size */
  1894.    buf_len = 12;
  1895.    lhdr.scb.system_buf_cnt = buf_len;
  1896.  
  1897.    /* Allocate the buffer */
  1898.    if (bufsize) { free(buffer); }
  1899.    buffer = malloc(buf_len);
  1900.    bufsize = buf_len;
  1901.  
  1902.    /* Get the SCSI command */
  1903.    lhdr.scb.scsi_cmd[0]  = 0x15;
  1904.    lhdr.scb.scsi_cmd[1]  = 0x00;
  1905.    lhdr.scb.scsi_cmd[2]  = 0x00;
  1906.    lhdr.scb.scsi_cmd[3]  = 0x00;
  1907.    lhdr.scb.scsi_cmd[4]  = buf_len;
  1908.    lhdr.scb.scsi_cmd[5]  = 0x00;
  1909.  
  1910.    /* Fill the buffer with 0's to start */
  1911.    for (i=0; i<buf_len; i++) { buffer[i]  = 0; }
  1912.    buffer[3]  = 8;
  1913.  
  1914.    /* Now get the details */
  1915.    printf("Media Type: ");
  1916.    fflush(stdout);
  1917.    gets(entry);
  1918.    ent_val = strtoul(entry, &stopstr, 0);
  1919.    buffer[1]  = (UCHAR)ent_val;
  1920.  
  1921.    printf("Density Code: ");
  1922.    fflush(stdout);
  1923.    gets(entry);
  1924.    ent_val = strtoul(entry, &stopstr, 0);
  1925.    buffer[4]  = (UCHAR)ent_val;
  1926.  
  1927.    printf("Block Size: ");
  1928.    fflush(stdout);
  1929.    gets(entry);
  1930.    ent_val = strtoul(entry, &stopstr, 0);
  1931.    buffer[11]  = (UCHAR)(ent_val & 0xFF);
  1932.    buffer[10]  = (UCHAR)((ent_val >>  8) & 0xFF);
  1933.    buffer[ 9]  = (UCHAR)((ent_val >> 16) & 0xFF);
  1934.  
  1935.    /* Our normal transfer SCB processing */
  1936.    psize = 4;
  1937.    dsize = 2;
  1938.    xfer.dev_handle = handle;
  1939.    xfer.sense_size = SENSE_SIZE;
  1940.    xfer.scb_header = &lhdr;
  1941.    xfer.flags      = 1;
  1942.    xfer.scb_phys   = 0;
  1943.  
  1944.    lhdr.next_scb_hdr = NULL;
  1945.    lhdr.tsb_adr = &tsb;
  1946.  
  1947.    lhdr.reserved1          = 0;
  1948.    lhdr.reserved2          = 0;
  1949.    lhdr.reserved3          = 0;
  1950.    lhdr.reserved4          = 0;
  1951.    lhdr.scb.tsb_adr        = &tsb;
  1952.    lhdr.scb.chain_adr      = NULL;
  1953.    lhdr.scb.system_buf_adr = buffer;
  1954.  
  1955.    /* Do it */
  1956.    retval = DosDevIOCtl (
  1957.       dh,                               /* Device handle returned by Open */
  1958.       (ULONG)0x80,                      /* Device category */
  1959.       (ULONG)0x52,                      /* Device-specific function code */
  1960.       (PVOID *)&xfer,                   /* Command-specific argument list */
  1961.       13,                               /* length of parm list  */
  1962.       &psize,                           /* length of parm list  */
  1963.       (PVOID *)&sense,                  /* Data area */
  1964.       SENSE_SIZE,                       /* length of data area  */
  1965.       &dsize                            /* Data area */
  1966.       );
  1967.  
  1968.    /* Tell how it went */
  1969.    if (retval == 0) {
  1970.       printf("Set Block Size went OK\n");
  1971.       }
  1972.    else {
  1973.       printf("Set Block Size failed, retval=%d\n",(UCHAR)retval);
  1974.       }
  1975.    return(retval);
  1976.  
  1977. }
  1978.  
  1979. /*****************************************************************************/
  1980. /*                                                                           */
  1981. /*****************************************************************************/
  1982. int    get_toc(USHORT handle)
  1983. {
  1984.    ULONG             psize;
  1985.    ULONG             dsize;
  1986.    xfer_lscb_type    xfer;
  1987.    long_scb_hdr_type lhdr;
  1988.    USHORT            new_size;
  1989.  
  1990.    /* Fill in the SCB */
  1991.    lhdr.scb.command        = 0x245F;   /* This is the Send Other SCB    */
  1992.    lhdr.scb.enable         = 0xC600;   /* Along with these enable bits  */
  1993.  
  1994.    /* The command is 10 bytes long */
  1995.    lhdr.scb.cmd_len  = 10;
  1996.  
  1997.    /* Get the SCSI command */
  1998.    lhdr.scb.scsi_cmd[0]  = 0x43;
  1999.    lhdr.scb.scsi_cmd[1]  = 0x00;
  2000.    lhdr.scb.scsi_cmd[2]  = 0x00;
  2001.    lhdr.scb.scsi_cmd[3]  = 0x00;
  2002.    lhdr.scb.scsi_cmd[4]  = 0x00;
  2003.    lhdr.scb.scsi_cmd[5]  = 0x00;
  2004.    lhdr.scb.scsi_cmd[6]  = 0x00;
  2005.    lhdr.scb.scsi_cmd[7]  = 0x00;
  2006.    lhdr.scb.scsi_cmd[8]  = 0x04;
  2007.    lhdr.scb.scsi_cmd[9]  = 0x00;
  2008.  
  2009.    /* Set the buffer size and allocate it if needed */
  2010.    lhdr.scb.system_buf_cnt = 4;
  2011.    if (bufsize) { free(buffer); }
  2012.    buffer = malloc(4);
  2013.    bufsize = 4;
  2014.  
  2015.    /* Our normal transfer SCB processing */
  2016.    psize = 4;
  2017.    dsize = 2;
  2018.    xfer.dev_handle = handle;
  2019.    xfer.sense_size = SENSE_SIZE;
  2020.    xfer.scb_header = &lhdr;
  2021.    xfer.flags      = 1;
  2022.    xfer.scb_phys   = 0;
  2023.  
  2024.    lhdr.next_scb_hdr = NULL;
  2025.    lhdr.tsb_adr = &tsb;
  2026.  
  2027.    lhdr.reserved1          = 0;
  2028.    lhdr.reserved2          = 0;
  2029.    lhdr.reserved3          = 0;
  2030.    lhdr.reserved4          = 0;
  2031.    lhdr.scb.tsb_adr        = &tsb;
  2032.    lhdr.scb.chain_adr      = NULL;
  2033.    lhdr.scb.system_buf_adr = buffer;
  2034.  
  2035.    /* Do it */
  2036.    retval = DosDevIOCtl (
  2037.       dh,                               /* Device handle returned by Open */
  2038.       (ULONG)0x80,                      /* Device category */
  2039.       (ULONG)0x52,                      /* Device-specific function code */
  2040.       (PVOID *)&xfer,                   /* Command-specific argument list */
  2041.       13,                               /* length of parm list  */
  2042.       &psize,                           /* length of parm list  */
  2043.       (PVOID *)&sense,                  /* Data area */
  2044.       SENSE_SIZE,                       /* length of data area  */
  2045.       &dsize                            /* Data area */
  2046.       );
  2047.  
  2048.    /* Tell how it went */
  2049.    if (retval) {
  2050.       printf("Failed getting size of TOC, rc = %d\n",(UCHAR)retval);
  2051.       return(retval);
  2052.       }
  2053.  
  2054.    /* Extract the full size of the TOC */
  2055.    new_size = (USHORT)buffer[1];
  2056.    new_size += 256*(USHORT)buffer[0];
  2057.    new_size += 2;
  2058.  
  2059.    lhdr.scb.scsi_cmd[7]  = (UCHAR)((new_size & 0xFF00) >> 8);
  2060.    lhdr.scb.scsi_cmd[8]  = (UCHAR)(new_size & 0x00FF);
  2061.  
  2062.    lhdr.scb.system_buf_cnt = (ULONG)new_size;
  2063.    if (bufsize) { free(buffer); }
  2064.    buffer = malloc(new_size);
  2065.    bufsize = new_size;
  2066.    lhdr.scb.system_buf_adr = buffer;
  2067.  
  2068.    /* Do it */
  2069.    retval = DosDevIOCtl (
  2070.       dh,                               /* Device handle returned by Open */
  2071.       (ULONG)0x80,                      /* Device category */
  2072.       (ULONG)0x52,                      /* Device-specific function code */
  2073.       (PVOID *)&xfer,                   /* Command-specific argument list */
  2074.       13,                               /* length of parm list  */
  2075.       &psize,                           /* length of parm list  */
  2076.       (PVOID *)&sense,                  /* Data area */
  2077.       SENSE_SIZE,                       /* length of data area  */
  2078.       &dsize                            /* Data area */
  2079.       );
  2080.  
  2081.    /* Tell how it went */
  2082.    if (retval == 0) {
  2083.       printf("Read of TOC worked\n");
  2084.       }
  2085.    else {
  2086.       printf("Failed getting TOC, rc = %d\n",(UCHAR)retval);
  2087.       }
  2088.    return(retval);
  2089.  
  2090. }
  2091.  
  2092. /*****************************************************************************/
  2093. /*                                                                           */
  2094. /*****************************************************************************/
  2095. int    get_toc_m(USHORT handle)
  2096. {
  2097.    ULONG             psize;
  2098.    ULONG             dsize;
  2099.    xfer_lscb_type    xfer;
  2100.    long_scb_hdr_type lhdr;
  2101.    USHORT            new_size;
  2102.  
  2103.    /* Fill in the SCB */
  2104.    lhdr.scb.command        = 0x245F;   /* This is the Send Other SCB    */
  2105.    lhdr.scb.enable         = 0xC600;   /* Along with these enable bits  */
  2106.  
  2107.    /* The command is 10 bytes long */
  2108.    lhdr.scb.cmd_len  = 10;
  2109.  
  2110.    /* Get the SCSI command */
  2111.    lhdr.scb.scsi_cmd[0]  = 0x43;
  2112.    lhdr.scb.scsi_cmd[1]  = 0x02;
  2113.    lhdr.scb.scsi_cmd[2]  = 0x00;
  2114.    lhdr.scb.scsi_cmd[3]  = 0x00;
  2115.    lhdr.scb.scsi_cmd[4]  = 0x00;
  2116.    lhdr.scb.scsi_cmd[5]  = 0x00;
  2117.    lhdr.scb.scsi_cmd[6]  = 0x00;
  2118.    lhdr.scb.scsi_cmd[7]  = 0x00;
  2119.    lhdr.scb.scsi_cmd[8]  = 0x04;
  2120.    lhdr.scb.scsi_cmd[9]  = 0x00;
  2121.  
  2122.    /* Set the buffer size and allocate it if needed */
  2123.    lhdr.scb.system_buf_cnt = 4;
  2124.    if (bufsize) { free(buffer); }
  2125.    buffer = malloc(4);
  2126.    bufsize = 4;
  2127.  
  2128.    /* Our normal transfer SCB processing */
  2129.    psize = 4;
  2130.    dsize = 2;
  2131.    xfer.dev_handle = handle;
  2132.    xfer.sense_size = SENSE_SIZE;
  2133.    xfer.scb_header = &lhdr;
  2134.    xfer.flags      = 1;
  2135.    xfer.scb_phys   = 0;
  2136.  
  2137.    lhdr.next_scb_hdr = NULL;
  2138.    lhdr.tsb_adr = &tsb;
  2139.  
  2140.    lhdr.reserved1          = 0;
  2141.    lhdr.reserved2          = 0;
  2142.    lhdr.reserved3          = 0;
  2143.    lhdr.reserved4          = 0;
  2144.    lhdr.scb.tsb_adr        = &tsb;
  2145.    lhdr.scb.chain_adr      = NULL;
  2146.    lhdr.scb.system_buf_adr = buffer;
  2147.  
  2148.    /* Do it */
  2149.    retval = DosDevIOCtl (
  2150.       dh,                               /* Device handle returned by Open */
  2151.       (ULONG)0x80,                      /* Device category */
  2152.       (ULONG)0x52,                      /* Device-specific function code */
  2153.       (PVOID *)&xfer,                   /* Command-specific argument list */
  2154.       13,                               /* length of parm list  */
  2155.       &psize,                           /* length of parm list  */
  2156.       (PVOID *)&sense,                  /* Data area */
  2157.       SENSE_SIZE,                       /* length of data area  */
  2158.       &dsize                            /* Data area */
  2159.       );
  2160.  
  2161.    /* Tell how it went */
  2162.    if (retval) {
  2163.       printf("Failed getting size of TOC, rc = %d\n",(UCHAR)retval);
  2164.       return(retval);
  2165.       }
  2166.  
  2167.    /* Extract the full size of the TOC */
  2168.    new_size = (USHORT)buffer[1];
  2169.    new_size += 256*(USHORT)buffer[0];
  2170.    new_size += 2;
  2171.  
  2172.    lhdr.scb.scsi_cmd[7]  = (UCHAR)((new_size & 0xFF00) >> 8);
  2173.    lhdr.scb.scsi_cmd[8]  = (UCHAR)(new_size & 0x00FF);
  2174.  
  2175.    lhdr.scb.system_buf_cnt = (ULONG)new_size;
  2176.    if (bufsize) { free(buffer); }
  2177.    buffer = malloc(new_size);
  2178.    bufsize = new_size;
  2179.    lhdr.scb.system_buf_adr = buffer;
  2180.  
  2181.    /* Do it */
  2182.    retval = DosDevIOCtl (
  2183.       dh,                               /* Device handle returned by Open */
  2184.       (ULONG)0x80,                      /* Device category */
  2185.       (ULONG)0x52,                      /* Device-specific function code */
  2186.       (PVOID *)&xfer,                   /* Command-specific argument list */
  2187.       13,                               /* length of parm list  */
  2188.       &psize,                           /* length of parm list  */
  2189.       (PVOID *)&sense,                  /* Data area */
  2190.       SENSE_SIZE,                       /* length of data area  */
  2191.       &dsize                            /* Data area */
  2192.       );
  2193.  
  2194.    /* Tell how it went */
  2195.    if (retval == 0) {
  2196.       printf("Read of TOC worked\n");
  2197.       }
  2198.    else {
  2199.       printf("Failed getting TOC, rc = %d\n",(UCHAR)retval);
  2200.       }
  2201.    return(retval);
  2202.  
  2203. }
  2204.  
  2205. /* This function displays the valid commands */
  2206. void syntax(void)
  2207. {
  2208.    printf("quit     = quit                   ?        = help\n");
  2209.    printf("alloc    = Allocate a device      free     = free allocated device\n");
  2210.    printf("gen      = General SCB            other    = Send Other SCB\n");
  2211.    printf("capac    = Show device capacity   inq      = Device inquiry\n");
  2212.    printf("count    = Get device count       parms    = Get device parms\n");
  2213.    printf("timeout  = Set device timeout     rtime    = Read device timeout\n");
  2214.    printf("reset    = Reset device\n");
  2215.    printf("toc      = Read CDROM TOC         toc_m    = Read CDROM TOC (MSF)\n");
  2216.    printf("p_toc    = Display TOC            p_toc_m  = Display TOC (MSF)\n");
  2217.    printf("w_toc    = Write TOC to disk      w_toc_m  = Write TOC (MSF)\n");
  2218.    printf("mode_set = Mode Select Command    blk_size = Set block size\n");
  2219.    printf("speed          = Measure speed by reading lots of data\n");
  2220.    printf("read           = Read data from device (up to 64K bytes)\n");
  2221.    printf("rd_all/rd_some = Read data from device to file - binary\n");
  2222.    printf("p_data         = Display data buffer (up to 64 bytes)\n");
  2223.    printf("w_dat          = Write data to disk - printable form\n");
  2224.    printf("xw_dat         = Write data to disk - binary\n");
  2225.    printf("write          = Write data from file to device\n");
  2226.    printf("\n");
  2227.    printf("sense  = Get device sense data\n");
  2228.    printf("p_sns  = Display sense (interpreted)\n");
  2229.    printf("xp_sns = Display Sense (hex)\n");
  2230.    printf("p_tsb  = Display tsb (interpreted)\n");
  2231.    printf("xp_tsb = Display tsb (hex)\n");
  2232. }
  2233.  
  2234. /* This function displays a buffer in printable format */
  2235. void hexdisp(UCHAR *data, int count)
  2236. {
  2237.    char prtbuf[80];
  2238.    int  i;
  2239.    int  maxdisp;
  2240.    int  remaining;
  2241.    int  offset;
  2242.  
  2243.    remaining = count;
  2244.    offset = 0;
  2245.    while (remaining) {
  2246.       maxdisp = 16;
  2247.       if (16 > remaining) maxdisp = remaining;
  2248.       for (i=0; i<maxdisp; i++) { sprintf((prtbuf+(i*3)),"%02X ",*(data+offset+i)); }
  2249.       printf("%s\n",prtbuf);
  2250.       remaining -= maxdisp;
  2251.       offset += 16;
  2252.       }
  2253.  
  2254. }
  2255.  
  2256. /* This function writes a buffer to the output file in printable format */
  2257. void hexsave(UCHAR *data, int count)
  2258. {
  2259.    char prtbuf[80];
  2260.    int  i;
  2261.    int  maxdisp;
  2262.    int  remaining;
  2263.    int  offset;
  2264.    FILE *ofile;
  2265.    int   wrote_count;
  2266.  
  2267.    ofile = get_file("w");
  2268.    if (ofile == NULL) return;
  2269.    remaining = count;
  2270.    offset = 0;
  2271.    while (remaining) {
  2272.       maxdisp = 16;
  2273.       if (16 > remaining) maxdisp = remaining;
  2274.       for (i=0; i<maxdisp; i++) { sprintf((prtbuf+(i*3)),"%02X ",*(data+offset+i)); }
  2275.       wrote_count = fprintf(ofile,"%s\n",prtbuf);
  2276.       if (wrote_count < 0) {
  2277.          perror("Error writing data");
  2278.          return;
  2279.          }
  2280.       remaining -= maxdisp;
  2281.       offset += 16;
  2282.       }
  2283.    fclose(ofile);
  2284.    printf("Data wrote OK\n");
  2285.  
  2286. }
  2287.  
  2288. /* This function writes a buffer to the output file in binary format */
  2289. void binsave(UCHAR *data, int count)
  2290. {
  2291.    FILE *ofile;
  2292.    int   wrote_count;
  2293.  
  2294.    ofile = get_file("wb");
  2295.    if (ofile == NULL) return;
  2296.    wrote_count = fwrite(data,1, count, ofile);
  2297.    if (wrote_count < 0) {
  2298.       perror("Error writing data");
  2299.       return;
  2300.       }
  2301.    fclose(ofile);
  2302.    printf("Data wrote OK\n");
  2303.  
  2304. }
  2305.  
  2306. /* This function displays the Sense buffer in hex format */
  2307. void show_sense_x(void)
  2308. {
  2309.    hexdisp(sense, SENSE_SIZE);
  2310. }
  2311.  
  2312. /* This function displays the TSB buffer in hex format */
  2313. void show_tsb_x(void)
  2314. {
  2315.    hexdisp((UCHAR *)&tsb, sizeof(tsb_type));
  2316. }
  2317.  
  2318. /* This function displays the TSB buffer in interpreted format */
  2319. void show_tsb(void)
  2320. {
  2321.    printf("SCB_status            = %04X\n",tsb.SCB_status);
  2322.    printf("Retries               = %04X\n",tsb.retry_counts);
  2323.    printf("Residual Count        = %08X\n",tsb.residual_buffer_byte_count);
  2324.    printf("Residual Address      = %08X\n",tsb.residual_buffer_address);
  2325.    printf("Additional status len = %04X\n",tsb.additional_status_length);
  2326.    printf("SCSI Status code      = %01X\n",tsb.SCSI_status_code);
  2327.    printf("Command Status        = %02X\n",tsb.command_status);
  2328.    printf("Device error code     = %02X\n",tsb.device_error_code);
  2329.    printf("Command error code    = %02X\n",tsb.command_error_code);
  2330.    printf("Error modifier        = %04X\n",tsb.error_modifier);
  2331.    printf("Cache info            = %04X\n",tsb.cache_info);
  2332.    printf("Last SCB processed    = %04X\n",tsb.last_SCB_address_processed);
  2333. }
  2334.  
  2335. /* This function displays the sense buffer in interpreted format */
  2336. void show_sense(void)
  2337. {
  2338.    printf("Info Valid       = %01X\n",(sense[0] >> 7));
  2339.    printf("Error Class      = %01X\n",7 & (sense[0] >> 4));
  2340.    printf("Error Code       = %01X\n",(sense[0] & 0x0F));
  2341.    printf("Segment Number   = %02X\n",sense[1]);
  2342.    printf("Filemark seen    = %01X\n",(sense[2] >> 7));
  2343.    printf("End of Medium    = %01X\n",((0x40 & sense[2]) >> 6));
  2344.    printf("Invalid Length   = %01X\n",((0x20 & sense[2]) >> 5));
  2345.    printf("Sense Key        = %01X\n",(sense[2] & 0x0F));
  2346.    printf("Additional Data  = %02X\n",sense[12]);
  2347.    printf("Additional Data1 = %02X\n",sense[13]);
  2348. }
  2349.  
  2350. /* This function displays 64 bytes of a buffer */
  2351. void show_data(void)
  2352. {
  2353.    hexdisp(buffer, 64);
  2354. }
  2355.  
  2356. /* This function writes a buffer to the output file in printable form */
  2357. void save_data(void)
  2358. {
  2359.    hexsave(buffer, bufsize);
  2360. }
  2361.  
  2362. /* This function writes a buffer to the output file in binary */
  2363. void save_datab(void)
  2364. {
  2365.    binsave(buffer, bufsize);
  2366. }
  2367.  
  2368. /* This function fulls the sense buffer with 0's */
  2369. void clear_sense(void)
  2370. {
  2371.    int i;
  2372.    for (i=0; i<SENSE_SIZE; i++) { sense[i] = '\0'; }
  2373. }
  2374.  
  2375. /* This function reverses the byte order in a 16-bit value */
  2376. USHORT swap16(USHORT inval)
  2377. {
  2378.    USHORT temp;
  2379.  
  2380.    temp = 256*(inval  & 0xFFFF);
  2381.    temp += (inval >> 8);
  2382.    return(temp);
  2383.  
  2384. }
  2385.  
  2386. /* This function reverses the byte order in a 32-bit value */
  2387. ULONG swap32(ULONG inval)
  2388. {
  2389.    ULONG temp;
  2390.  
  2391.    temp = 0;
  2392.    temp += (inval >> 24) &  0x000000FF;
  2393.    temp += (inval >>  8) &  0x0000FF00;
  2394.    temp += (inval <<  8) &  0x00FF0000;
  2395.    temp += (inval << 24) &  0xFF000000;
  2396.    return(temp);
  2397.  
  2398. }
  2399.  
  2400. /* This function displays an interpreted TOC */
  2401. void show_toc(void)
  2402. {
  2403.    ULONG size;
  2404.    int   start_track, end_track;
  2405.    int   track_start, track_no;
  2406.    int   i;
  2407.    int   ctl;
  2408.    UCHAR adrctl;
  2409.  
  2410.    if (buffer == NULL) {
  2411.       printf("Buffer is empty\n");
  2412.       return;
  2413.       }
  2414.    size  = (ULONG)buffer[1];
  2415.    size += 256 * (ULONG)buffer[0];
  2416.    size += 2;
  2417.    if (size != bufsize) {
  2418.       printf("Buffer contents are not a TOC\n");
  2419.       return;
  2420.       }
  2421.  
  2422.    start_track = (int)buffer[2];
  2423.    end_track = (int)buffer[3];
  2424.    printf("First track = %d, last track = %d\n",start_track, end_track);
  2425.    for (i=start_track; i <= end_track; i++) {
  2426.       track_start  =         (int)buffer[11+(i-1)*8];
  2427.       track_start +=   256 * (int)buffer[10+(i-1)*8];
  2428.       track_start += 65536 * (int)buffer[ 9+(i-1)*8];
  2429.       adrctl =  buffer[5+(i-1)*8];
  2430.       ctl = (int)adrctl & 0x0F;
  2431.       track_no = (int)buffer[6+(i-1)*8];
  2432.       printf("Track %02X, ADR/CTL = %02X, Starting sector = %d\n",track_no,
  2433.                  adrctl, track_start);
  2434.       printf("    Track type - %s\n",ctl_msg[ctl]);
  2435.       }
  2436.    track_start  =         (int)buffer[11+end_track*8];
  2437.    track_start +=   256 * (int)buffer[10+end_track*8];
  2438.    track_start += 65536 * (int)buffer[ 9+end_track*8];
  2439.    adrctl =  buffer[5+end_track*8];
  2440.    ctl = (int)adrctl & 0x0F;
  2441.    track_no = (int)buffer[6+end_track*8];
  2442.    printf("Track %02X, ADR/CTL = %02X, Starting sector = %d\n",track_no,
  2443.               adrctl, track_start);
  2444.    printf("    Track type - %s",ctl_msg[ctl]);
  2445.    if (track_no == 0xAA) { printf(" - Leadout\n"); }
  2446.    else                  { printf("\n"); }
  2447.  
  2448.    return;
  2449.  
  2450. }
  2451.  
  2452. /* This function writes an interpreted TOC */
  2453. void write_toc(void)
  2454. {
  2455.    ULONG size;
  2456.    int   start_track, end_track;
  2457.    int   track_start, track_no;
  2458.    int   i;
  2459.    int   ctl;
  2460.    UCHAR adrctl;
  2461.    FILE  *ofile;
  2462.  
  2463.    if (buffer == NULL) {
  2464.       printf("Buffer is empty\n");
  2465.       return;
  2466.       }
  2467.    size  = (ULONG)buffer[1];
  2468.    size += 256 * (ULONG)buffer[0];
  2469.    size += 2;
  2470.    if (size != bufsize) {
  2471.       printf("Buffer contents are not a TOC\n");
  2472.       return;
  2473.       }
  2474.  
  2475.    ofile = get_file("w");
  2476.    if (ofile == NULL) { return; }
  2477.  
  2478.    start_track = (int)buffer[2];
  2479.    end_track = (int)buffer[3];
  2480.    fprintf(ofile,"First track = %d, last track = %d\n",start_track, end_track);
  2481.    for (i=start_track; i <= end_track; i++) {
  2482.       track_start  =         (int)buffer[11+(i-1)*8];
  2483.       track_start +=   256 * (int)buffer[10+(i-1)*8];
  2484.       track_start += 65536 * (int)buffer[ 9+(i-1)*8];
  2485.       adrctl =  buffer[5+(i-1)*8];
  2486.       ctl = (int)adrctl & 0x0F;
  2487.       track_no = (int)buffer[6+(i-1)*8];
  2488.       fprintf(ofile,"Track %02X, ADR/CTL = %02X, Starting sector = %d\n",track_no,
  2489.                  adrctl, track_start);
  2490.       fprintf(ofile,"    Track type - %s\n",ctl_msg[ctl]);
  2491.       }
  2492.    track_start  =         (int)buffer[11+end_track*8];
  2493.    track_start +=   256 * (int)buffer[10+end_track*8];
  2494.    track_start += 65536 * (int)buffer[ 9+end_track*8];
  2495.    adrctl =  buffer[5+end_track*8];
  2496.    ctl = (int)adrctl & 0x0F;
  2497.    track_no = (int)buffer[6+end_track*8];
  2498.    fprintf(ofile,"Track %02X, ADR/CTL = %02X, Starting sector = %d\n",track_no,
  2499.               adrctl, track_start);
  2500.    fprintf(ofile,"    Track type - %s",ctl_msg[ctl]);
  2501.    if (track_no == 0xAA) { fprintf(ofile," - Leadout\n"); }
  2502.    else                  { fprintf(ofile,"\n"); }
  2503.  
  2504.    fclose(ofile);
  2505.    printf("Write of TOC complete\n");
  2506.    return;
  2507.  
  2508. }
  2509.  
  2510. /* This function displays an interpreted TOC */
  2511. void show_toc_m(void)
  2512. {
  2513.    ULONG size;
  2514.    int   start_track, end_track;
  2515.    int   track_no;
  2516.    int   i;
  2517.    int   ctl;
  2518.    UCHAR adrctl;
  2519.  
  2520.    if (buffer == NULL) {
  2521.       printf("Buffer is empty\n");
  2522.       return;
  2523.       }
  2524.    size  = (ULONG)buffer[1];
  2525.    size += 256 * (ULONG)buffer[0];
  2526.    size += 2;
  2527.    if (size != bufsize) {
  2528.       printf("Buffer contents are not a TOC\n");
  2529.       return;
  2530.       }
  2531.  
  2532.    start_track = (int)buffer[2];
  2533.    end_track = (int)buffer[3];
  2534.    printf("First track = %d, last track = %d\n",start_track, end_track);
  2535.    for (i=start_track; i <= end_track; i++) {
  2536.       adrctl =  buffer[5+(i-1)*8];
  2537.       ctl = (int)adrctl & 0x0F;
  2538.       track_no = (int)buffer[6+(i-1)*8];
  2539.       printf("Track %02X, ADR/CTL = %02X, Start = %02d:%02d:%02d\n",track_no,
  2540.                  adrctl,buffer[ 9+(i-1)*8],
  2541.                         buffer[10+(i-1)*8],
  2542.                         buffer[11+(i-1)*8]);
  2543.       printf("    Track type - %s\n",ctl_msg[ctl]);
  2544.       }
  2545.    adrctl =  buffer[5+end_track*8];
  2546.    ctl = (int)adrctl & 0x0F;
  2547.    track_no = (int)buffer[6+end_track*8];
  2548.    printf("Track %02X, ADR/CTL = %02X, Start = %02d:%02d:%02d\n",track_no,
  2549.               adrctl,buffer[ 9+end_track*8],
  2550.                      buffer[10+end_track*8],
  2551.                      buffer[11+end_track*8]);
  2552.    printf("    Track type - %s",ctl_msg[ctl]);
  2553.    if (track_no == 0xAA) { printf(" - Leadout\n"); }
  2554.    else                  { printf("\n"); }
  2555.  
  2556.    return;
  2557.  
  2558. }
  2559.  
  2560. /* This function writes an interpreted TOC */
  2561. void write_toc_m(void)
  2562. {
  2563.    ULONG size;
  2564.    int   start_track, end_track;
  2565.    int   track_no;
  2566.    int   i;
  2567.    int   ctl;
  2568.    UCHAR adrctl;
  2569.    FILE  *ofile;
  2570.  
  2571.    if (buffer == NULL) {
  2572.       printf("Buffer is empty\n");
  2573.       return;
  2574.       }
  2575.    size  = (ULONG)buffer[1];
  2576.    size += 256 * (ULONG)buffer[0];
  2577.    size += 2;
  2578.    if (size != bufsize) {
  2579.       printf("Buffer contents are not a TOC\n");
  2580.       return;
  2581.       }
  2582.  
  2583.    ofile = get_file("w");
  2584.    if (ofile == NULL) { return; }
  2585.  
  2586.    start_track = (int)buffer[2];
  2587.    end_track = (int)buffer[3];
  2588.    fprintf(ofile,"First track = %d, last track = %d\n",start_track, end_track);
  2589.    for (i=start_track; i <= end_track; i++) {
  2590.       adrctl =  buffer[5+(i-1)*8];
  2591.       ctl = (int)adrctl & 0x0F;
  2592.       track_no = (int)buffer[6+(i-1)*8];
  2593.       fprintf(ofile,"Track %02X, ADR/CTL = %02X, Start = %02d:%02d:%02d\n",track_no,
  2594.                  adrctl,buffer[ 9+(i-1)*8],
  2595.                         buffer[10+(i-1)*8],
  2596.                         buffer[11+(i-1)*8]);
  2597.       fprintf(ofile,"    Track type - %s\n",ctl_msg[ctl]);
  2598.       }
  2599.    adrctl =  buffer[5+end_track*8];
  2600.    ctl = (int)adrctl & 0x0F;
  2601.    track_no = (int)buffer[6+end_track*8];
  2602.    fprintf(ofile,"Track %02X, ADR/CTL = %02X, Start = %02d:%02d:%02d\n",track_no,
  2603.               adrctl,buffer[ 9+end_track*8],
  2604.                      buffer[10+end_track*8],
  2605.                      buffer[11+end_track*8]);
  2606.    fprintf(ofile,"    Track type - %s",ctl_msg[ctl]);
  2607.    if (track_no == 0xAA) { fprintf(ofile," - Leadout\n"); }
  2608.    else                  { fprintf(ofile,"\n"); }
  2609.  
  2610.    fclose(ofile);
  2611.    printf("Write of TOC complete\n");
  2612.    return;
  2613.  
  2614. }
  2615.  
  2616. /* This function prompts the user for a filename and opens the file */
  2617. FILE *get_file(char *mode)
  2618. {
  2619.    char  fname[300];
  2620.    char  msg[300];
  2621.    FILE *f;
  2622.  
  2623.    printf("Enter filename (blank for SCSITEST.DAT): ");
  2624.    fflush(stdout);
  2625.    gets(fname);
  2626.  
  2627.    if (fname[0] == '\0') strcpy(fname,"scsitest.dat");
  2628.  
  2629.    f = fopen(fname,mode);
  2630.  
  2631.    sprintf(msg,"Error opening '%s'",fname);
  2632.    if (f == NULL) { perror(msg); }
  2633.  
  2634.    return(f);
  2635.  
  2636. }
  2637.  
  2638. int    copy_all(USHORT handle)
  2639. {
  2640.    FILE *ofile;
  2641.    int   rc;
  2642.  
  2643.    /* Get the file and open it */
  2644.    ofile = get_file("wb");
  2645.  
  2646.    /* Get the number of blocks and block size */
  2647.    rc = dev_capacity(handle, 1);
  2648.    if (rc) return;
  2649.  
  2650.    /* Do the read */
  2651.    printf("Copying from sector 0 for %d sectors - sector size = %d\n",
  2652.            last_block,block_len);
  2653.    rc = read_many(handle, 0, last_block, block_len, ofile);
  2654.    if (!rc) { printf("Copy went OK\n"); }
  2655.  
  2656.    /* Close the file */
  2657.    fclose(ofile);
  2658. }
  2659.  
  2660. int    copy_some(USHORT handle)
  2661. {
  2662.    FILE *ofile;
  2663.    int   rc;
  2664.    char           input_char[10];
  2665.    char          *stopstr;
  2666.    int            sector;
  2667.    int            count;
  2668.  
  2669.    /* Get the number of blocks and block size */
  2670.    rc = dev_capacity(handle, 1);
  2671.    if (rc) {
  2672.       printf("Error %d getting size of disk in drive\n",rc);
  2673.       return;
  2674.       }
  2675.  
  2676.    /* Get the start and number of sectors */
  2677.    printf("Enter starting sector to read: ");
  2678.    fflush(stdout);
  2679.    gets(input_char);
  2680.    sector = strtoul(input_char, &stopstr, 0);
  2681.    printf("Enter number of sectors to read: ");
  2682.    fflush(stdout);
  2683.    gets(input_char);
  2684.    count = strtoul(input_char, &stopstr, 0);
  2685.  
  2686.    /* Get the file and open it */
  2687.    ofile = get_file("wb");
  2688.  
  2689.    /* Do the read */
  2690.    printf("Copying from sector %d for %d sectors - sector size = %d\n",
  2691.            sector,count,block_len);
  2692.    rc = read_many(handle, sector, count, block_len, ofile);
  2693.    if (!rc) { printf("Copy went OK\n"); }
  2694.  
  2695.    /* Close the file */
  2696.    fclose(ofile);
  2697. }
  2698.  
  2699. ULONG get_curr_time(void)
  2700. {
  2701.   ULONG temp;
  2702.   DosQuerySysinfo(QSV_MS_COUNT,QSV_MS_COUNT,(void *)&temp,4);
  2703.   return(temp);
  2704. }
  2705.  
  2706. int    time_read(USHORT handle)
  2707. {
  2708.    int   rc;
  2709.    int   loops;
  2710.    ULONG curr_time;
  2711.    ULONG strt_time;
  2712.    ULONG end_time;
  2713.    int   sector;
  2714.    int   num_blks;
  2715.    int   seconds;
  2716.    int   blk_size;
  2717.  
  2718.  
  2719.    /* Get the number of blocks and block size */
  2720. /* rc = dev_capacity(handle, 1);
  2721.    if (rc) {
  2722.       printf("Error %d getting size of disk in drive\n",rc);
  2723.       return;
  2724.       }     */
  2725.  
  2726.    blk_size = 2048;
  2727.    num_blks = 20;
  2728.    seconds  = 40;
  2729.    sector   = 1;
  2730.  
  2731.    rc = read_many_nofile(handle, sector, num_blks, blk_size);
  2732.  
  2733.    if (rc) {
  2734.       printf("Error %d on READ\n");
  2735.       return(-1);
  2736.       }
  2737.    sector = sector + num_blks;
  2738.  
  2739.    /* Get the current milliseconds since IPL */
  2740.    strt_time = get_curr_time();
  2741.  
  2742.    /* Figure out 10 seconds from now */
  2743.    end_time = strt_time + (seconds * 1000);
  2744.  
  2745.    /* Do */
  2746.    loops = 0;
  2747.    do {
  2748.       /* Read a chunk */
  2749.       rc = read_many_nofile(handle, sector, num_blks, blk_size);
  2750.  
  2751.       if (rc) {
  2752.          printf("Error %d on READ\n");
  2753.          return(-1);
  2754.          }
  2755.       sector = sector + num_blks;
  2756.       loops++;
  2757.  
  2758.       /* Get the current milliseconds since IPL */
  2759.       curr_time = get_curr_time();
  2760.  
  2761.       } while (end_time > curr_time);
  2762.  
  2763.    printf("Read at %d bytes/second\n",(num_blks * loops * blk_size) / seconds);
  2764.    return(0);
  2765.  
  2766.  
  2767. }
  2768.  
  2769.