home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_3.5 / Examples / HDWrench / tester.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-17  |  77.3 KB  |  3,076 lines

  1. /*    tester.c    test hdwrench.library for some basic functions.
  2.  *        $VER: Tester.c 44.4 (18.9.99) © Wizardess Designs and Joanne Dow 1999 All rights reserved
  3.  *
  4.  *        © Copyright 1999 by Joanne Dow, Wizardess Designs
  5.  *        All Rights Reserved
  6.  *
  7.  *    Tester.c can be taken both as a test program and as an example of usage,
  8.  *    in spite of its cut and paste, overblown and ugly coding style, of usage
  9.  *    for each of the "hdwrench.library" API entry points.
  10.  *
  11.  *    Functions:
  12.  *        Support:
  13.  *        1) Open device and close device
  14.  *            BU baseunit.
  15.  *        Translations:
  16.  *
  17.  *        2) Read RDB from <file>.list and write as mountfile to <file>..list.
  18.  *        3) Read RDB from <file>.list and write as RDBs to <file>..rdb.
  19.  *        4) Read RDB from <file>.rdb and write as mountfile to <file>..list.
  20.  *        5) Read RDB from <file>.rdb and write as RDBs to <file>..rdb.
  21.  *        6) Read Mountfile from memory and write as Mountfile to memory.
  22.  *            (uses 000.list for input and writes to "foo" and screen.)
  23.  *        7) Read Mountfile from memory and write as RDB Structs to memory.
  24.  *            (uses 000.list for input and writes to "foo".)
  25.  *        8)  Read RDBStructs memory and write as RDB Structs to memory.
  26.  *            (uses 000..rdb for input and writes to "bar".)
  27.  *
  28.  *        Basic Disk acccesses:
  29.  *        9) Read RDB from disk and write as mountfile to <file>...list.
  30.  *        10) Perform SCSI Inquiry and report results up to 40 bytes.
  31.  *        11) Perform SCSI ModeSense  and report results up to 255 bytes.
  32.  *        12) Perform SCSI Read Capacity and report disk size.
  33.  *        13) Perform SCSI Test Unit Ready and report device readiness.
  34.  *
  35.  *        Complex Disk Accesses...
  36.  *        14) Find Disk Name returning in string variable.
  37.  *        15) Find Controller self-ID returning in ULONG (which Commododo fails!).
  38.  *        16) Report last available block on the drive.
  39.  *        17) Generate default drive parameters.
  40.  *        18) Read and report raw sector 'MS'.    (Not really complex but...)
  41.  *        19) Find all valid disks on a given controller
  42.  *
  43.  *        Dangerous disk accesses:
  44.  *        20) Raw write to a block of low disk. (Safe write - I hope!)
  45.  *        21) Write with checksum to a block of low disk. (Safe write - I hope!)
  46.  *        22) Read RDBs from <file.list> and write to disk. (The biggie!)
  47.  *        23) Read RDBs from disk and write to RDBStructs to <file>.rdb.
  48.  *        24) Read RDBStructs from <file>.rdb and write to <file>...rdb.
  49.  *        25) Verify data on disk.
  50.  *        26) Read RDBStructs from <file>...rdb and write to Disk.
  51.  *        27) Read RDBs from disk and write RDB Structs memory thence to file
  52.  *             and console as hex.
  53.  *        100) Format Drive - VERY DANGEROUS!
  54.  *
  55.  *        Presumes "scsi.device" else enter "DEVICE devicename".
  56.  */
  57. #include    <stdio.h>
  58. #include    <stdarg.h>
  59. #include    <string.h>
  60. #include    <ctype.h>
  61. #include    <stdlib.h>
  62. #include    <math.h>
  63. #include    <dos.h>
  64. #include    <exec/types.h>
  65. #include    <exec/ports.h>
  66. #include    <exec/libraries.h>
  67. #include    <exec/io.h>
  68. #include    <exec/nodes.h>
  69. #include    <exec/lists.h>
  70. #include    <exec/tasks.h>
  71. #include    <exec/memory.h>
  72. #include    <exec/execbase.h>
  73. #include    <devices/trackdisk.h>
  74. #include    <libraries/dos.h>
  75. #include    <libraries/dosextens.h>
  76. #include    <dos/filehandler.h>
  77. #include    <devices/hardblocks.h>
  78. #include    <devices/scsidisk.h>
  79. #include    <intuition/intuition.h>
  80. #include    <workbench/workbench.h>
  81. #include    <workbench/icon.h>
  82. #include    <workbench/startup.h>
  83. #include    <dos/rdargs.h>
  84. #include    <dos/dostags.h>
  85.  
  86. #include    <proto/dos.h>
  87. #include    <proto/exec.h>
  88. #include    <pragmas/exec_pragmas.h>
  89. #include    <pragmas/disk_pragmas.h>
  90. #include    <pragmas/dos_pragmas.h>
  91.  
  92. #include    "HDWrench.h"
  93. #include    "HDWrench_pragmas.h"
  94. #define        USE_SUGGESTED_MESSAGES
  95. #include    "HDW_CallbackMsgs.h"
  96.  
  97. struct HDWLibrary    *HDWBase = NULL;
  98.  
  99. #define TEMPLATE "TEST/N/A,BU/N/K,FILE/K,MS/N/K,DEVICE/K"
  100. #define NUM_ARGS 5
  101.  
  102. char hexits [] = "0123456789abcdef";
  103. char spaces [] = "                                                ";
  104.  
  105. enum { ARG_TEST, ARG_BU, ARG_FILE, ARG_MS, ARG_DEVICE };
  106.  
  107. LONG             ArgArray [ NUM_ARGS ];
  108.  
  109. char            *inmembuffer    = NULL;
  110. char            *outmembuffer    = NULL;
  111. BOOL             deviceopen        = FALSE;
  112. struct RDArgs    *Args             = NULL;
  113. BOOL             aborted        = FALSE;
  114. ULONG             testnum;
  115.  
  116. long __stdargs __saveds __asm CallBack ( register __a0 HDWCallbackMsg *msg );
  117.  
  118. void usage ( void )
  119. {
  120.     printf ( "tester %s\n", TEMPLATE );
  121.     printf ( "Gotta have a test number!\n" );
  122.     printf ( "1)  Basic Open and Close Device\n" );
  123.     printf ( "2)  Read RDB from <file>.list and write as mountfile to <file>..list.\n");
  124.     printf ( "3)  Read RDB from <file>.list and write as RDBs to <file>..rdb.\n" );
  125.     printf ( "4)  Read RDBs from <file>..rdb and write Mountfile to <file>...list.\n" );
  126.     printf ( "5)  Read Mountfile from disk and write as mountfile to memory.\n");
  127.     printf ( "6)  Read Mountfile from memory and write as Mountfile to memory.\n");
  128.     printf ( "7)  Read Mountfile from memory and write as RDB Structs to memory.\n");
  129.     printf ( "8)  Read RDBStructs memory and write as RDB Structs to memory.\n");
  130.     printf ( "9)  Read RDB from disk and write as mountfile to <file>...list.\n");
  131.     printf ( "10) Perform SCSI Inquiry and report results up to 40 bytes.\n");
  132.     printf ( "11) Perform SCSI ModeSense  and report results up to 256 bytes.\n");
  133.     printf ( "12) Perform SCSI Read Capacity and report disk size.\n");
  134.     printf ( "13) Perform SCSI Test Unit Ready and report device readiness.\n");
  135.     printf ( "14) Find Disk Name returning in string variable.\n" );
  136.     printf ( "15) Find Controller self-ID returning in ULONG (which Commododo fails!).\n" );
  137.     printf ( "16) Report last available block on the drive.\n");
  138.     printf ( "17) Generate default drive parameters.\n" );
  139.     printf ( "18) Read and report raw sector 'MS'.\n");
  140.     printf ( "19) Find all valid disks on a given controller.\n");
  141.     printf ( "20) Raw write to a block of low disk. (Safe write - I hope!)\n");
  142.     printf ( "21) Write with checksum to a block of low disk. (Safe write - I hope!)\n");
  143.     printf ( "22) Read RDBs from <file.list> and write to disk. (The biggie!)\n" );
  144.     printf ( "23) Read RDBs from disk and write to file <file>.rdb\n");
  145.     printf ( "24) Read RDBStructs from <file>.rdb and write to <file>...rdb.\n");
  146.     printf ( "25) Verify data on disk.\n" );
  147.     printf ( "26) Read RDBStructs from <file>...rdb and write to Disk.\n");
  148.     printf ( "27) Read RDBs from disk. Write RDB Structs to memory thence to file and console as hex.\n\n" );
  149.     printf ( "100) Format Drive - VERY DANGEROUS!\n" );
  150. }
  151.  
  152. int btrap ( void )
  153. {
  154.     printf ( "\n***BREAK***\n" );
  155.     if (( testnum != 25 ) && ( testnum != 100 ))
  156.         exit(20);
  157.     aborted = TRUE;
  158.     return 0;
  159. }
  160.  
  161. void gone ( void )
  162. {
  163.     if ( deviceopen )
  164.     {
  165.         printf ( "Closing opened device\n" );
  166.         HDWCloseDevice();
  167.         deviceopen = FALSE;
  168.     }
  169.  
  170.     if ( outmembuffer )
  171.     {
  172.         free ( outmembuffer );
  173.         outmembuffer = NULL;
  174.     }
  175.  
  176.     if ( inmembuffer )
  177.     {
  178.         free ( inmembuffer );
  179.         inmembuffer = NULL;
  180.     }
  181.  
  182.     if ( Args )
  183.         FreeArgs ( Args );
  184.  
  185.     if ( HDWBase )
  186.         CloseLibrary ( ( struct Library *) HDWBase );
  187.     HDWBase = NULL;
  188.  
  189.     printf ("Aw gone!\n");
  190. }
  191.  
  192. void printhex ( BYTE * buf, int size )
  193. {
  194.     int i;
  195.     int j;
  196.     char c;
  197.  
  198.     for ( i=0, j = 0; i < size; i++)
  199.     {
  200.         if (( i & 0x0f ) == 0 )
  201.             printf ( "%c%c%c%c: ",
  202.                      hexits [( i >> 12 ) & 0xf ],
  203.                      hexits [( i >> 8  ) & 0xf ],
  204.                      hexits [( i >> 4  ) & 0xf ],
  205.                      hexits [  i         & 0xf ] );
  206.         c = buf [ i ];
  207.         printf ( "%c%c ", hexits [( c>>4 ) & 0xf], hexits [ c & 0xf ]);
  208.         if ( ( i & 0x3 )  == 3 )
  209.         {
  210.             if ( ( i & 0xf ) == 15 )
  211.             {
  212.                 for ( ; j <= i; j++ )
  213.                 {
  214.                     c = buf [ j ];
  215.                     if ( isalnum ( c ) || c == ' ' )
  216.                         printf ( "%c", c );
  217.                     else
  218.                         printf ( "." );
  219.  
  220. //                    if ( ( j & 0x7 )  == 7 )
  221. //                        printf ( " " );
  222.                 }
  223.                 printf ( "\n" );
  224.             }
  225.             else
  226.                 printf ( " " );
  227.         }
  228.     }
  229.     if ( j != i )
  230.     {
  231.         int k = (( i - 1 ) & 0xf ) + 1;
  232.  
  233.         k = k * 3 + ( k > 8 );
  234.         printf ( "%s", &spaces [ k ] );
  235.  
  236.         for ( ; j < i; j++ )
  237.         {
  238.             c = buf [ j ];
  239.             if ( isalnum ( c ) )
  240.                 printf ( "%c ", c );
  241.             else
  242.                 printf ( ". " );
  243.  
  244. //            if ( ( j & 0x7 )  == 7 )
  245. //                printf ( "  " );
  246.         }
  247.         printf ( "\n" );
  248.     }
  249. }
  250.  
  251. int
  252. main ( int argc, char **argv)
  253. {
  254.     char             *filename;
  255.     char              devicename[60];
  256.     FILE             *workfile;
  257.     ULONG              baseunit;
  258.     ULONG              mspage;
  259.     ULONG              sizeb;
  260.     ULONG              sizememneeded;
  261.  
  262.     char              realfilename[256];
  263.     ULONG              rsuccess;
  264.     USHORT              rwsuccess;
  265.  
  266.     ArgArray [ 0 ] =
  267.     ArgArray [ 1 ] =
  268.     ArgArray [ 2 ] =
  269.     ArgArray [ 3 ] =
  270.     ArgArray [ 4 ] = 0;
  271.  
  272.     puts( "Tester, the HDWrench test program.\n" );
  273.  
  274.     atexit( gone );
  275.     if ( onbreak ( &btrap ))
  276.     {
  277.         printf ( "Break trap not installed!" );
  278.         exit ( 20 );
  279.     }
  280.  
  281.     Args = ReadArgs( TEMPLATE, ArgArray, NULL );
  282.     if ( Args )
  283.     {
  284.         //    ARG_TEST, ARG_BU, ARG_FILE, ARG_MS, ARG_DEVICE
  285.         testnum        = (ULONG)    ArgArray [ ARG_TEST ];
  286.         baseunit    = (ULONG)    ArgArray [ ARG_BU ];
  287.         filename    = (char *)    ArgArray [ ARG_FILE ];
  288.         mspage        = (ULONG)    ArgArray [ ARG_MS ];
  289.         memset ( devicename, 0, 60 );
  290.         if ( ArgArray [ ARG_DEVICE ] != NULL )
  291.             strncpy ( devicename, (char *)    ArgArray [ ARG_DEVICE ], 59 );
  292.         else
  293.             strncpy ( devicename, "scsi.device", 59 );
  294.  
  295.         if ( testnum )
  296.             testnum = *(ULONG*) testnum;
  297.         else
  298.             testnum = 0;
  299.  
  300.         if ( baseunit)
  301.             baseunit = *(ULONG*) baseunit;
  302.         else
  303.             baseunit = (ULONG) -1L;
  304.  
  305.         if ( mspage )
  306.             mspage = *(ULONG*) mspage;
  307.  
  308.         printf ( "Test Num    = %ld\n", testnum );
  309.         printf ( "Base Unit    = %ld\n", baseunit );
  310.         if ( filename )
  311.             printf ( "Filename    = %s\n", filename );
  312.         else
  313.             printf ( "Filename    = <none>\n" );
  314.         printf ( "MS Page        = %ld\n", mspage);
  315.         printf ( "Devicename    = %s\n\n\n", devicename);
  316.  
  317.         if (( HDWBase = ( struct HDWLibrary *) OpenLibrary ( HDWBaseName, 0)) == NULL )
  318.         {
  319.             printf( "Failed to open HDWBase!\n");
  320.             exit ( 10 );
  321.         }
  322.  
  323.         switch ( testnum )
  324.         {
  325.         case 0:        /* No test! */
  326.         default:
  327.             usage();
  328.             break;
  329.  
  330. /******************************************
  331.  *
  332.  *    1
  333.  *        BASIC OPENDEVICE/CLOSEDEVICE TEST
  334.  *
  335.  *****************************************/
  336.         case 1:    // Basic Open and Close Device
  337.             printf ( "1) Basic Open and Close Device\n\n" );
  338. //    BOOL __saveds __asm         HDWOpenDevice ( register __a0 char *DevName,
  339. //                                             register __d0 ULONG unit );
  340. //    void __saveds __asm         HDWCloseDevice ( void );
  341.             if ( baseunit == (ULONG) -1L )
  342.             {
  343.                 printf ( "You must enter a BU, Base Unit, number\n");
  344.                 break;
  345.             }
  346.             // Open device here.
  347.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  348.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  349.             if ( deviceopen )
  350.             {
  351.                 printf ( "Closing opened device\n" );
  352.                 HDWCloseDevice();
  353.                 deviceopen = FALSE;
  354.             }
  355.             else
  356.                 printf ( "No device was opened!\n");
  357.             break;
  358.  
  359. /******************************************
  360.  *
  361.  *    2-4
  362.  *        BASIC READ/WRITE FILE TESTS
  363.  *
  364.  *****************************************/
  365.         case 2:    // Read RDB from <file>.list and write as mountfile to <file>..list.
  366. //    ULONG __saveds __asm
  367. //    ReadMountfile ( register __d0 ULONG unit,
  368. //                    register __a0 char * filename,
  369. //                    register __a1 char *controller )
  370. /* HDW_ReadMountfile()
  371.  *    Description:
  372.  *        Parse a mounfile into internal RDB structures.
  373.  *
  374.  *    Direct Inputs:
  375.  *        filename        Pointer to mountfile in memory null terminated
  376.  *        unit            Unit number to masquarade as.
  377.  *
  378.  *    Indirect Inputs:
  379.  *
  380.  *    Direct Outputs:
  381.  *        ret            error 0 if success else error indication
  382.  *
  383.  *    Indirect Outputs:
  384.  *        RDB structures built in memory
  385.  *
  386.  *    Local Calls:
  387.  *        parse ()
  388.  *
  389.  *    OS Calls:
  390.  *        fclose ()
  391.  *        fopen ()
  392.  *
  393.  *    Algorithm:
  394.  *        If RDBs open then fail
  395.  *        If file open close it.
  396.  *        NULL memp
  397.  *        if filename null then fail
  398.  *        if Open filename fails then fail
  399.  *        parse data as it comes until null character.
  400.  *        return errors encountered in parse
  401.  *
  402.  *    Code:
  403.  *        Joanne Dow, Wizardess Designs, Jan 1999
  404.  */
  405. /* HDW_WriteMountfile()
  406.  *    Description:
  407.  *        Write to filename given from internal RDB structures in mountfile
  408.  *        format. Check for matching files if filename entry is present in
  409.  *        RDB structures and write appropriate FS and DriveInit code files.
  410.  *
  411.  *    Direct Inputs:
  412.  *        filename    pointer to the name of the file to be written.
  413.  *        flags        Flag what should be written to files.
  414.  *        ldir        L: directory path to use or NULL. (Use "L:" if null.)
  415.  *
  416.  *    Indirect Inputs:
  417.  *        Mountfile and any filesystem files or device init files written.
  418.  *
  419.  *    Direct Outputs:
  420.  *        ret            error 0 if success else error indication
  421.  *
  422.  *    Indirect Outputs:
  423.  *        Internal file structures written to disk in mountfile format.
  424.  *
  425.  *    Local Calls:
  426.  *        print ()
  427.  *
  428.  *    OS Calls:
  429.  *        fclose ()
  430.  *        fopen ()
  431.  *
  432.  *    Algorithm:
  433.  *        If no RDBs stored or file open fails exit with error
  434.  *        print () mountfile to file.
  435.  *        return accumulated error
  436.  *
  437.  *    Code:
  438.  *        Joanne Dow, Wizardess Designs, Jan 1999
  439.  */
  440. //    ULONG __saveds __asm
  441. //    WriteMountfile ( register __a0 char *filename,
  442. //                     register __a1 char *ldir,
  443. //                     register __d0 ULONG unit )
  444.             printf ( "2) Read RDB from <file>.list and write as mountfile to <file>..list.\n\n");
  445.             if ( !filename )
  446.             {
  447.                 printf ( "Need a filename\n" );
  448.                 break;
  449.             }
  450.             if ( strlen( filename ) > 248 )
  451.             {
  452.                 printf ( "Filename: %s is too long!\n", filename );
  453.                 break;
  454.             }
  455.             if ( baseunit == (ULONG) -1L )
  456.             {
  457.                 printf ( "Need a base unit for this command.\n" );
  458.                 break;
  459.             }
  460.             sprintf ( realfilename, "%s%s", filename, ".list" );
  461.             rsuccess = ReadMountfile ( baseunit, realfilename, devicename );
  462.             if ( rsuccess == 0 )
  463.             {
  464.                 sprintf ( realfilename, "%s%s", filename, "..list" );
  465.                 rsuccess = WriteMountfile ( realfilename, "sys:", baseunit );
  466.                 if ( rsuccess == 0 )
  467.                     printf ( "You should have a new %s waiting.\n", realfilename );
  468.                 else
  469.                     printf ( "Mountfile write failed: %d\n", rsuccess );
  470.             }
  471.             else
  472.             {
  473.                     printf ( "Mountfile read failed: %d\n", rsuccess );
  474.                     break;
  475.             }
  476.             break;
  477.  
  478.         case 3:
  479. //    ULONG __saveds __asm
  480. //    ReadMountfile ( register __d0 ULONG unit,
  481. //                    register __a0 char * filename,
  482. //                    register __a1 char *controller )
  483. /* HDW_WriteRDBStructs()
  484.  *    Description:
  485.  *        (Write RDBs to file instead of RDB area of disk.)
  486.  *        Write the internal RDB structures to disk exactly as in memory.
  487.  *
  488.  *    Direct Inputs:
  489.  *        Filename        Name of file to write. NB: This will clobber duplicates
  490.  *
  491.  *    Indirect Inputs:
  492.  *        RDB structures in memory
  493.  *
  494.  *    Direct Outputs:
  495.  *        ret            error 0 if success else error indication
  496.  *
  497.  *    Indirect Outputs:
  498.  *        File written
  499.  *
  500.  *    Local Calls:
  501.  *
  502.  *    OS Calls:
  503.  *        fclose ()
  504.  *        fopen ()
  505.  *        fwrite ()
  506.  *
  507.  *    Algorithm:
  508.  *        if no RDBs in memory of file open fails exit with error
  509.  *        else
  510.  *            pointer = Basepointer->next
  511.  *            while pointer
  512.  *                translate and write block to disk file
  513.  *                pointer = pointer->next
  514.  *            endwhile
  515.  *        endif
  516.  *
  517.  *    Code:
  518.  *        Joanne Dow, Wizardess Designs, Jan 1999
  519.  */
  520. //    ULONG __saveds __asm
  521. //    WriteRDBStructs ( register __a0 char *filename )
  522.             printf ( "3)  Read RDB from <file>.list and write as RDBs to <file>..rdb.\n\n" );
  523.             if ( !filename )
  524.             {
  525.                 printf ( "Need a filename\n" );
  526.                 break;
  527.             }
  528.             if ( strlen( filename ) > 248 )
  529.             {
  530.                 printf ( "Filename: %s is too long!\n", filename );
  531.                 break;
  532.             }
  533.             if ( baseunit == (ULONG) -1L )
  534.             {
  535.                 printf ( "Need a base unit for this command.\n" );
  536.                 break;
  537.             }
  538.             sprintf ( realfilename, "%s%s", filename, ".list" );
  539.             rsuccess = ReadMountfile ( baseunit, realfilename, devicename );
  540.             if ( rsuccess == 0 )
  541.             {
  542.                 sprintf ( realfilename, "%s%s", filename, "..rdb" );
  543.  
  544.                 rsuccess = WriteRDBStructs ( realfilename );
  545.                 if ( rsuccess == 0 )
  546.                     printf ( "You should have a new %s waiting.\n", realfilename );
  547.                 else
  548.                     printf ( "RDBfile write failed: %d\n", rsuccess );
  549.             }
  550.             else
  551.             {
  552.                     printf ( "Mountfile read failed: %d\n", rsuccess );
  553.                     break;
  554.             }
  555.             break;
  556.  
  557.         case 4:
  558. /* HDW_ReadRDBStructs()
  559.  *    Description
  560.  *        (Read RDBs from file instead of RDB area of disk.)
  561.  *        Read the dumped RDB file structures from the file into internal
  562.  *        memory. (NB: Only actual declared RDB areas are included in the
  563.  *        structures as written.)
  564.  *        NB: The RDB structures read MUST have their relative block numbers
  565.  *        written correctly.  They are used when writing to disk, even if
  566.  *        changed in writing.
  567.  *
  568.  *    Direct Inputs:
  569.  *        filename    pointer to the name of the file to be written. This
  570.  *                    file will be unconditionally overwritten if present.
  571.  *
  572.  *    Indirect Inputs:
  573.  *        Internal RDB structures as loaded.
  574.  *
  575.  *    Direct Outputs:
  576.  *        ret            error 0 if success else error indication
  577.  *
  578.  *    Indirect Outputs:
  579.  *        Internal RDB structures written to the filename indicated.
  580.  *
  581.  *    Local Calls:
  582.  *        ClearBlockList ()
  583.  *        ScanList ()
  584.  *
  585.  *    OS Calls:
  586.  *        fclose ()
  587.  *        fopen ()
  588.  *        fread ()
  589.  *
  590.  *    Algorithm:
  591.  *        If RDBs in memory or file open fails return error code
  592.  *        else
  593.  *            while ( not end of file )
  594.  *                allocate block
  595.  *                block read the block from disk file
  596.  *                switch type
  597.  *                  case RDSK        Add to front of list
  598.  *                  case PART        Add after RDSK entry and other PART entries
  599.  *                                if any else front of list
  600.  *                  case BADB        Add just after RDSK if any.
  601.  *                  case FSHD        Add after last PART entries if any
  602.  *                  case LSEG        Add to end of list in order encountered
  603.  *                  otherwise        Ignore!!!!
  604.  *                endswitch
  605.  *            endwhile
  606.  *        endif
  607.  *
  608.  *    Code:
  609.  *        Joanne Dow, Wizardess Designs, Jan 1999
  610.  */
  611. //ULONG __saveds __asm
  612. //HDW_ReadRDBStructs ( register __a0 char *filename, register __d0 unit )
  613.             printf ( "4)  Read RDBs from <file>..rdb and write Mountfile to <file>...list.\n\n" );
  614.             if ( !filename )
  615.             {
  616.                 printf ( "Need a filename\n" );
  617.                 break;
  618.             }
  619.             if ( strlen( filename ) > 248 )
  620.             {
  621.                 printf ( "Filename: %s is too long!\n", filename );
  622.                 break;
  623.             }
  624.             if ( baseunit == (ULONG) -1L )
  625.             {
  626.                 printf ( "Need a base unit for this command.\n" );
  627.                 break;
  628.             }
  629.             sprintf ( realfilename, "%s%s", filename, "..rdb" );
  630.             rsuccess = ReadRDBStructs ( realfilename, baseunit );
  631.             if ( rsuccess == 0 )
  632.             {
  633.                 sprintf ( realfilename, "%s%s", filename, "...list" );
  634.  
  635.                 rsuccess = WriteMountfile ( realfilename, "sys:", baseunit );
  636.                 if ( rsuccess == 0 )
  637.                     printf ( "You should have a new %s waiting.\n", realfilename );
  638.                 else
  639.                     printf ( "MountFile write failed: %d\n", rsuccess );
  640.             }
  641.             else
  642.             {
  643.                     printf ( "RDB file read failed: %d\n", rsuccess );
  644.                     break;
  645.             }
  646.             break;
  647.  
  648.  
  649. /******************************************
  650.  *
  651.  *    5-8
  652.  *        BASIC INMEMORY READ/WRITE TESTS
  653.  *
  654.  *****************************************/
  655.         case 5:
  656. /*
  657.  * HDW_OutMemMountfile()
  658.  *    Description:
  659.  *        Write RDBs into a block of memory as null terminated mountfile text.
  660.  *        If block supplied is too small fail. If memp = NULL return size needed
  661.  *        but no written data.
  662.  *
  663.  *    Direct Inputs:
  664.  *        memp        Pointer to block of memory
  665.  *        sizeb        size of block of memory
  666.  *        sizew        Pointer to size written
  667.  *
  668.  *    Indirect Inputs:
  669.  *        RDB structures in memory
  670.  *
  671.  *    Direct Outputs:
  672.  *        ret            error code
  673.  *        sizew        size written
  674.  *
  675.  *    Indirect Outputs:
  676.  *        Block of memory written
  677.  *
  678.  *    Local Calls:
  679.  *        print ()
  680.  *
  681.  *    OS Calls:
  682.  *        fclose ()
  683.  *
  684.  *    Algorithm:
  685.  *        if file open then close it.
  686.  *        if memory open then null it.
  687.  *        if RDBs not open then fail
  688.  *        set memp to input vector (NULL is legitimate for returning size)
  689.  *        Set maximum sze value per passed in value or "huge" of memp == NULL
  690.  *        Call print() to generate the RDBs into the memory block
  691.  *        set size written value
  692.  *        return accumulated errors.
  693.  *
  694.  *    Code:
  695.  *        Joanne Dow, Wizardess Designs, Jan 1999
  696.  */
  697. //ULONG __saveds __asm
  698. //HDW_OutMemMountfile ( register __a0 char *mfp,
  699. //                      register __a1 ULONG *sizew,
  700. //                      register __d0 ULONG sizeb,        // Size of buffer
  701. //                      register __d1 ULONG unit )
  702.             printf ( "5) Read Mountfile from disk and write as mountfile to memory.\n\n");
  703.             /* More specifically read Mountfile from disk and write as mountfile to
  704.              * printing results to stdout.
  705.              */
  706.             if ( !filename )
  707.             {
  708.                 printf ( "Need a filename\n" );
  709.                 break;
  710.             }
  711.             if ( strlen( filename ) > 248 )
  712.             {
  713.                 printf ( "Filename: %s is too long!\n", filename );
  714.                 break;
  715.             }
  716.             if ( baseunit == (ULONG) -1L )
  717.             {
  718.                 printf ( "Need a base unit for this command.\n" );
  719.                 break;
  720.             }
  721.             sprintf ( realfilename, "%s%s", filename, ".list" );
  722.             rsuccess = ReadMountfile ( baseunit, realfilename, devicename );
  723.             if ( rsuccess == 0 )
  724.             {
  725.                 rsuccess = OutMemMountfile ( NULL, &sizememneeded, 0, baseunit );
  726.  
  727.                 if ( rsuccess == 0 )
  728.                 {
  729.                     printf ( "5) Need %ld bytes of buffer for mountfile.\n", sizememneeded );
  730.                     outmembuffer = malloc ( sizememneeded + 256 );
  731.                     if ( outmembuffer )
  732.                     {
  733.                         rsuccess = OutMemMountfile ( outmembuffer, &sizememneeded, sizememneeded + 255, baseunit );
  734.                         if ( rsuccess == 0 )
  735.                         {
  736.                             FILE *foofile = NULL;
  737.  
  738.                             outmembuffer [ sizememneeded + 255 ] = 0;
  739.                             printf ( "Actual use = %d\n", strlen( outmembuffer ));
  740.                             printf ( outmembuffer );
  741.  
  742.                             foofile = fopen ( "foo", "wb" );
  743.                             if ( foofile )
  744.                             {
  745.                                 fwrite ( outmembuffer, sizememneeded, 1, foofile );
  746.                                 fclose ( foofile );
  747.                                 foofile = NULL;
  748.                             }
  749.                         }
  750.                         else
  751.                         {
  752.                             printf ( "Could not write the file: %d\n", rsuccess );
  753.                         }
  754.                     }
  755.                 }
  756.                 else
  757.                     printf ( "Mountfile size write failed: %d\n", rsuccess );
  758.             }
  759.             else
  760.             {
  761.                     printf ( "Mountfile read failed: %d\n", rsuccess );
  762.                     break;
  763.             }
  764.             break;
  765.  
  766.         case 6:
  767. /* HDW_InMemMountfile()
  768.  *    Description:
  769.  *        Parse a block of memory as if it were a disk file feeding through
  770.  *        HDW_ReadMountfile().
  771.  *
  772.  *    Direct Inputs:
  773.  *      unit        unit number of device for which this is intended
  774.  *        mfdata        Pointer to mountfile in memory null terminated
  775.  *        controller  Pointer to "controller ID" information
  776.  *
  777.  *    Indirect Inputs:
  778.  *        BootBlocks    rdb list
  779.  *
  780.  *    Direct Outputs:
  781.  *        ret            error 0 if success else error indication
  782.  *
  783.  *    Indirect Outputs:
  784.  *        RDB structures built in memory
  785.  *
  786.  *    Local Calls:
  787.  *        parse ()
  788.  *
  789.  *    OS Calls:
  790.  *        fclose ()
  791.  *
  792.  *    Algorithm:
  793.  *        If file open close it.
  794.  *        NULL memp.
  795.  *        if data pointer is real use it.
  796.  *        If RDBs not already open
  797.  *            parse data as it comes until null character.
  798.  *
  799.  *    Code:
  800.  *        Joanne Dow, Wizardess Designs, Jan 1999
  801.  */
  802. //ULONG __saveds __asm
  803. //HDW_InMemMountfile ( register __d0 ULONG unit,
  804. //                     register __a0 char *mfdata,
  805. //                     register __a1 char *controller )
  806.             printf ( "6) Read Mountfile from memory and write as Mountfile to memory.\n\n");
  807.             /* More specifically read Mountfile from disk and write as mountfile to
  808.              * printing results to stdout.
  809.              */
  810.             if ( !filename )
  811.             {
  812.                 printf ( "Need a filename\n" );
  813.                 break;
  814.             }
  815.             if ( strlen( filename ) > 248 )
  816.             {
  817.                 printf ( "Filename: %s is too long!\n", filename );
  818.                 break;
  819.             }
  820.             if ( baseunit == (ULONG) -1L )
  821.             {
  822.                 printf ( "Need a base unit for this command.\n" );
  823.                 break;
  824.             }
  825.             sprintf ( realfilename, "%s%s", filename, ".list" );
  826.             workfile = fopen ( realfilename, "rb" );
  827.             if ( !workfile )
  828.             {
  829.                 printf ( "Failed to open %s\n", realfilename );
  830.                 goto cleanup;
  831.             }
  832.             fseek ( workfile, 0, SEEK_END );
  833.             sizeb = ftell ( workfile );
  834.             fseek ( workfile, 0, 0 );
  835.             inmembuffer = malloc ( sizeb + 1 );
  836.             printf ( "Read %d blocks of %d bytes\n", fread ( inmembuffer, sizeb, 1, workfile ), sizeb);
  837.             fclose ( workfile );
  838.             inmembuffer [ sizeb ] = 0;
  839.             printf ( inmembuffer );    // For reference
  840.  
  841.             rsuccess = InMemMountfile ( baseunit, inmembuffer, devicename );
  842.             if ( rsuccess == 0 )
  843.             {
  844.                 rsuccess = OutMemMountfile ( NULL, &sizememneeded, 0, baseunit );
  845.  
  846.                 if ( rsuccess == 0 )
  847.                 {
  848.                     printf ( "6) Need %ld bytes of buffer for mountfile.\n", sizememneeded );
  849.                     outmembuffer = malloc ( sizememneeded + 256 );
  850.                     if ( outmembuffer )
  851.                     {
  852.                         rsuccess = OutMemMountfile ( outmembuffer, &sizememneeded, sizememneeded + 255, baseunit );
  853.                         if ( rsuccess == 0 )
  854.                         {
  855.                             FILE *foofile = NULL;
  856.  
  857.                             outmembuffer [ sizememneeded + 255 ] = 0;
  858.                             printf ( "Actual use = %d\n", strlen( outmembuffer ));
  859.                             printf ( outmembuffer );
  860.  
  861.                             foofile = fopen ( "foo", "wb" );
  862.                             if ( foofile )
  863.                             {
  864.                                 fwrite ( outmembuffer, sizememneeded, 1, foofile );
  865.                                 fclose ( foofile );
  866.                                 foofile = NULL;
  867.                             }
  868.                         }
  869.                         else
  870.                         {
  871.                             printf ( "Could not write the file: %d\n", rsuccess );
  872.                         }
  873.                     }
  874.                 }
  875.                 else
  876.                     printf ( "Mountfile size write failed: %d\n", rsuccess );
  877.             }
  878.             else
  879.                 printf ( "InMemMountfile failed, %ld\n", rsuccess );
  880.  
  881.             break;
  882.  
  883.         case 7:
  884. /* HDW_OutMemRDBStructs()
  885.  *    Description:
  886.  *        (Write RDBs to memory area instead of RDB area of disk.)
  887.  *        Write RDB structs into external memory if large enough as if
  888.  *        writing to disk. If size = 4L return number of bytes required in
  889.  *        *memp.
  890.  *
  891.  *    Direct Inputs:
  892.  *        memp        Pointer to block of memory to be written
  893.  *        sizeb        Size of each block to be written
  894.  *        sizew        pointer to returned number of BLOCKS written
  895.  *
  896.  *    Indirect Inputs:
  897.  *
  898.  *    Direct Outputs:
  899.  *        ret            error 0 if success else error indication
  900.  *        sizew        zeroed then incremented by one for each block written
  901.  *
  902.  *    Indirect Outputs:
  903.  *        RDBs written to memory as if to disk
  904.  *
  905.  *    Local Calls:
  906.  *        none
  907.  *
  908.  *    OS Calls:
  909.  *        fclose ()
  910.  *        memcpy ()
  911.  *
  912.  *    Algorithm:
  913.  *        if file open then close it.
  914.  *        NULL memp.
  915.  *        if RDBs not loaded then fail
  916.  *        Figure out block size from existing RDB structures.
  917.  *        Walk the list to determine total size needed using "sizew" variable.
  918.  *        if rdbp entered is NULL then
  919.  *            do not write anything and return size calculated.
  920.  *        Walk the list again writing RDBs to memory using memcpy.
  921.  *        return 0;
  922.  *
  923.  *    Code:
  924.  *        Joanne Dow, Wizardess Designs, Jan 1999
  925.  */
  926. //ULONG __saveds __asm
  927. //HDW_OutMemRDBStructs ( register __a0 char *rdbp,
  928. //                       register __a1 LONG *sizew,        // Size written
  929. //                       register __d0 LONG sizeb )        // Size of buffer
  930.             printf ( "7) Read Mountfile from memory and write as RDB Structs to memory.\n\n");
  931.             /* More specifically read Mountfile from disk and write from memory
  932.              * to "foo" as one block of RDB Structs.
  933.              */
  934.             if ( !filename )
  935.             {
  936.                 printf ( "Need a filename\n" );
  937.                 break;
  938.             }
  939.             if ( strlen( filename ) > 248 )
  940.             {
  941.                 printf ( "Filename: %s is too long!\n", filename );
  942.                 break;
  943.             }
  944.             if ( baseunit == (ULONG) -1L )
  945.             {
  946.                 printf ( "Need a base unit for this command.\n" );
  947.                 break;
  948.             }
  949.             sprintf ( realfilename, "%s%s", filename, ".list" );
  950.             workfile = fopen ( realfilename, "rb" );
  951.             if ( !workfile )
  952.             {
  953.                 printf ( "Failed to open %s\n", realfilename );
  954.                 goto cleanup;
  955.             }
  956.             fseek ( workfile, 0, SEEK_END );
  957.             sizeb = ftell ( workfile );
  958.             fseek ( workfile, 0, 0 );
  959.             inmembuffer = malloc ( sizeb + 1 );
  960.             printf ( "Read %d blocks of %d bytes\n", fread ( inmembuffer, sizeb, 1, workfile ), sizeb);
  961.             fclose ( workfile );
  962.             inmembuffer [ sizeb ] = 0;
  963.  
  964.             rsuccess = InMemMountfile ( baseunit, inmembuffer, devicename );
  965.             if ( rsuccess == 0 )
  966.             {
  967.                 sizememneeded = 0;
  968.                 rsuccess = OutMemRDBStructs ( NULL, &sizememneeded, 0 );
  969.  
  970.                 if ( rsuccess == 0 )
  971.                 {
  972.                     printf ( "7) Need %ld bytes of buffer for mountfile.\n", sizememneeded );
  973.                     outmembuffer = malloc ( sizememneeded + 256 );
  974.                     if ( outmembuffer )
  975.                     {
  976. //                        int i;
  977. //                        for ( i = sizememneeded; i < sizememneeded + 256; i++)
  978. //                            outmembuffer[i] = 'A';
  979.                         rsuccess = OutMemRDBStructs ( outmembuffer, &sizememneeded, sizememneeded + 255 );
  980.                         if ( rsuccess == 0 )
  981.                         {
  982.                             FILE *foofile = NULL;
  983.  
  984.                             outmembuffer [ sizememneeded + 255 ] = 0;
  985.                             printhex ( &outmembuffer[sizememneeded-16], 256 );
  986.  
  987.                             foofile = fopen ( "foo", "wb" );
  988.                             if ( foofile )
  989.                             {
  990.                                 fwrite ( outmembuffer, sizememneeded, 1, foofile );
  991.                                 fclose ( foofile );
  992.                                 foofile = NULL;
  993.                             }
  994.                         }
  995.                         else
  996.                         {
  997.                             printf ( "Could not write the file: %d\n", rsuccess );
  998.                         }
  999.                     }
  1000.                 }
  1001.                 else
  1002.                     printf ( "Mountfile size write failed: %d\n", rsuccess );
  1003.             }
  1004.             else
  1005.                 printf ( "InMemMountfile failed, %ld\n", rsuccess );
  1006.  
  1007.             break;
  1008.  
  1009.         case 8:
  1010. /* HDW_InMemRDBStructs()
  1011.  *    Description:
  1012.  *        (Read RDBs from memory instead of RDB area of disk.)
  1013.  *        Read the dumped RDB structure format into internal memory as if from
  1014.  *        disk from an external memory block.
  1015.  *
  1016.  *    Direct Inputs:
  1017.  *        rdbp        Pointer to RDBs in memory
  1018.  *        sizeb        Block size
  1019.  *        startb        start block number
  1020.  *        endp        end memory pointer
  1021.  *    Indirect Inputs:
  1022.  *
  1023.  *    Direct Outputs:
  1024.  *        ret            error 0 if success else error indication
  1025.  *
  1026.  *    Indirect Outputs:
  1027.  *        BootBlock list filled
  1028.  *
  1029.  *    Local Calls:
  1030.  *        none
  1031.  *
  1032.  *    OS Calls:
  1033.  *        fclose ()
  1034.  *        memcpy ()
  1035.  *
  1036.  *    Algorithm:
  1037.  *        if RDBs already open then fail
  1038.  *        if file open then close it
  1039.  *        If memory pointer open then close it.
  1040.  *        if pointer not valid then fail
  1041.  *        set memory base to memory pointer
  1042.  *        Set memory end pointer to memory pointer plus input size.
  1043.  *        If fails simple consitency checks then fail
  1044.  *        // Note - RDSK block *MUST* be first
  1045.  *        Determine "blocksize" from first RDB in list as RDSK.
  1046.  *        Set base block number to rdb_RDBBlocksLo
  1047.  *        While ( still in passed memory block )
  1048.  *            if not a legitimate RDB block then fail
  1049.  *            Allocate a block for the list
  1050.  *            Setup overhead data and increment bnum
  1051.  *            Directly copy block data into allocated block
  1052.  *            Increment memory pointer by block size discovered
  1053.  *        return no error
  1054.  *
  1055.  *    Code:
  1056.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1057.  */
  1058. //ULONG  __saveds __asm
  1059. //HDW_InMemRDBStructs ( register __a0 char *rdbp,            // Start of RDB buffer
  1060. //                      register __d0 ULONG sizerdb,        // Size of source buffer
  1061. //                      register __d1 ULONG unit )        // Presumed unit
  1062.             printf ( "8) Read RDBStructs memory and write as RDB Structs to memory.\n\n");
  1063.             /* More specifically read Mountfile from disk and write from memory
  1064.              * to "foo" as one block of RDB Structs.
  1065.              */
  1066.             if ( !filename )
  1067.             {
  1068.                 printf ( "Need a filename\n" );
  1069.                 break;
  1070.             }
  1071.             if ( strlen( filename ) > 248 )
  1072.             {
  1073.                 printf ( "Filename: %s is too long!\n", filename );
  1074.                 break;
  1075.             }
  1076.             if ( baseunit == (ULONG) -1L )
  1077.             {
  1078.                 printf ( "Need a base unit for this command.\n" );
  1079.                 break;
  1080.             }
  1081.             sprintf ( realfilename, "%s%s", filename, "..rdb" );
  1082.             workfile = fopen ( realfilename, "rb" );
  1083.             if ( !workfile )
  1084.             {
  1085.                 printf ( "Failed to open %s\n", realfilename );
  1086.                 goto cleanup;
  1087.             }
  1088.             fseek ( workfile, 0, SEEK_END );
  1089.             sizeb = ftell ( workfile );
  1090.             fseek ( workfile, 0, 0 );
  1091.             inmembuffer = malloc ( sizeb + 1 );
  1092.             printf ( "Read %d blocks of %d bytes\n", fread ( inmembuffer, sizeb, 1, workfile ), sizeb);
  1093.             fclose ( workfile );
  1094.  
  1095.             rsuccess = InMemRDBStructs ( inmembuffer,    // Start of RDB buffer
  1096.                                          sizeb,            // Size of source buffer
  1097.                                          baseunit );    // Presumed unit
  1098.             if ( rsuccess == 0 )
  1099.             {
  1100.                 sizememneeded = 0;
  1101.                 rsuccess = OutMemRDBStructs ( NULL, &sizememneeded, 0 );
  1102.  
  1103.                 if ( rsuccess == 0 )
  1104.                 {
  1105.                     printf ( "8) Need %ld bytes of buffer for mountfile.\n", sizememneeded );
  1106.                     outmembuffer = malloc ( sizememneeded + 256 );
  1107.                     if ( outmembuffer )
  1108.                     {
  1109.                         rsuccess = OutMemRDBStructs ( outmembuffer, &sizememneeded, sizememneeded + 255 );
  1110.                         if ( rsuccess == 0 )
  1111.                         {
  1112.                             FILE *foofile = NULL;
  1113.  
  1114.                             outmembuffer [ sizememneeded + 255 ] = 0;
  1115.  
  1116.                             foofile = fopen ( "bar", "wb" );
  1117.                             if ( foofile )
  1118.                             {
  1119.                                 fwrite ( outmembuffer, sizememneeded, 1, foofile );
  1120.                                 fclose ( foofile );
  1121.                                 foofile = NULL;
  1122.                             }
  1123.                         }
  1124.                         else
  1125.                         {
  1126.                             printf ( "Could not write the file: %d\n", rsuccess );
  1127.                         }
  1128.                     }
  1129.                 }
  1130.                 else
  1131.                     printf ( "Mountfile size write failed: %d\n", rsuccess );
  1132.             }
  1133.             else
  1134.                 printf ( "InMemMountfile failed, %ld\n", rsuccess );
  1135.  
  1136.             break;
  1137.  
  1138.  
  1139.  
  1140. /******************************************
  1141.  *
  1142.  *    9
  1143.  *        BASIC RDB READ TEST
  1144.  *
  1145.  *****************************************/
  1146.         case 9:
  1147. /* HDW_ReadRDBs
  1148.  *    Description:
  1149.  *        Read the entire RDB structure into RAM. Pay NO attention to decodes.
  1150.  *
  1151.  *    Direct Inputs:
  1152.  *        none
  1153.  *
  1154.  *    Indirect Inputs:
  1155.  *        none except in functions called
  1156.  *
  1157.  *    Direct Outputs:
  1158.  *        USHORT with the "worst" success or fail value
  1159.  *
  1160.  *    Indirect Outputs:
  1161.  *        Completely loaded image of the disk's RDBs in a traceable structure
  1162.  *
  1163.  *    Local Calls:
  1164.  *        ClearBlockList ()
  1165.  *        AllocBlock ()
  1166.  *        HDW_RawRead ()
  1167.  *        ScanList ()
  1168.  *
  1169.  *    OS Calls:
  1170.  *        none
  1171.  *
  1172.  *    Algorithm:
  1173.  *        scan blocks 0 through 16 until we have found an RDSK block.
  1174.  *        mark AllocLimitLo = RDSK block number;    ??
  1175.  *        ScanList ( RDSK_block->bb_Longs [ 6 ]);    /* BadBlocks */
  1176.  *        ScanList ( RDSK_block->bb_Longs [ 7 ]);    /* Partitions */
  1177.  *        ScanList ( RDSK_block->bb_Longs [ 8 ]);    /* FileSystems */
  1178.  *        ScanList ( RDSK_block->bb_Longs [ 9 ]);    /* DriveInits */
  1179.  *        Then can scanlist for any others that may appear from 6 reserved.
  1180.  *
  1181.  *    Code:
  1182.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1183.  */
  1184. //USHORT __saveds __asm
  1185. //HDW_ReadRDBs ( void )
  1186.             printf ( "9) Read RDB from disk and write as mountfile to <file>...list.\n\n");
  1187.             if ( !filename )
  1188.             {
  1189.                 printf ( "Need a filename\n" );
  1190.                 break;
  1191.             }
  1192.             if ( strlen( filename ) > 248 )
  1193.             {
  1194.                 printf ( "Filename: %s is too long!\n", filename );
  1195.                 break;
  1196.             }
  1197.             if ( baseunit == (ULONG) -1L )
  1198.             {
  1199.                 printf ( "Need a base unit for this command.\n" );
  1200.                 break;
  1201.             }
  1202.  
  1203.  
  1204.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1205.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1206.             if ( !deviceopen )
  1207.             {
  1208.                 printf ( "No device was opened!\n");
  1209.                 break;
  1210.             }
  1211.  
  1212.             rwsuccess = ReadRDBs ( );
  1213.  
  1214.  
  1215.             if ( rwsuccess == success )
  1216.             {
  1217.                 sprintf ( realfilename, "%s%s", filename, "...list" );
  1218.                 rwsuccess = WriteMountfile ( realfilename, "sys:", baseunit );
  1219.                 if ( rwsuccess == 0 )
  1220.                     printf ( "You should have a new %s waiting.\n", realfilename );
  1221.                 else
  1222.                     printf ( "Mountfile write failed: %d\n", rwsuccess );
  1223.             }
  1224.             else
  1225.             {
  1226.                     printf ( "RDB read failed: %d\n", rwsuccess );
  1227.                     break;
  1228.             }
  1229.  
  1230.             if ( deviceopen )
  1231.             {
  1232.                 printf ( "Closing opened device\n" );
  1233.                 HDWCloseDevice();
  1234.                 deviceopen = FALSE;
  1235.             }
  1236.  
  1237.             break;
  1238.  
  1239.  
  1240.         case 10:
  1241. /* HDW_QueryInquiry
  1242.  *    Description:
  1243.  *        Issue a SCSI "INQUIRY" command and return results
  1244.  *    Direct Inputs:
  1245.  *        errorcode        Pointer to error code storage
  1246.  *    Indirect Inputs:
  1247.  *        none
  1248.  *    Direct Outputs:
  1249.  *        returns result codes lightly massaged
  1250.  *    Indirect Outputs:
  1251.  *        SC data field filled with inquiry data.
  1252.  *    Local Calls:
  1253.  *        none
  1254.  *    OS Calls:
  1255.  *        DoIO ()
  1256.  *    Algorithm:
  1257.  *        Fill out SCMD for an INQUIRY command
  1258.  *        Issue the command
  1259.  *        return lightly massaged results
  1260.  *    Code:
  1261.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1262.  */
  1263. //BOOL __saveds __asm
  1264. //HDW_QueryInquiry ( register __a0 BYTE *inqbuf, register __a1 int *errorcode )
  1265.             printf ( "10) Perform SCSI Inquiry and report results up to 40 bytes.\n\n");
  1266.             if ( baseunit == (ULONG) -1L )
  1267.             {
  1268.                 printf ( "Need a base unit for this command.\n" );
  1269.                 break;
  1270.             }
  1271.  
  1272.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1273.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1274.             if ( !deviceopen )
  1275.             {
  1276.                 printf ( "No device was opened!\n");
  1277.                 break;
  1278.             }
  1279.  
  1280.             {
  1281.                 BYTE inqbuf [ INQBUFSIZE ];
  1282.                 int     errorcode;
  1283.  
  1284.                 memset ( inqbuf, 0xff, INQBUFSIZE );
  1285.                 if ( QueryInquiry ( inqbuf, &errorcode ))
  1286.                 {
  1287.                     printf ( "SCSI inquiry returns:\n" );
  1288.                     printhex ( inqbuf, INQBUFSIZE );
  1289.                 }
  1290.                 else
  1291.                     printf ( "SCSI inquiry failed: %d\n", errorcode );
  1292.             }
  1293.  
  1294.             if ( deviceopen )
  1295.             {
  1296.                 printf ( "Closing opened device\n" );
  1297.                 HDWCloseDevice();
  1298.                 deviceopen = FALSE;
  1299.             }
  1300.             break;
  1301.  
  1302.         case 11:
  1303. /* HDW_QueryModeSense ()
  1304.  *    Description:
  1305.  *
  1306.  *    Direct Inputs:
  1307.  *        page            mode sense page requested
  1308.  *
  1309.  *    Indirect Inputs:
  1310.  *
  1311.  *    Direct Outputs:
  1312.  *
  1313.  *    Indirect Outputs:
  1314.  *
  1315.  *    Local Calls:
  1316.  *
  1317.  *    OS Calls:
  1318.  *        DoIO ()
  1319.  *    Algorithm:
  1320.  *
  1321.  *    Code:
  1322.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1323.  */
  1324. //BOOL __saveds __asm
  1325. //HDW_QueryModeSense ( register __d0 int         page,
  1326. //                     register __d1 int         msbsize,
  1327. //                     register __a0 BYTE        *msbuf,
  1328. //                     register __a1 int        *errorcode )
  1329.             printf ( "11) Perform SCSI ModeSense  and report results up to 256 bytes.\n\n");
  1330.             if ( baseunit == (ULONG) -1L )
  1331.             {
  1332.                 printf ( "Need a base unit for this command.\n" );
  1333.                 break;
  1334.             }
  1335.  
  1336.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1337.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1338.             if ( !deviceopen )
  1339.             {
  1340.                 printf ( "No device was opened!\n");
  1341.                 break;
  1342.             }
  1343.  
  1344.             {
  1345.                 BYTE msbuf [ 256 ];
  1346.                 int     errorcode;
  1347.  
  1348.                 memset ( msbuf, 0xff, 256 );
  1349.                 if ( QueryModeSense ( (BYTE) mspage, 256, msbuf, &errorcode ))    // All sets page 0
  1350.                 {
  1351.                     printf ( "SCSI ModeSense returns:\n" );
  1352.                     printhex ( msbuf, 256 );
  1353.                 }
  1354.                 else
  1355.                     printf ( "SCSI ModeSense failed: %d\n", errorcode );
  1356.             }
  1357.  
  1358.             if ( deviceopen )
  1359.             {
  1360.                 printf ( "Closing opened device\n" );
  1361.                 HDWCloseDevice();
  1362.                 deviceopen = FALSE;
  1363.             }
  1364.             break;
  1365.  
  1366.         case 12:
  1367.  
  1368. /* HDW_QueryCapacity
  1369.  *    Description:
  1370.  *
  1371.  *    Direct Inputs:
  1372.  *        none
  1373.  *    Indirect Inputs:
  1374.  *
  1375.  *    Direct Outputs:
  1376.  *
  1377.  *    Indirect Outputs:
  1378.  *
  1379.  *    Local Calls:
  1380.  *
  1381.  *    OS Calls:
  1382.  *        DoIO ()
  1383.  *    Algorithm:
  1384.  *
  1385.  *    Code:
  1386.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1387.  */
  1388. //BOOL __saveds __asm
  1389. //HDW_QueryCapacity( register __a0 ULONG *capacity )
  1390.             printf ( "12) Perform SCSI Read Capacity and report disk size.\n\n");
  1391.             if ( baseunit == (ULONG) -1L )
  1392.             {
  1393.                 printf ( "Need a base unit for this command.\n" );
  1394.                 break;
  1395.             }
  1396.  
  1397.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1398.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1399.             if ( !deviceopen )
  1400.             {
  1401.                 printf ( "No device was opened!\n");
  1402.                 break;
  1403.             }
  1404.  
  1405.             {
  1406.                 ULONG capacity;
  1407.                 ULONG blocksize;
  1408.  
  1409.                 if ( QueryCapacity ( &capacity, &blocksize ))    // All sets page 0
  1410.                     printf ( "SCSI Read Capacity returns: %ld blocks of %ld bytes.\n",
  1411.                              capacity,
  1412.                              blocksize );
  1413.                 else
  1414.                     printf ( "SCSI Read Capacity failed\n" );
  1415.             }
  1416.  
  1417.             if ( deviceopen )
  1418.             {
  1419.                 printf ( "Closing opened device\n" );
  1420.                 HDWCloseDevice();
  1421.                 deviceopen = FALSE;
  1422.             }
  1423.         break;
  1424.  
  1425.         case 13:
  1426. /* HDW_QueryReady
  1427.  *    Description:
  1428.  *        Issue a SCSI "TEST UNIT READY" command and return results
  1429.  *    Direct Inputs:
  1430.  *        errorcode        pointer to an error code return
  1431.  *
  1432.  *    Indirect Inputs:
  1433.  *
  1434.  *    Direct Outputs:
  1435.  *        returns TRUE for ready and FALSE for not ready
  1436.  *    Indirect Outputs:
  1437.  *        errorcode        contains the (massaged) IO error codes on return
  1438.  *    Local Calls:
  1439.  *        none
  1440.  *    OS Calls:
  1441.  *        DoIO ()
  1442.  *    Algorithm:
  1443.  *        Fill out SCMD for a TEST UNIT READY command
  1444.  *        Issue the command
  1445.  *        fill out errorcode
  1446.  *        return Ready or not ready
  1447.  *    Code:
  1448.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1449.  */
  1450. //BOOL __saveds __asm
  1451. //HDW_QueryReady ( register __a0 int * errorcode )
  1452.             printf ( "13) Perform SCSI Test Unit Ready and report device readiness.\n\n");
  1453.             if ( baseunit == (ULONG) -1L )
  1454.             {
  1455.                 printf ( "Need a base unit for this command.\n" );
  1456.                 break;
  1457.             }
  1458.  
  1459.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1460.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1461.             if ( !deviceopen )
  1462.             {
  1463.                 printf ( "No device was opened!\n");
  1464.                 break;
  1465.             }
  1466.  
  1467.             {
  1468.                 int errorcode;
  1469.  
  1470.                 if ( QueryReady ( &errorcode ))    // All sets page 0
  1471.                     printf ( "SCSI Test Unit Ready indicates ready.\n" );
  1472.                 else
  1473.                     printf ( "SCSI Test Unit Ready indicates not ready: %ld\n", errorcode );
  1474.             }
  1475.  
  1476.             if ( deviceopen )
  1477.             {
  1478.                 printf ( "Closing opened device\n" );
  1479.                 HDWCloseDevice();
  1480.                 deviceopen = FALSE;
  1481.             }
  1482.         break;
  1483.  
  1484.         case 14:
  1485. /* HDW_FindDiskName ()
  1486.  *    Description:
  1487.  *        Reads manufacturer data from Inquiry command and installs in supplied
  1488.  *        string space. Should be a valid device.
  1489.  *
  1490.  *    Direct Inputs:
  1491.  *        diskname        A pointer to a disk name storage array
  1492.  *
  1493.  *    Indirect Inputs:
  1494.  *        Already opened device
  1495.  *
  1496.  *    Direct Outputs:
  1497.  *
  1498.  *    Indirect Outputs:
  1499.  *
  1500.  *    Local Calls:
  1501.  *        Calls global QueryInquiry function
  1502.  *
  1503.  *    OS Calls:
  1504.  *
  1505.  *    Algorithm:
  1506.  *        if device not open or diskname is null return failure
  1507.  *        call HDW_QueryInquiry
  1508.  *        Copy disk name into provided storage for exactly 28 bytes using memcpy.
  1509.  *    Code:
  1510.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1511.  */
  1512. //BOOL __saveds __asm /* error */
  1513. //HDW_FindDiskName ( register __a0 *diskname )
  1514.             printf ( "14) Find Disk Name returning in string variable.\n\n" );
  1515.             if ( baseunit == (ULONG) -1L )
  1516.             {
  1517.                 printf ( "Need a base unit for this command.\n" );
  1518.                 break;
  1519.             }
  1520.  
  1521.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1522.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1523.             if ( !deviceopen )
  1524.             {
  1525.                 printf ( "No device was opened!\n");
  1526.                 break;
  1527.             }
  1528.  
  1529.             {
  1530.                 char diskname[32];
  1531.  
  1532.                 memset ( diskname, 0xff, 32 );
  1533.                 if ( FindDiskName ( diskname ))
  1534.                     printhex ( diskname, 32 );
  1535.                 else
  1536.                     printf ( "FindDiskName failed!\n" );
  1537.             }
  1538.  
  1539.             if ( deviceopen )
  1540.             {
  1541.                 printf ( "Closing opened device\n" );
  1542.                 HDWCloseDevice();
  1543.                 deviceopen = FALSE;
  1544.             }
  1545.         break;
  1546.  
  1547.         case 15:
  1548. /* HDW_FindControllerID()
  1549.  *    Description:
  1550.  *        Test open devices until find SelfID error
  1551.  *        ( Of course, this does not work on Commododo "scsi.device". <bleah!> )
  1552.  *
  1553.  *    Direct Inputs:
  1554.  *        ULONG    *selfid    pointer to selfid result field. Contains a Unit number
  1555.  *                        with a valid board number field.
  1556.  *
  1557.  *    Indirect Inputs:
  1558.  *
  1559.  *    Direct Outputs:
  1560.  *        Unit number for controller's SCSI ID.
  1561.  *
  1562.  *    Indirect Outputs:
  1563.  *
  1564.  *    Local Calls:
  1565.  *
  1566.  *    OS Calls:
  1567.  *
  1568.  *    Algorithm:
  1569.  *
  1570.  *    Code:
  1571.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1572.  */
  1573. //BOOL16 Apr 1999 __saveds __asm /* error */
  1574. //HDW_FindControllerID ( register __a0 char *devname, register __a1 ULONG *selfid )
  1575.             printf ( "15) Find Controller self-ID returning in ULONG.\n\n" );
  1576.             if ( baseunit == (ULONG) -1L )
  1577.             {
  1578.                 printf ( "Need a base unit for this command.\n" );
  1579.                 break;
  1580.             }
  1581.  
  1582.             {
  1583.                 ULONG selfid = baseunit;
  1584.  
  1585.                 if ( FindControllerID ( devicename, &selfid ))
  1586.                     printf ( "Controller ID is %ld.\n", selfid );
  1587.                 else
  1588.                     printf ( "FindControllerID failed!\n" );
  1589.             }
  1590.             break;
  1591.  
  1592.         case 16:
  1593. /* HDW_FindLastSector()    ( Made available chiefly for diagnostic purposes.)
  1594.  *    Description:
  1595.  *        Determine last available sector on disk WITH tests.
  1596.  *
  1597.  *    Direct Inputs:
  1598.  *
  1599.  *    Indirect Inputs:
  1600.  *
  1601.  *    Direct Outputs:
  1602.  *        Last block on the disk numbered 1 through n. (This was done so that
  1603.  *        the TotalBlocks report and the FindLastSector report are congruent.)
  1604.  *
  1605.  *    Indirect Outputs:
  1606.  *
  1607.  *    Local Calls:
  1608.  *
  1609.  *    OS Calls:
  1610.  *
  1611.  *    Algorithm:
  1612.  *        HDW_QueryCapacity
  1613.  *        Test what should be last block.
  1614.  *        If ( Read the rated last block is OK )
  1615.  *            if ( Read the block past rated last block is bad )
  1616.  *                return no error and last sector number confirmed.
  1617.  *            else
  1618.  *                Search upwards binary search until find real last bad
  1619.  *                sector. Return error "Last Sector to low" and found top block.
  1620.  *        else
  1621.  *            Step downwards one block then two then four until read one OK.
  1622.  *            Then step upwards binary search for actual top block.
  1623.  *            Return error "Last sector too high" and found top block.
  1624.  *        endif
  1625.  *        exit
  1626.  *
  1627.  *    Code:
  1628.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1629.  */
  1630. //ULONG __saveds __asm /* error */
  1631. //HDW_FindLastSector ( void )
  1632.             printf ( "16) Report last available block on the drive.\n\n");
  1633.             if ( baseunit == (ULONG) -1L )
  1634.             {
  1635.                 printf ( "Need a base unit for this command.\n" );
  1636.                 break;
  1637.             }
  1638.  
  1639.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1640.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1641.             if ( !deviceopen )
  1642.             {
  1643.                 printf ( "No device was opened!\n");
  1644.                 break;
  1645.             }
  1646.  
  1647.             printf ( "Find Last Sector returns: %ld\n", FindLastSector());
  1648.  
  1649.             if ( deviceopen )
  1650.             {
  1651.                 printf ( "Closing opened device\n" );
  1652.                 HDWCloseDevice();
  1653.                 deviceopen = FALSE;
  1654.             }
  1655.         break;
  1656.  
  1657.         case 17:
  1658. /* HDW_FindDefaults ()
  1659.  *    Description:
  1660.  *        Determine default blocking for device.
  1661.  *
  1662.  *    Direct Inputs:
  1663.  *        Optimize        A flag array for optimization values
  1664.  *        Return            Pointer to a DefaultsArray structure for return values
  1665.  *
  1666.  *    Indirect Inputs:
  1667.  *        Opened IO device
  1668.  *
  1669.  *    Direct Outputs:
  1670.  *        Error return value passing back informational and fatal errors.
  1671.  *        The DefaultsArray passed in is filled in
  1672.  *
  1673.  *    Indirect Outputs:
  1674.  *        Many internal values are filled in which will be overridden when
  1675.  *        reading RDBs or Mountfiles.
  1676.  *
  1677.  *    Local Calls:
  1678.  *        HDW_FindLastSector ()
  1679.  *        HDW_QueryInquiry ()
  1680.  *        HDW_QueryModeSense ()
  1681.  *
  1682.  *    OS Calls:
  1683.  *
  1684.  *    Algorithm:
  1685.  *        HDW_QueryCapacity
  1686.  *        HDW_FindLastBlock () // Test what should be last block.
  1687.  *        Division routines....
  1688.  *        exit
  1689.  *
  1690.  *    Code:
  1691.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1692.  */
  1693. //ULONG __saveds __asm
  1694. //HDW_FindDefaults ( register __d0 BOOL Optimize,
  1695. //                   register __a0 struct DefaultsArray Return )
  1696. /*struct DefaultsArray
  1697.  *{
  1698.  *    UWORD    BytesPerBlock;
  1699.  *    UWORD    BlocksPerSurface;
  1700.  *    UWORD    Surfaces;
  1701.  *    UWORD    Cylinders;                // note: MaxCyl = Cylinders - 1;
  1702.  *};
  1703.  */
  1704.             printf ( "17) Generate default drive parameters.\n\n" );
  1705.             if ( baseunit == (ULONG) -1L )
  1706.             {
  1707.                 printf ( "Need a base unit for this command.\n" );
  1708.                 break;
  1709.             }
  1710.  
  1711.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1712.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1713.             if ( !deviceopen )
  1714.             {
  1715.                 printf ( "No device was opened!\n");
  1716.                 break;
  1717.             }
  1718.  
  1719.             {
  1720.                 struct    DefaultsArray defaults;
  1721.                 ULONG    errorcode;
  1722.  
  1723.                 memset ( &defaults, 0, sizeof ( struct DefaultsArray) );
  1724.                 errorcode = FindDefaults ( 0, &defaults );    // No optimize
  1725.                 if ( errorcode == 0 )
  1726.                 {
  1727.                     printf ( "TotalBlocks:         %d\n", defaults.TotalBlocks );
  1728.                     printf ( "BytesPerBlock:       %d\n", defaults.BytesPerBlock );
  1729.                     printf ( "BlocksPerSurface:    %d\n", defaults.BlocksPerSurface );
  1730.                     printf ( "Surfaces:            %d\n", defaults.Surfaces );
  1731.                     printf ( "Cylinders:           %d\n", defaults.Cylinders );
  1732.                     printf ( "Unused Blocks:       %d\n", defaults.UnusedBlocks );
  1733.                 }
  1734.                 else
  1735.                     printf ( "FindDefaults failed!\n" );
  1736.  
  1737.                 printf ( "\nAttempting Optimized Defaults.\n" );
  1738.                 memset ( &defaults, 0, sizeof ( struct DefaultsArray) );
  1739.                 errorcode = FindDefaults ( DA_OPTIMIZE, &defaults );
  1740.                 if ( errorcode == 0 )
  1741.                 {
  1742.                     printf ( "TotalBlocks:         %d\n", defaults.TotalBlocks );
  1743.                     printf ( "BytesPerBlock:       %d\n", defaults.BytesPerBlock );
  1744.                     printf ( "BlocksPerSurface:    %d\n", defaults.BlocksPerSurface );
  1745.                     printf ( "Surfaces:            %d\n", defaults.Surfaces );
  1746.                     printf ( "Cylinders:           %d\n", defaults.Cylinders );
  1747.                     printf ( "Unused Blocks:       %d\n", defaults.UnusedBlocks );
  1748.                 }
  1749.                 else
  1750.                     printf ( "FindDefaults failed!\n" );
  1751.  
  1752.                 printf ( "\nAttempting HardFrame Defaults.\n" );
  1753.                 memset ( &defaults, 0, sizeof ( struct DefaultsArray) );
  1754.                 errorcode = FindDefaults ( DA_HF_WAY, &defaults );
  1755.                 if ( errorcode == 0 )
  1756.                 {
  1757.                     printf ( "TotalBlocks:         %d\n", defaults.TotalBlocks );
  1758.                     printf ( "BytesPerBlock:       %d\n", defaults.BytesPerBlock );
  1759.                     printf ( "BlocksPerSurface:    %d\n", defaults.BlocksPerSurface );
  1760.                     printf ( "Surfaces:            %d\n", defaults.Surfaces );
  1761.                     printf ( "Cylinders:           %d\n", defaults.Cylinders );
  1762.                     printf ( "Unused Blocks:       %d\n", defaults.UnusedBlocks );
  1763.                 }
  1764.                 else
  1765.                     printf ( "FindDefaults failed!\n" );
  1766.  
  1767.                 // Note this is a "hidden flag" used for debugging.
  1768.                 // It is otherwise pointless to use.
  1769.                 printf ( "\nAttempting 1Meg Cylinder size Defaults.\n" );
  1770.                 memset ( &defaults, 0, sizeof ( struct DefaultsArray) );
  1771.                 errorcode = FindDefaults ( 8, &defaults );
  1772.                 if ( errorcode == 0 )
  1773.                 {
  1774.                     printf ( "TotalBlocks:         %d\n", defaults.TotalBlocks );
  1775.                     printf ( "BytesPerBlock:       %d\n", defaults.BytesPerBlock );
  1776.                     printf ( "BlocksPerSurface:    %d\n", defaults.BlocksPerSurface );
  1777.                     printf ( "Surfaces:            %d\n", defaults.Surfaces );
  1778.                     printf ( "Cylinders:           %d\n", defaults.Cylinders );
  1779.                     printf ( "Unused Blocks:       %d\n", defaults.UnusedBlocks );
  1780.                 }
  1781.                 else
  1782.                     printf ( "FindDefaults failed!\n" );
  1783.  
  1784.                 printf ( "\nAttempting Optimized Defaults with a huge disk.\n" );
  1785.                 memset ( &defaults, 0, sizeof ( struct DefaultsArray) );
  1786.                 errorcode = FindDefaults ( DA_OPTIMIZE | DA_HUGE, &defaults );
  1787.                 if ( errorcode == 0 )
  1788.                 {
  1789.                     printf ( "TotalBlocks:         %d\n", defaults.TotalBlocks );
  1790.                     printf ( "BytesPerBlock:       %d\n", defaults.BytesPerBlock );
  1791.                     printf ( "BlocksPerSurface:    %d\n", defaults.BlocksPerSurface );
  1792.                     printf ( "Surfaces:            %d\n", defaults.Surfaces );
  1793.                     printf ( "Cylinders:           %d\n", defaults.Cylinders );
  1794.                     printf ( "Unused Blocks:       %d\n", defaults.UnusedBlocks );
  1795.                 }
  1796.                 else
  1797.                     printf ( "FindDefaults failed!\n" );
  1798.             }
  1799.  
  1800.             if ( deviceopen )
  1801.             {
  1802.                 printf ( "Closing opened device\n" );
  1803.                 HDWCloseDevice();
  1804.                 deviceopen = FALSE;
  1805.             }
  1806.         break;
  1807.  
  1808.         case 18:
  1809. /* HDW_RawRead
  1810.  *    Description:
  1811.  *        Read a block from the disk into the provided BootBlock structure at
  1812.  *        the block number stored in the BootBlock structure.
  1813.  *
  1814.  *    Direct Inputs:
  1815.  *        bb                pointer to an array of ULONG of indefinate size.
  1816.  *        blocknum        The number of the block to read.
  1817.  *
  1818.  *    Indirect Inputs:
  1819.  *        SC            Global utility SCSI direct command field
  1820.  *        SCCmd        Global utility SCSI command field
  1821.  *        IOR            IO Request block for a presumed opened device
  1822.  *        ddBlockBytes    Block size as determined from the first (good) disk read
  1823.  *                        On first read use 16384. On success this is updated from
  1824.  *                        SCSI.actual.
  1825.  *    Direct Output:
  1826.  *        USHORT Success or failure per enum...
  1827.  *
  1828.  *    Indirect Output:
  1829.  *        bb                 filled with data and errorcode from the read.
  1830.  *        ddBlockBytes    updated as appropriate for size of actual read.
  1831.  *
  1832.  *    Local Calls:
  1833.  *        None
  1834.  *
  1835.  *    OS Calls:
  1836.  *        DoIO ()
  1837.  *
  1838.  *    Algorithm:
  1839.  *        If block less than 2097152, 2^21, use the 6 byte command sequence,
  1840.  *        else use the 10 byte read command sequence. (This is an arbitrary choice.)
  1841.  *
  1842.  *        Ascertain device is open
  1843.  *        allocate temporary read block per size of ddBlockBytes
  1844.  *        Build the command
  1845.  *        issue the command
  1846.  *        If command good
  1847.  *            if ddBlockBytes == 16384 set ddBlockBytes to actual xfersize
  1848.  *            copy actual transfer size bytes into bb
  1849.  *        if blocksize not power of two >= 512L <= 16384L
  1850.  *            errorcode = invalid_block_size
  1851.  *        return error codes as appropriate.
  1852.  *
  1853.  *    Code:
  1854.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1855.  */
  1856. //USHORT __saveds __asm
  1857. //HDW_RawRead ( register __a0 BootBlock *bbk, register __d0 USHORT size )
  1858.             printf ( "18) Read and report raw sector 'MS'.\n\n");
  1859.             if ( baseunit == (ULONG) -1L )
  1860.             {
  1861.                 printf ( "Need a base unit for this command.\n" );
  1862.                 break;
  1863.             }
  1864.  
  1865.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  1866.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  1867.             if ( !deviceopen )
  1868.             {
  1869.                 printf ( "No device was opened!\n");
  1870.                 break;
  1871.             }
  1872.  
  1873.  
  1874.             {
  1875.                 BootBlock    *bb;
  1876.                 ULONG         capacity;
  1877.                 ULONG         blocksize;
  1878.                 USHORT         ecode;
  1879.  
  1880.                 if ( QueryCapacity ( &capacity, &blocksize ))    // All sets page 0
  1881.                     printf ( "SCSI Read Capacity returns: %ld blocks of %ld bytes.\n",
  1882.                              capacity,
  1883.                              blocksize );
  1884.                 else
  1885.                 {
  1886.                     printf ( "SCSI Read Capacity failed\n" );
  1887.                     blocksize = 16384L;            // Better use a safe blocksize!
  1888.                 }
  1889.  
  1890.                 bb = malloc ( sizeof ( BootBlock ) - 512 + blocksize );
  1891.                 if ( bb == NULL )
  1892.                 {
  1893.                     printf ( "BootBlock allocation failed!\n" );
  1894.                     break;
  1895.                 }
  1896.  
  1897.                 bb->bb_BlockNum = mspage;    // Only value really needed
  1898.                 ecode = RawRead ( bb, blocksize );
  1899.                 if ( ecode == success )
  1900.                     printhex ( bb->bb_Data.bd_Bytes, blocksize );
  1901.                 else
  1902.                     printf ( "RawRead failed %d!", ecode );
  1903.  
  1904.             }
  1905.  
  1906.  
  1907.             if ( deviceopen )
  1908.             {
  1909.                 printf ( "Closing opened device\n" );
  1910.                 HDWCloseDevice();
  1911.                 deviceopen = FALSE;
  1912.             }
  1913.         break;
  1914.  
  1915.         case 19:
  1916. /* HDW_QueryFindValid
  1917.  *    Description:
  1918.  *        Attempt to determine all valid configureable units on devicename
  1919.  *        according to an acceptable types bitmap supplied on entry. Data is
  1920.  *        filled into a 16 word of 16 bits each bitmap with pointer supplied
  1921.  *        on entry. "BoardNumber" to be tested is supplied by the calling
  1922.  *        routine.
  1923.  *    Direct Inputs:
  1924.  *        ValidIDs            Pointer ValidIDstruct
  1925.  *        devicename            device name for testing
  1926.  *        board                Board ID to test
  1927.  *        types                ULONG bitmap of valid device typese
  1928.  *        widescsi            BOOLEAN set TRUE if wide scsi used.
  1929.  *        CallBack            Pointer to callback handler
  1930.  *
  1931.  *    Indirect Inputs:
  1932.  *
  1933.  *    Direct Outputs:
  1934.  *
  1935.  *    Indirect Outputs:
  1936.  *
  1937.  *    Local Calls:
  1938.  *
  1939.  *    OS Calls:
  1940.  *
  1941.  *    Algorithm:
  1942.  *        Clear the supplied bitmap array
  1943.  *        For all IDs on the SCSI bus
  1944.  *            For all LUNs on each ID
  1945.  *                HW_OpenDevice ( Board, ID, LUN, devicename )
  1946.  *                TestUnitReady()
  1947.  *                Inquiry()
  1948.  *                if in valid types
  1949.  *                    Mark as valid
  1950.  *                if LUN 0 fails to open
  1951.  *                    break - skipping remaining LUNs
  1952.  *                if self-id for controller
  1953.  *                    break - skipping controller
  1954.  *        return completion status
  1955.  *    Code:
  1956.  *        Joanne Dow, Wizardess Designs, Jan 1999
  1957.  */
  1958. //void __saveds __asm
  1959. //HDW_QueryFindValid ( register __a0 ValidIDstruct *ValidIDs,
  1960. //                       register __a1 char * devicename,
  1961. //                       register __d0 int board,
  1962. //                       register __d1 ULONG types,
  1963. //                       register __d2 BOOL wide_scsi,
  1964. //                       register __a2 long ( *__asm CallBack)
  1965. //                                           ( register __a0 HDWCallbackMsg msg ));
  1966.             printf ( "19) Find all valid disks on a given controller.\n\n");
  1967.             if ( baseunit == (ULONG) -1L )
  1968.             {
  1969.                 printf ( "Need a base unit for this command.\n" );
  1970.                 break;
  1971.             }
  1972.  
  1973.             {
  1974.                 ULONG             types;
  1975.                 int                 board = baseunit;
  1976.                 ValidIDstruct     ValidIDs;
  1977.  
  1978.                 printf ( "Trying for hard disks only.\n" );
  1979.                 types = 1;    // Only disk drives!
  1980.                 QueryFindValid ( &ValidIDs, devicename, board, types, FALSE, NULL );
  1981.                 printhex ( (BYTE *) ValidIDs.there, 16 * sizeof (USHORT ));
  1982.                 printhex ( (BYTE *) ValidIDs.ready, 16 * sizeof (USHORT ));
  1983.  
  1984.                 printf ( "\nTrying for ALL drive types.\n" );
  1985.                 types = (ULONG) -1L;    // All devices!
  1986.                 QueryFindValid ( &ValidIDs, devicename, board, types, FALSE, CallBack );
  1987.                 printf ("\n\n");
  1988.                 printhex ( (BYTE *) ValidIDs.there, 16 * sizeof (USHORT ));
  1989.                 printhex ( (BYTE *) ValidIDs.ready, 16 * sizeof (USHORT ));
  1990.             }
  1991.         break;
  1992.  
  1993.         case 20:
  1994. /* HDW_RawWrite
  1995.  *    Description:
  1996.  *        Write the data section of a BootBlock to the disk at the block number
  1997.  *        stored within the BootBlock structure.
  1998.  *
  1999.  *    Direct Inputs:
  2000.  *        bb                pointer to a BootBlock structure of indefinate size.
  2001.  *                        Note that bb includes the block ID
  2002.  *
  2003.  *    Indirect Inputs:
  2004.  *        SC            Global utility SCSI direct command field
  2005.  *        SCCmd        Global utility SCSI command field
  2006.  *        IOR            IO Request block for a presumed opened device
  2007.  *        ddBlockBytes    Block size as determined from the first (good) disk read
  2008.  *                        On first read use 16384. On success this is updated from
  2009.  *                        SCSI.actual.
  2010.  *
  2011.  *    Direct Output:
  2012.  *        UHSORT Success or failure per enum...
  2013.  *
  2014.  *    Indirect Output:
  2015.  *        bb                 data field written to disk.
  2016.  *
  2017.  *    Local Calls:
  2018.  *        None
  2019.  *
  2020.  *    OS Calls:
  2021.  *        DoIO ()
  2022.  *
  2023.  *    Algorithm:
  2024.  *        Make sure IOR is legitimately opened
  2025.  *        blocknum = bb->bb_BlockNum
  2026.  *        if blocknum = -1
  2027.  *            find in bitmap first unassigned block and assign it
  2028.  *            repair bb->BlockNum and blocknum to reflect this
  2029.  *        Build the SCSI command
  2030.  *        Issue IO command
  2031.  *        return massaged error code.
  2032.  *    Code:
  2033.  *        Joanne Dow, Wizardess Designs, Jan 1999
  2034.  */
  2035. //USHORT __saveds __asm
  2036. //HDW_RawWrite ( register __a0 BootBlock *bb )
  2037.             printf ( "20) Raw write to a block of low disk. (Safe write - I hope!)\n\n");
  2038.             if ( baseunit == (ULONG) -1L )
  2039.             {
  2040.                 printf ( "Need a base unit for this command.\n" );
  2041.                 break;
  2042.             }
  2043.  
  2044.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  2045.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  2046.             if ( !deviceopen )
  2047.             {
  2048.                 printf ( "No device was opened!\n");
  2049.                 break;
  2050.             }
  2051.  
  2052.  
  2053.             {
  2054.                 BootBlock    *bb;
  2055.                 BootBlock    *bbt;
  2056.                 BootBlock    *bbtr;
  2057.                 ULONG         capacity;
  2058.                 ULONG         blocksize;
  2059.                 USHORT         ecode;
  2060.  
  2061.                 if ( QueryCapacity ( &capacity, &blocksize ))    // All sets page 0
  2062.                     printf ( "SCSI Read Capacity returns: %ld blocks of %ld bytes.\n",
  2063.                              capacity,
  2064.                              blocksize );
  2065.                 else
  2066.                 {
  2067.                     printf ( "SCSI Read Capacity failed\n" );
  2068.                     blocksize = 16384L;            // Better use a safe blocksize!
  2069.                 }
  2070.  
  2071.                 bb   = malloc ( sizeof ( BootBlock ) - 512 + blocksize );
  2072.                 bbt  = malloc ( sizeof ( BootBlock ) - 512 + blocksize );
  2073.                 bbtr = malloc ( sizeof ( BootBlock ) - 512 + blocksize );
  2074.                 if (( bb == NULL ) || ( bbt == NULL ) || ( bbtr == NULL ))
  2075.                 {
  2076.                     printf ( "BootBlock allocation failed!\n" );
  2077.                     if ( bb )
  2078.                         free ( bb );
  2079.                     if ( bbt )
  2080.                         free ( bbt );
  2081.                     if ( bbtr )
  2082.                         free ( bbtr );
  2083.                     break;
  2084.                 }
  2085.  
  2086.                 bb->bb_BlockNum   = mspage;    // Only value really needed
  2087.                 bbt->bb_BlockNum  = mspage;    // Only value really needed
  2088.                 bbtr->bb_BlockNum = mspage;    // Only value really needed
  2089.  
  2090.                 ecode = RawRead ( bb, blocksize );
  2091.                 if ( ecode == success )
  2092.                     printhex ( bb->bb_Data.bd_Bytes, 32 );
  2093.                 else
  2094.                 {
  2095.                     printf ( "RawRead failed %d!", ecode );
  2096.                     if ( bb )
  2097.                         free ( bb );
  2098.                     if ( bbt )
  2099.                         free ( bbt );
  2100.                     if ( bbtr )
  2101.                         free ( bbtr );
  2102.                     break;
  2103.                 }
  2104.                 printf ( "This IS dangerous. Continue? ");
  2105.                 gets ( bbt->bb_Data.bd_Bytes );
  2106.                 if ( bbt->bb_Data.bd_Bytes [ 0 ] != 'Y' )
  2107.                 {
  2108.                     printf ( "OK, I'm GONE Kemosabe!\n" );
  2109.                     if ( bb )
  2110.                         free ( bb );
  2111.                     if ( bbt )
  2112.                         free ( bbt );
  2113.                     if ( bbtr )
  2114.                         free ( bbtr );
  2115.                     break;
  2116.                 }
  2117.  
  2118.                 // OK guys - this is the BIG doodoo if we get it wrong!
  2119.                 // Write exactly the same data back....
  2120.                 ecode = RawWrite ( bb );
  2121.                 if ( ecode != success )
  2122.                 {
  2123.                     printf ( "RawWrite failed, %d\n", ecode );
  2124.                     if ( bb )
  2125.                         free ( bb );
  2126.                     if ( bbt )
  2127.                         free ( bbt );
  2128.                     if ( bbtr )
  2129.                         free ( bbtr );
  2130.                     break;
  2131.                 }
  2132.                 else
  2133.                     printf ( "Block written = %d\n", bb->bb_RWErrors.block_written );
  2134.  
  2135.                 // Now fill the data block with OTHER data!
  2136.                 //
  2137.                 for ( ecode = 0; ecode < blocksize; ecode++ )
  2138.                     bbt->bb_Data.bd_Bytes [ ecode ] = (UBYTE) (ecode & 0xff);
  2139.  
  2140.                 // OK guys - this is the REAL BIG doodoo if we get it wrong!
  2141.                 // Write exactly the same data back....
  2142.                 ecode = RawWrite ( bbt );
  2143.                 if ( ecode != success )
  2144.                 {
  2145.                     printf ( "RawWrite failed, %d\n", ecode );
  2146.                     if ( bb )
  2147.                         free ( bb );
  2148.                     if ( bbt )
  2149.                         free ( bbt );
  2150.                     if ( bbtr )
  2151.                         free ( bbtr );
  2152.                     break;
  2153.                 }
  2154.                 else
  2155.                     printf ( "Block written = %d\n", bbt->bb_RWErrors.block_written );
  2156.  
  2157.                 // Reread it for confirmation it was written
  2158.                 ecode = RawRead ( bbtr, blocksize );
  2159.                 if ( ecode == success )
  2160.                     printhex ( bbtr->bb_Data.bd_Bytes, 32 );
  2161.                 else
  2162.                 {
  2163.                     printf ( "RawRead failed %d!", ecode );
  2164.                     if ( bb )
  2165.                         free ( bb );
  2166.                     if ( bbt )
  2167.                         free ( bbt );
  2168.                     if ( bbtr )
  2169.                         free ( bbtr );
  2170.                     break;
  2171.                 }
  2172.  
  2173.                 // IMMEDIATELY restore the original block!
  2174.                 ecode = RawWrite ( bb );
  2175.                 if ( ecode != success )
  2176.                 {
  2177.                     printf ( "RawWrite failed, %d\n", ecode );
  2178.                     if ( bb )
  2179.                         free ( bb );
  2180.                     if ( bbt )
  2181.                         free ( bbt );
  2182.                     if ( bbtr )
  2183.                         free ( bbtr );
  2184.                     break;
  2185.                 }
  2186.                 else
  2187.                     printf ( "Block written = %d\n", bb->bb_RWErrors.block_written );
  2188.  
  2189.                 for ( ecode = 0; ecode < blocksize; ecode++ )
  2190.                 {
  2191.                     if ( bbt->bb_Data.bd_Bytes [ ecode ] != bbtr->bb_Data.bd_Bytes [ ecode ] )
  2192.                     {
  2193.                         printf ( "Compare error at %d: %x vs %x\n",
  2194.                                  ecode,
  2195.                                  bbt->bb_Data.bd_Bytes [ ecode ],
  2196.                                  bbtr->bb_Data.bd_Bytes [ ecode ] );
  2197.                         break;
  2198.                     }
  2199.                 }
  2200.                 if ( ecode == blocksize )
  2201.                     printf ( "Completely successful compare here, too.\n" );
  2202.  
  2203.                 if ( bb )
  2204.                     free ( bb );
  2205.                 if ( bbt )
  2206.                     free ( bbt );
  2207.                 if ( bbtr )
  2208.                     free ( bbtr );
  2209.             }
  2210.  
  2211.  
  2212.             if ( deviceopen )
  2213.             {
  2214.                 printf ( "Closing opened device\n" );
  2215.                 HDWCloseDevice();
  2216.                 deviceopen = FALSE;
  2217.             }
  2218.         break;
  2219.  
  2220.         case 21:
  2221. /* HDW_WriteBlock
  2222.  *    Description:
  2223.  *        Write a BootBlock's data to the disk at the block number stored in the
  2224.  *        structure. Readback to verify the written data. Repeat a few times on
  2225.  *        initial failure.
  2226.  *
  2227.  *    Direct Inputs:
  2228.  *        bb                pointer to a BootBlock structure of indefinate size.
  2229.  *                        Note that bb includes the block ID
  2230.  *    Indirect Inputs:
  2231.  *        SC            Global utility SCSI direct command field
  2232.  *        SCCmd        Global utility SCSI command field
  2233.  *        IOR            IO Request block for a presumed opened device
  2234.  *        ddBlockBytes    Block size as determined from the first (good) disk read
  2235.  *                        On first read use 16384. On success this is updated from
  2236.  *                        SCSI.actual.
  2237.  *
  2238.  *    Direct Output:
  2239.  *        USHORT Success or failure per enum...
  2240.  *
  2241.  *    Indirect Output:
  2242.  *        bb                 data field written to disk.
  2243.  *
  2244.  *    Local Calls:
  2245.  *        HDW_RawWrite ()
  2246.  *        HDW_RawRead ()
  2247.  *
  2248.  *    OS Calls:
  2249.  *        none
  2250.  *
  2251.  *    Algorithm:
  2252.  *        Allocate temporary BootBlock structure
  2253.  *        repeat several tries:
  2254.  *            Write block
  2255.  *            Read block 1000 to try to flush disk caches slightly
  2256.  *            Read back written block to a scratchpad
  2257.  *            Compare block to scratchpad
  2258.  *            if error repeat
  2259.  *        Free temporary bootblock structure
  2260.  *        massage error codes.
  2261.  *        return massaged error code.
  2262.  *    Code:
  2263.  *        Joanne Dow, Wizardess Designs, Jan 1999
  2264.  */
  2265. //USHORT __saveds __asm
  2266. //HDW_WriteBlock( register __a0 BootBlock *bb )
  2267.             printf ( "21) Write with checksum to a block of low disk. (Safe write - I hope!)\n\n");
  2268.             if ( baseunit == (ULONG) -1L )
  2269.             {
  2270.                 printf ( "Need a base unit for this command.\n" );
  2271.                 break;
  2272.             }
  2273.  
  2274.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  2275.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  2276.             if ( !deviceopen )
  2277.             {
  2278.                 printf ( "No device was opened!\n");
  2279.                 break;
  2280.             }
  2281.  
  2282.             {
  2283.                 BootBlock    *bb;
  2284.                 BootBlock    *bbt;
  2285.                 BootBlock    *bbtr;
  2286.                 ULONG         capacity;
  2287.                 ULONG         blocksize;
  2288.                 USHORT         ecode;
  2289.  
  2290.                 if ( QueryCapacity ( &capacity, &blocksize ))    // All sets page 0
  2291.                     printf ( "SCSI Read Capacity returns: %ld blocks of %ld bytes.\n",
  2292.                              capacity,
  2293.                              blocksize );
  2294.                 else
  2295.                 {
  2296.                     printf ( "SCSI Read Capacity failed\n" );
  2297.                     blocksize = 16384L;            // Better use a safe blocksize!
  2298.                 }
  2299.  
  2300.                 bb   = malloc ( sizeof ( BootBlock ) - 512 + blocksize );
  2301.                 bbt  = malloc ( sizeof ( BootBlock ) - 512 + blocksize );
  2302.                 bbtr = malloc ( sizeof ( BootBlock ) - 512 + blocksize );
  2303.                 if (( bb == NULL ) || ( bbt == NULL ) || ( bbtr == NULL ))
  2304.                 {
  2305.                     printf ( "BootBlock allocation failed!\n" );
  2306.                     if ( bb )
  2307.                         free ( bb );
  2308.                     if ( bbt )
  2309.                         free ( bbt );
  2310.                     if ( bbtr )
  2311.                         free ( bbtr );
  2312.                     break;
  2313.                 }
  2314.  
  2315.                 bb->bb_BlockNum   = mspage;    // Only value really needed
  2316.                 bbt->bb_BlockNum  = mspage;    // Only value really needed
  2317.                 bbtr->bb_BlockNum = mspage;    // Only value really needed
  2318.  
  2319.                 ecode = RawRead ( bb, blocksize );
  2320.                 if ( ecode == success )
  2321.                     printhex ( bb->bb_Data.bd_Bytes, 32 );
  2322.                 else
  2323.                 {
  2324.                     printf ( "RawRead failed %d!", ecode );
  2325.                     if ( bb )
  2326.                         free ( bb );
  2327.                     if ( bbt )
  2328.                         free ( bbt );
  2329.                     if ( bbtr )
  2330.                         free ( bbtr );
  2331.                     break;
  2332.                 }
  2333.                 printf ( "This IS dangerous. Continue? ");
  2334.                 gets ( bbt->bb_Data.bd_Bytes );
  2335.                 if ( bbt->bb_Data.bd_Bytes [ 0 ] != 'Y' )
  2336.                 {
  2337.                     printf ( "OK, I'm GONE Kemosabe!\n" );
  2338.                     if ( bb )
  2339.                         free ( bb );
  2340.                     if ( bbt )
  2341.                         free ( bbt );
  2342.                     if ( bbtr )
  2343.                         free ( bbtr );
  2344.                     break;
  2345.                 }
  2346.  
  2347.                 // Now fill the data block with OTHER data!
  2348.                 //
  2349.                 for ( ecode = 0; ecode < blocksize; ecode++ )
  2350.                     bbt->bb_Data.bd_Bytes [ ecode ] = (UBYTE) (ecode & 0xff);
  2351.  
  2352.                 bbt->bb_Data.bd_RDB.rdb_SummedLongs = blocksize >> 2;
  2353.                 bbt->bb_Data.bd_RDB.rdb_ID = 0x57495045;
  2354.                 // OK guys - this is the REAL BIG doodoo if we get it wrong!
  2355.                 // Write exactly the same data back....
  2356.                 ecode = WriteBlock ( bbt );
  2357.                 if ( ecode != success )
  2358.                 {
  2359.                     printf ( "WriteBlock failed, %d\n", ecode );
  2360.                     if ( bb )
  2361.                         free ( bb );
  2362.                     if ( bbt )
  2363.                         free ( bbt );
  2364.                     if ( bbtr )
  2365.                         free ( bbtr );
  2366.                     break;
  2367.                 }
  2368.                 else
  2369.                     printf ( "Block written = %d\n", bbt->bb_RWErrors.block_written );
  2370.  
  2371.                 // Reread it for confirmation it was written
  2372.                 ecode = RawRead ( bbtr, blocksize );
  2373.                 if ( ecode == success )
  2374.                     printhex ( bbtr->bb_Data.bd_Bytes, 32 );
  2375.                 else
  2376.                 {
  2377.                     printf ( "RawRead failed %d!", ecode );
  2378.                     if ( bb )
  2379.                         free ( bb );
  2380.                     if ( bbt )
  2381.                         free ( bbt );
  2382.                     if ( bbtr )
  2383.                         free ( bbtr );
  2384.                     break;
  2385.                 }
  2386.  
  2387.                 // IMMEDIATELY restore the original block!
  2388.                 ecode = RawWrite ( bb );
  2389.                 if ( ecode != success )
  2390.                 {
  2391.                     printf ( "RawWrite failed, %d\n", ecode );
  2392.                     if ( bb )
  2393.                         free ( bb );
  2394.                     if ( bbt )
  2395.                         free ( bbt );
  2396.                     if ( bbtr )
  2397.                         free ( bbtr );
  2398.                     break;
  2399.                 }
  2400.                 else
  2401.                     printf ( "Block written = %d\n", bb->bb_RWErrors.block_written );
  2402.  
  2403.                 for ( ecode = 0; ecode < blocksize; ecode++ )
  2404.                 {
  2405.                     if ( bbt->bb_Data.bd_Bytes [ ecode ] != bbtr->bb_Data.bd_Bytes [ ecode ] )
  2406.                     {
  2407.                         printf ( "Compare error at %d: %x vs %x\n",
  2408.                                  ecode,
  2409.                                  bbt->bb_Data.bd_Bytes [ ecode ],
  2410.                                  bbtr->bb_Data.bd_Bytes [ ecode ] );
  2411.                         break;
  2412.                     }
  2413.                 }
  2414.                 if ( ecode == blocksize )
  2415.                     printf ( "Completely successful compare here, too.\n" );
  2416.  
  2417.                 if ( bb )
  2418.                     free ( bb );
  2419.                 if ( bbt )
  2420.                     free ( bbt );
  2421.                 if ( bbtr )
  2422.                     free ( bbtr );
  2423.             }
  2424.  
  2425.             if ( deviceopen )
  2426.             {
  2427.                 printf ( "Closing opened device\n" );
  2428.                 HDWCloseDevice();
  2429.                 deviceopen = FALSE;
  2430.             }
  2431.         break;
  2432.  
  2433.         case 22:
  2434. /* HDW_WriteRDBs
  2435.  *    Description:
  2436.  *        Traverse "BootBlocks" RDB structures given.
  2437.  *        Write them to disk in the order the structures exist in the structure
  2438.  *        linked list.
  2439.  *
  2440.  *    Direct Inputs:
  2441.  *        none
  2442.  *
  2443.  *    Indirect Inputs:
  2444.  *        BlockLists        List head for the RDB blocklists to be written
  2445.  *
  2446.  *    Direct Outputs:
  2447.  *        Cumulative error code
  2448.  *
  2449.  *    Indirect Outputs:
  2450.  *        RDBs written to disk as RDBs.
  2451.  *
  2452.  *    Local Calls:
  2453.  *        HDW_BlockWrite ()
  2454.  *
  2455.  *    OS Calls:
  2456.  *        None
  2457.  *
  2458.  *    Algorithm:
  2459.  *        Trace the blocklist via the .Succ nodes writing the data segment
  2460.  *        of every BootBlock encountered to disk.
  2461.  *            If complete failure
  2462.  *                return
  2463.  *            if error worse than prior errors
  2464.  *                set new return value.
  2465.  *
  2466.  *    Code:
  2467.  *        Joanne Dow, Wizardess Designs, Jan 1999
  2468.  */
  2469. //USHORT __saveds __asm
  2470. //HDW_WriteRDBs ( void )
  2471.             printf ( "22) Read RDBs from <file.list> and write to disk. (The biggie!)\n\n" );
  2472.             if ( !filename )
  2473.             {
  2474.                 printf ( "Need a filename\n" );
  2475.                 break;
  2476.             }
  2477.             if ( strlen( filename ) > 248 )
  2478.             {
  2479.                 printf ( "Filename: %s is too long!\n", filename );
  2480.                 break;
  2481.             }
  2482.             if ( baseunit == (ULONG) -1L )
  2483.             {
  2484.                 printf ( "Need a base unit for this command.\n" );
  2485.                 break;
  2486.             }
  2487.             sprintf ( realfilename, "%s%s", filename, ".list" );
  2488.             rsuccess = ReadMountfile ( baseunit, realfilename, devicename );
  2489.             if ( rsuccess != 0 )
  2490.             {
  2491.                 printf ( "Mountfile read failed: %d\n", rsuccess );
  2492.                 break;
  2493.             }
  2494.  
  2495.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  2496.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  2497.             if ( !deviceopen )
  2498.             {
  2499.                 printf ( "No device was opened!\n");
  2500.                 break;
  2501.             }
  2502.  
  2503.             printf ( "Beginning to write RDBs.\n" );
  2504.  
  2505.             rwsuccess = WriteRDBs (  );
  2506.             if ( rwsuccess == 0 )
  2507.                 printf ( "You should have a new RDBs waiting on the disk.\n" );
  2508.             else
  2509.                 if ( rwsuccess != 0xffff )
  2510.                     printf ( "DOODOO CITY! RDB Write failed: %d\n", rwsuccess );
  2511.                 else
  2512.                     printf ( "RDB Write failed because this version does not have it supported.\n" );
  2513.  
  2514.             if ( deviceopen )
  2515.             {
  2516.                 printf ( "Closing opened device\n" );
  2517.                 HDWCloseDevice();
  2518.                 deviceopen = FALSE;
  2519.             }
  2520.             break;
  2521.  
  2522. /* HDW_WriteRDBStructs()
  2523.  *    Description:
  2524.  *        (Write RDBs to file instead of RDB area of disk.)
  2525.  *        Write the internal RDB structures to disk exactly as in memory.
  2526.  *
  2527.  *    Direct Inputs:
  2528.  *        Filename        Name of file to write. NB: This will clobber duplicates
  2529.  *
  2530.  *    Indirect Inputs:
  2531.  *        RDB structures in memory
  2532.  *
  2533.  *    Direct Outputs:
  2534.  *        ret            error 0 if success else error indication
  2535.  *
  2536.  *    Indirect Outputs:
  2537.  *        File written
  2538.  *
  2539.  *    Local Calls:
  2540.  *
  2541.  *    OS Calls:
  2542.  *        fclose ()
  2543.  *        fopen ()
  2544.  *        fwrite ()
  2545.  *
  2546.  *    Algorithm:
  2547.  *        if no RDBs in memory of file open fails exit with error
  2548.  *        else
  2549.  *            pointer = Basepointer->next
  2550.  *            while pointer
  2551.  *                translate and write block to disk file
  2552.  *                pointer = pointer->next
  2553.  *            endwhile
  2554.  *        endif
  2555.  *
  2556.  *    Code:
  2557.  *        Joanne Dow, Wizardess Designs, Jan 1999
  2558.  */
  2559.         case 23:
  2560.             printf ( "23) Read RDBs from disk and write RDB Structs to file.\n\n" );
  2561.             if ( !filename )
  2562.             {
  2563.                 printf ( "Need a filename\n" );
  2564.                 break;
  2565.             }
  2566.             if ( strlen( filename ) > 248 )
  2567.             {
  2568.                 printf ( "Filename: %s is too long!\n", filename );
  2569.                 break;
  2570.             }
  2571.             if ( baseunit == (ULONG) -1L )
  2572.             {
  2573.                 printf ( "Need a base unit for this command.\n" );
  2574.                 break;
  2575.             }
  2576.  
  2577.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  2578.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  2579.             if ( !deviceopen )
  2580.             {
  2581.                 printf ( "No device was opened!\n");
  2582.                 break;
  2583.             }
  2584.             printf ( "Attempting to read RDBs into library.\n");
  2585.  
  2586.             rwsuccess = ReadRDBs ( );
  2587.  
  2588.             if ( rwsuccess == success )
  2589.             {
  2590.                 sprintf ( realfilename, "%s%s", filename, ".rdb" );
  2591.                 rwsuccess = WriteRDBStructs ( realfilename );
  2592.                 if ( rwsuccess == 0 )
  2593.                     printf ( "You should have a new %s waiting.\n", realfilename );
  2594.                 else
  2595.                     printf ( "Mountfile write failed: %d\n", rwsuccess );
  2596.             }
  2597.             else
  2598.             {
  2599.                     printf ( "RDB read failed: %d\n", rwsuccess );
  2600.                     break;
  2601.             }
  2602.  
  2603.             if ( deviceopen )
  2604.             {
  2605.                 printf ( "Closing opened device\n" );
  2606.                 HDWCloseDevice();
  2607.                 deviceopen = FALSE;
  2608.             }
  2609.             break;
  2610.  
  2611.  
  2612.         case 24:
  2613.             printf ( "24) Read RDB Structs from file and write RDB Structs to file.\n\n" );
  2614.             if ( !filename )
  2615.             {
  2616.                 printf ( "Need a filename\n" );
  2617.                 break;
  2618.             }
  2619.             if ( strlen( filename ) > 248 )
  2620.             {
  2621.                 printf ( "Filename: %s is too long!\n", filename );
  2622.                 break;
  2623.             }
  2624.             if ( baseunit == (ULONG) -1L )
  2625.             {
  2626.                 printf ( "Need a base unit for this command.\n" );
  2627.                 break;
  2628.             }
  2629.  
  2630.             sprintf ( realfilename, "%s%s", filename, ".rdb" );
  2631.             rsuccess = ReadRDBStructs ( realfilename, baseunit );
  2632.  
  2633.             if ( rsuccess == 0 )
  2634.             {
  2635.                 sprintf ( realfilename, "%s%s", filename, "...rdb" );
  2636.                 rwsuccess = WriteRDBStructs ( realfilename );
  2637.                 if ( rwsuccess == 0 )
  2638.                     printf ( "You should have a new %s waiting.\n", realfilename );
  2639.                 else
  2640.                     printf ( "RDBfile write failed: %d\n", rwsuccess );
  2641.             }
  2642.             else
  2643.             {
  2644.                     printf ( "RDB read failed: %d\n", rwsuccess );
  2645.                     break;
  2646.             }
  2647.  
  2648.             break;
  2649.  
  2650.         case 25:    // Verify Data On Drive
  2651.             {
  2652.                 LONG ok;
  2653.  
  2654.                 printf ( "25) Verify data on disk.\n\n" );
  2655.                 if ( baseunit == (ULONG) -1L )
  2656.                 {
  2657.                     printf ( "You must enter a BU, Base Unit, number\n");
  2658.                     break;
  2659.                 }
  2660.                 // Open device here.
  2661.                 printf ( "Attempting to open: %s\n", devicename );
  2662.                 deviceopen = HDWOpenDevice ( devicename, baseunit );
  2663.                 if ( !deviceopen )
  2664.                 {
  2665.                     printf ("%s unit %ld failed to open\n", devicename, baseunit );
  2666.                     break;
  2667.                 }
  2668.  
  2669.                 ok = VerifyDrive ( CallBack );
  2670.                 printf ( "ok = %d\n", ok );
  2671.  
  2672.                 if ( deviceopen )
  2673.                 {
  2674.                     printf ( "Closing opened device\n" );
  2675.                     HDWCloseDevice();
  2676.                     deviceopen = FALSE;
  2677.                 }
  2678.             }
  2679.             break;
  2680.  
  2681.         case 26:
  2682.             printf ( "26) Read RDBStructs from <file>...rdb and write to Disk.\n");
  2683.             if ( !filename )
  2684.             {
  2685.                 printf ( "Need a filename\n" );
  2686.                 break;
  2687.             }
  2688.             if ( strlen( filename ) > 248 )
  2689.             {
  2690.                 printf ( "Filename: %s is too long!\n", filename );
  2691.                 break;
  2692.             }
  2693.             if ( baseunit == (ULONG) -1L )
  2694.             {
  2695.                 printf ( "Need a base unit for this command.\n" );
  2696.                 break;
  2697.             }
  2698.  
  2699.             sprintf ( realfilename, "%s%s", filename, ".rdb" );
  2700.             rsuccess = ReadRDBStructs ( realfilename, baseunit );
  2701.  
  2702.             if ( rsuccess == 0 )
  2703.             {
  2704.                 printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  2705.                 deviceopen = HDWOpenDevice ( devicename, baseunit );
  2706.                 if ( !deviceopen )
  2707.                 {
  2708.                     printf ( "No device was opened!\n");
  2709.                     break;
  2710.                 }
  2711.  
  2712.                 printf ( "Beginning to write RDBs.\n" );
  2713.  
  2714.                 rwsuccess = WriteRDBs (  );
  2715.                 if ( rwsuccess == 0 )
  2716.                     printf ( "You should have a new RDBs waiting on the disk.\n" );
  2717.                 else
  2718.                     if ( rwsuccess != 0xffff )
  2719.                         printf ( "DOODOO CITY! RDB Write failed: %d\n", rwsuccess );
  2720.                     else
  2721.                         printf ( "RDB Write failed because this version does not have it supported.\n" );
  2722.  
  2723.                 if ( deviceopen )
  2724.                 {
  2725.                     printf ( "Closing opened device\n" );
  2726.                     HDWCloseDevice();
  2727.                     deviceopen = FALSE;
  2728.                 }
  2729.             }
  2730.             break;
  2731.  
  2732.         case 27:
  2733.             printf ( "27) Read RDBs from disk and write RDB Structs memory thence to file and console as hex.\n\n" );
  2734.             if ( !filename )
  2735.             {
  2736.                 printf ( "Need a filename\n" );
  2737.                 break;
  2738.             }
  2739.             if ( strlen( filename ) > 248 )
  2740.             {
  2741.                 printf ( "Filename: %s is too long!\n", filename );
  2742.                 break;
  2743.             }
  2744.             if ( baseunit == (ULONG) -1L )
  2745.             {
  2746.                 printf ( "Need a base unit for this command.\n" );
  2747.                 break;
  2748.             }
  2749.  
  2750.             printf ( "Attempting to open: %s:%d\n", devicename, baseunit );
  2751.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  2752.             if ( !deviceopen )
  2753.             {
  2754.                 printf ( "No device was opened!\n");
  2755.                 break;
  2756.             }
  2757.             printf ( "Attempting to read RDBs into library.\n");
  2758.  
  2759.             rwsuccess = ReadRDBs ( );
  2760.  
  2761.             if ( rwsuccess == 0 )
  2762.             {
  2763.                 sizememneeded = 0;
  2764.                 rsuccess = OutMemRDBStructs ( NULL, &sizememneeded, 0 );
  2765.  
  2766.                 if ( rsuccess == 0 )
  2767.                 {
  2768.                     printf ( "7) Need %ld bytes of buffer for mountfile.\n", sizememneeded );
  2769.                     outmembuffer = malloc ( sizememneeded + 256 );
  2770.                     if ( outmembuffer )
  2771.                     {
  2772. //                        int i;
  2773. //                        for ( i = sizememneeded; i < sizememneeded + 256; i++)
  2774. //                            outmembuffer[i] = 'A';
  2775.                         rsuccess = OutMemRDBStructs ( outmembuffer, &sizememneeded, sizememneeded + 255 );
  2776.                         if ( rsuccess == 0 )
  2777.                         {
  2778.                             FILE *foofile = NULL;
  2779.                             ULONG    foo;
  2780.                             ULONG    offset = *(ULONG *) &outmembuffer[ 128 ];
  2781.  
  2782.                             outmembuffer [ sizememneeded + 255 ] = 0;
  2783.                             for ( foo = 0; foo < sizememneeded; foo+= 512L)
  2784.                             {
  2785.                                 printf ( "Block %2.2x:\n", (foo >> 9) + offset);
  2786.                                 printhex ( &outmembuffer[foo], 512 );
  2787.                             }
  2788. //                            printhex ( &outmembuffer[sizememneeded-16], 256 );
  2789.  
  2790.                             foofile = fopen ( filename, "wb" );
  2791.                             if ( foofile )
  2792.                             {
  2793.                                 fwrite ( outmembuffer, sizememneeded, 1, foofile );
  2794.                                 fclose ( foofile );
  2795.                                 foofile = NULL;
  2796.                             }
  2797.                         }
  2798.                         else
  2799.                         {
  2800.                             printf ( "Could not write the file: %d\n", rsuccess );
  2801.                         }
  2802.                     }
  2803.                 }
  2804.                 else
  2805.                     printf ( "Mountfile size write failed: %d\n", rsuccess );
  2806.             }
  2807.             else
  2808.                 printf ( "InMemMountfile failed, %ld\n", rsuccess );
  2809.  
  2810.             if ( deviceopen )
  2811.             {
  2812.                 printf ( "Closing opened device\n" );
  2813.                 HDWCloseDevice();
  2814.                 deviceopen = FALSE;
  2815.             }
  2816.             break;
  2817.  
  2818.         case 28:
  2819. #if 0
  2820.             if ( baseunit == (ULONG) -1L )
  2821.             {
  2822.                 printf ( "You must enter a BU, Base Unit, number\n");
  2823.                 break;
  2824.             }
  2825.             // Open device here.
  2826.             printf ( "Attempting to open: %s\n", devicename );
  2827.             deviceopen = HDWOpenDevice ( devicename, baseunit );
  2828.             if ( !deviceopen )
  2829.             {
  2830.                 printf ("%s unit %ld failed to open\n", devicename, baseunit );
  2831.                 break;
  2832.             }
  2833. #endif
  2834.             printf ( "Not implemented yet!\n" );
  2835.             break;
  2836.  
  2837.         case 100:
  2838. //ULONG __saveds __asm LowlevelFormat ( register __a0 long ( * __asm CallBack)
  2839. //                                      ( register __a0 HDWCallbackMsg *msg ))
  2840.             {
  2841.                 LONG ok;
  2842.  
  2843.                 printf ( "100) Format Drive - VERY DANGEROUS!\n\n" );
  2844.                 if ( baseunit == (ULONG) -1L )
  2845.                 {
  2846.                     printf ( "You must enter a BU, Base Unit, number\n");
  2847.                     break;
  2848.                 }
  2849.                 // Open device here.
  2850.                 printf ( "Attempting to open: %s\n", devicename );
  2851.                 deviceopen = HDWOpenDevice ( devicename, baseunit );
  2852.                 if ( !deviceopen )
  2853.                 {
  2854.                     printf ("%s unit %ld failed to open\n", devicename, baseunit );
  2855.                     break;
  2856.                 }
  2857.  
  2858.                 ok = LowlevelFormat ( CallBack );
  2859.                 printf ( "ok = %d\n", ok );
  2860.  
  2861.                 if ( deviceopen )
  2862.                 {
  2863.                     printf ( "Closing opened device\n" );
  2864.                     HDWCloseDevice();
  2865.                     deviceopen = FALSE;
  2866.                 }
  2867.             }
  2868.             break;
  2869.         }
  2870.     }
  2871.     else
  2872.     {
  2873.         usage ();
  2874.     }
  2875.  
  2876. cleanup:
  2877.  
  2878.     exit ( 0 );
  2879. }
  2880.  
  2881. /*
  2882. typedef struct
  2883. {
  2884.     STRPTR    devicename;
  2885.     LONG    board;
  2886.     LONG    address;
  2887.     LONG    lun;
  2888.     STRPTR    messagestring;
  2889.     LONG    extra;
  2890. } HDWCallbackMsg;
  2891. */
  2892. long __stdargs __saveds __asm CallBack ( register __a0 HDWCallbackMsg *msg )
  2893. {
  2894.     char      str[80];
  2895.     char      och = *msg->messagestring;
  2896.     char      ch = och;
  2897.     char     *string;
  2898.  
  2899.     if (( ch < MIN_MESSAGE )
  2900.      || ( ch > MAX_MESSAGE ))
  2901.         ch = 'c';
  2902.     string = callback_messages [ ch - 'A' ];
  2903.  
  2904.     switch ( msg->extra )
  2905.     {
  2906.       case EXTRA_BEFORE_TEST:    // before scan
  2907.         sprintf ( str,
  2908.                   callback_messages[0],        // Always "Scanning: " or equivalent
  2909.                   msg->devicename,
  2910.                   msg->board,
  2911.                   msg->lun,
  2912.                   msg->address );
  2913.         printf ( "%s%dD", str, strlen( str ) );
  2914.         flushall();
  2915.         break;
  2916.  
  2917.       case EXTRA_AFTER_TEST:
  2918.         printf ( "[%d%d%d] ", msg->board, msg->lun, msg->address );
  2919.         flushall();
  2920.         break;
  2921.  
  2922.       case EXTRA_BEFORE_VERIFY:        // Validate Drive
  2923.         // Print messagestring plus other data.
  2924.         // Perform an ARE YOU SURE function.
  2925.         printf ( callback_messages[2],
  2926.                  msg->lun, msg->address, msg->board );
  2927.         str[0] = 0;
  2928.         while ( 1 )
  2929.         {
  2930.             fgets ( str, 79, stdin);
  2931.             ch = tolower( str[0] );
  2932.             if ( ch == 'y' )
  2933.                 break;
  2934.             if ( ch == 'n' )
  2935.                 return FALSE;
  2936.             printf ( "Do you wish to continue?" );
  2937.         }
  2938.         break;
  2939.  
  2940.       case EXTRA_BEFORE_FORMAT:        // Format Drive
  2941.         // Print messagestring plus other data.
  2942.         // Perform an *BIG* ARE YOU SURE function.
  2943.         printf ( callback_messages[1],
  2944.                  msg->lun,
  2945.                  msg->address,
  2946.                  msg->board );
  2947.         str[0] = 0;
  2948.         while ( 1 )
  2949.         {
  2950.             fgets ( str, 79, stdin);
  2951.             ch = tolower( str[0] );
  2952.             if ( ch == 'y' )
  2953.                 break;
  2954.             if ( ch == 'n' )
  2955.                 return FALSE;
  2956.             printf ( "Are you VERY sure you want to do this?\n" );
  2957.         }
  2958.         while ( 1 )
  2959.         {
  2960.             printf ( "Let's try again, do you really want to destroy all your data?\n" );
  2961.             fgets ( str, 79, stdin);
  2962.             ch = str [ 0 ];
  2963.             if ( ch == 'y' )
  2964.                 break;
  2965.             if ( ch == 'n' )
  2966.                 return FALSE;
  2967.         }
  2968.         break;
  2969.  
  2970.       case EXTRA_UPDATE_VERIFY:        // 4
  2971.           chkabort();
  2972.         if ( aborted )            // Note we do NOT clear the aborted flag.
  2973.             return FALSE;
  2974.         printf ( "LUN %d on drive %d on board %d: ",
  2975.                  msg->lun, msg->address, msg->board );
  2976.  
  2977.         switch ( ch )
  2978.         {
  2979.           case 'E':
  2980.             printf ( string, &msg->messagestring [ 2 ] );
  2981.             break;
  2982.  
  2983.           case 'O':
  2984.             printf ( string, msg->param1, msg->param2, msg->param3 );
  2985.             break;
  2986.  
  2987.           case 'R':
  2988.           case 'U':
  2989.           case 'X':
  2990.           case 'Y':
  2991.           case 'Z':
  2992.           case '[':
  2993.           case '\\':
  2994.           case ']':
  2995.           case '^':
  2996.           case '_':
  2997.           case '`':
  2998.           case 'b':
  2999.               printf ( string );
  3000.               break;
  3001.  
  3002.           case 'S':
  3003.           case 'T':
  3004.           case 'V':
  3005.           case 'a':
  3006.             printf ( string, msg->param1 );
  3007.               break;
  3008.  
  3009.           case 'W':
  3010.             printf ( string, msg->param1, msg->param2 );
  3011.               break;
  3012.  
  3013.           default:
  3014.             printf ( string, och );
  3015.               break;
  3016.         }
  3017.         flushall();
  3018.           break;
  3019.  
  3020.       case EXTRA_VERIFY_REASSIGN:
  3021.         while ( 1 )
  3022.         {
  3023.             printf ( string, msg->param1 );
  3024.             fgets ( str, 79, stdin);
  3025.             ch = str [ 0 ];
  3026.             if ( ch == 'y' )
  3027.                 break;
  3028.             if ( ch == 'n' )
  3029.                 return FALSE;
  3030.         }
  3031.           break;
  3032.  
  3033.       case EXTRA_VERIFY_FINISHED:
  3034.           printf ( "LUN %d on Drive %d on board %d:\n",
  3035.                  msg->lun, msg->address, msg->board );
  3036.         switch ( ch )
  3037.         {
  3038.           case 'D':
  3039.           case 'H':
  3040.           case 'I':
  3041.           case 'J':
  3042.           case 'K':
  3043.           case 'L':
  3044.           case 'M':
  3045.           case 'N':
  3046.               printf ( string );
  3047.               break;
  3048.  
  3049.           case 'F':
  3050.               printf ( string, &msg->messagestring [ 2 ] );
  3051.               break;
  3052.  
  3053.           case 'G':
  3054.               printf ( string, msg->param1 );
  3055.               break;
  3056.  
  3057.           case 'Q':
  3058.               printf ( string, msg->param1, msg->param2, msg->param3 );
  3059.             break;
  3060.  
  3061.           default:
  3062.             printf ( string, och );
  3063.               break;
  3064.         }
  3065.  
  3066.         printf ( "OK\n" );
  3067.         fgets ( str, 79, stdin);
  3068.           break;
  3069.  
  3070.       default:
  3071.           break;
  3072.     }
  3073.  
  3074.     return TRUE;
  3075. }
  3076.