home *** CD-ROM | disk | FTP | other *** search
/ ftp.update.uu.se / ftp.update.uu.se.2014.03.zip / ftp.update.uu.se / pub / rainbow / msdos / decus / RB139 / rx50-103.lzh / RX50INIT.C < prev    next >
C/C++ Source or Header  |  1986-09-10  |  8KB  |  346 lines

  1. /*t RX50INIT -- Initialize RX50 MS-DOS Data Diskette */
  2. /*----------------------------------------------------------------------*/
  3. /*                                    */
  4. /*           RX50INIT -- Initialize RX50 MS-DOS Data Diskette        */
  5. /*                                    */
  6. /*----------------------------------------------------------------------*/
  7.  
  8. #define PROGREV "[1.03]"            /*      09-Dec-84 14:00 */
  9.  
  10. /*        Copyright (c) 1984 by    Robert F. Morse
  11. **                    17 Bowdoin Street
  12. **                    Cambridge, MA  02138
  13. **
  14. **
  15. **  Function:  Initialize the directory and FAT of an RX50 diskette to
  16. **    be used as an MS-DOS data diskette for a DECmate or Rainbow.
  17. **
  18. **  Invocation:
  19. **
  20. **        RX50INIT  [d:]  [volume-name]
  21. **
  22. **    The drive letter is optional; D is the default.  The volume name
  23. **    is optional; if none is given, none is written in the directory.
  24. **
  25. **  Notes:  This version is for an IBM PC-AT and requires that device
  26. **    driver RX50DRVR.SYS be loaded when the system was booted.  This
  27. **    driver maps references to drive D: to the AT's high-capacity drive
  28. **    (normally drive A:) and sets that drive to handle the 80-track
  29. **    10-sector RX50 format.
  30. */
  31.  
  32. #include "standard.h"
  33. #include "msdosdir.h"
  34. #include "msdosdpb.h"
  35.  
  36. #define SECTOR_SIZE    512
  37.  
  38. #define FAT_SECTORS    3
  39. #define FAT_BUFSIZE    (FAT_SECTORS * SECTOR_SIZE)
  40. #define FAT_START_1    20
  41. #define FAT_START_2    23
  42.  
  43. #define CLUSTER_EOF    0x0FFF
  44. #define CLUSTER_MEDIA  0x0FFA
  45.  
  46. #define DIR_SECTORS    6
  47. #define DIR_BUFSIZE    (DIR_SECTORS * SECTOR_SIZE)
  48. #define DIR_START      26
  49.  
  50. #define DPB_MEDIA        0xFA
  51. #define DPB_MAX_CLUSTER  769
  52.  
  53. char *malloc();
  54. /*^---------- Global Constants & Data -------------*/
  55.  
  56. char *fatbuf;
  57. MSDOS_Dir *dirbuf;
  58.  
  59. char vol_name[12] = "           ";
  60.  
  61. uint target_unit = 3;            /*  default drive is D:  */
  62.  
  63. char *disk_errs[] ={    "Write protect",    /*  0 */
  64.             "Invalid unit",        /*  1 */
  65.             "Not ready",        /*  2 */
  66.             "Bad command",        /*  3 */
  67.             "Data CRC",        /*  4 */
  68.             "Bad request",        /*  5 */
  69.             "Seek",            /*  6 */
  70.             "Unknown media",    /*  7 */
  71.             "Sector not found",    /*  8 */
  72.             "Out of paper",        /*  9 */
  73.             "Write fault",        /* 10 */
  74.             "Read fault",        /* 11 */
  75.             "I/O",            /* 12 */
  76.             "",            /* 13 */
  77.             "",            /* 14 */
  78.             "Invalid disk change"};    /* 15 */
  79.  
  80. /* BOOT BLOCK, to be written in block 0 */
  81.  
  82. struct {byte jump[3];
  83.     char oem_name[8];
  84.  
  85.     int  bytes_sector;
  86.     byte sects_alu;
  87.     int  reserved_sects;
  88.     byte num_fats;
  89.     int  num_dirents;
  90.     int  total_sectors;
  91.     byte fat_id;
  92.     int  fat_sectors;
  93.  
  94.     int  sects_track;
  95.     int  num_heads;
  96.     int  hidden_sects; } boot_block = {
  97.  
  98.                 {0xE9, 0x00, 0x00},
  99.                 {'D', 'E', 'C', '-', 'R', 'X', '5', '0'},
  100.                 512, 1, 20, 2, 96, 800, 0xFA, 3,
  101.                 10, 1, 0 };
  102.     
  103. /*^*/
  104.  
  105. #define DOS_GETDATE  0x2A
  106. #define DOS_GETTIME  0x2C
  107.  
  108. typedef struct {
  109.   unsigned Wyr;
  110.   unsigned Wmo;
  111.   unsigned Wda;
  112.   unsigned Whr;
  113.   unsigned Wmn;
  114.   unsigned Wsc;
  115.   unsigned Whn;
  116.   unsigned Wdw;
  117.         } When;
  118.  
  119. When now;
  120.  
  121. timestamp (w)    When *w;
  122.     {
  123.         RuptRegs reg;
  124.  
  125.     getsegs (®);
  126.     
  127.     doscall (DOS_GETDATE, ®);
  128.     w->Wyr = reg.w.cx;
  129.     w->Wmo = reg.b.dh;
  130.     w->Wda = reg.b.dl;
  131.     w->Wdw = reg.b.al;
  132.     
  133.     doscall (DOS_GETTIME, ®);
  134.     w->Whr = reg.b.ch;
  135.     w->Wmn = reg.b.cl;
  136.     w->Wsc = reg.b.dh;
  137.     w->Whn = reg.b.dl;
  138.     }
  139. /*^------------------------------------------------------------*/
  140.    write_sect (unit, block, count, buffer)   char *buffer;
  141. /*---------------------------------------------------------------
  142. ** Write <count> sectors beginning with sector <block> on <unit>
  143. ** from <*buffer>, returning 0 if OK or aborting the program if
  144. ** there is an uncorrectable error.
  145. */
  146.  
  147. #define MSDOS_WRITE      0x26
  148. #define CF_MASK        0x0001
  149.  
  150.     {    RuptRegs reg;
  151.         char ch;
  152. again:
  153.     getsegs (®);
  154.     reg.w.ax = unit;
  155.     reg.w.bx = (uint) buffer;
  156.     reg.w.cx = count;
  157.     reg.w.dx = block;
  158.     
  159.     if (intcall (MSDOS_WRITE, ®) & CF_MASK)
  160.       {
  161.       cputf ("\n\n%s error writing drive %c:\nAbort, Retry?  ",
  162.           disk_errs[reg.b.al], unit + 'A');
  163.       do ch = cgetcne();
  164.         while (strchr ("AaRr\003", ch) == NULL);
  165.       cputc ('\n');
  166.       if (toupper (ch) == 'R')
  167.         goto again;
  168.       cputs ("CANCELLED");
  169.       _exit (1);
  170.       }
  171.     else
  172.       return (0);
  173.     }
  174.  
  175.  
  176.  
  177. get_fat (fat, n)    char *fat;
  178.     {    int  w;
  179.     w = * (int*) &fat[(n*3)/2];
  180.     if (n & 1)
  181.       w >>= 4;
  182.     return(w & 0x0FFF);
  183.     }
  184.  
  185. put_fat (fat, n, val)    char *fat;
  186.     {    int *w;
  187.     w = (int*) &fat[(n*3)/2];
  188.     if (n & 1)
  189.       *w = (*w & 0x000F) | ((val << 4) & 0xFFF0);
  190.     else
  191.       *w = (*w & 0xF000) | (val & 0xFFF);
  192.     }
  193. /*^-----------------------------------*/
  194.    main (argc, argv)    char *argv[];
  195. /*------------------------------------*/
  196.     {    int n, x, y, err;
  197.         char ch;
  198.           MSDOS_Dir *p;
  199.         MSDOS_Dpb dpb;
  200.         RuptRegs reg;
  201.         unsigned int attr;
  202.         unsigned int clus;
  203.         
  204.     cputf ("%-45.45s%10.10s%24.24s\n%79.79s",
  205.             "Initialize DEC RX50 Data Diskette",
  206.             PROGREV,
  207.             "Copyright (c) 1984",
  208.             "by Robert F. Morse");
  209.  
  210.     n = 1;
  211. /*
  212. ** Get the drive letter (if any) from the command arguments.
  213. */
  214.     if (n < argc)
  215.       {
  216.       if (argv[n][1] == ':')
  217.         {
  218.         if ( ((target_unit = toupper (argv[n][0]) - 'A') < 25) &&
  219.              (strlen (argv[n]) == 2) )
  220.           ++n;
  221.         else
  222.           {
  223.           cputf ("\n    INVALID SOURCE DRIVE LETTER   %s", argv[n]); 
  224.           _exit (1);
  225.           }
  226.         }
  227.       }
  228. /*
  229. ** Get the volume name (if any) from the command arguments.
  230. */
  231.     if (n < argc)
  232.       {
  233.       for (x = 0;  x < 11;  ++x)
  234.         {
  235.         if ((ch = argv[n][x]) == '\0')
  236.           break;
  237.         if (isalnum (ch) || (ch == '-'))
  238.           vol_name[x] = toupper (ch);
  239.         else
  240.           {
  241.           cputf ("\n    INVALID CHARACTER '%c' IN VOLUME NAME %s", ch, argv[n]);
  242.           _exit (1);
  243.           }
  244.         }
  245.       }
  246. /*
  247. ** Allocate memory for disk data buffers.
  248. */    
  249.     if ( ((fatbuf = malloc(FAT_BUFSIZE)) == NULL) ||
  250.          ((dirbuf = (MSDOS_Dir*) malloc(DIR_BUFSIZE)) == NULL)   )
  251.       {
  252.       cputs( "\n    INSUFFICIENT MEMORY");
  253.       _exit(1);
  254.       }
  255. /*
  256. ** Ask the operator to insert a diskette in the target drive.
  257. */
  258.     cputf(
  259. "\n    Insert diskette into drive \033[7m %c \033[m and press ENTER  ",
  260.         target_unit + 'A');
  261.     do {
  262.       ch = cgetcne ();
  263.       if (ch == 3)                /* quit on ctrl/C */
  264.           {
  265.           cputf ("\nCANCELLED");
  266.            _exit (1);
  267.           }
  268.        } while (ch != '\r');
  269. /*
  270. ** Get the diskette's DPB to check that it is a possible RX50 and is NOT
  271. ** (horrors!) the hard disk.  Also catches uninstalled drive letters.
  272. */
  273.     reg.b.dl = target_unit + 1;
  274.     doscall (0x32, ®);
  275.     if (reg.b.al)
  276.       {
  277.       cputf ("\n    DRIVE %c: NOT INSTALLED", target_unit + 'A');
  278.       _exit (1);
  279.       }
  280.  
  281.     peek (reg.w.ds, reg.w.bx, &dpb, sizeof(dpb));
  282.     if ((dpb.Dpb_max_cluster != DPB_MAX_CLUSTER) ||
  283.         (dpb.Dpb_media       != DPB_MEDIA) )
  284.       {
  285.       cputf ("\n    DRIVE %c: CANNOT HANDLE RX50 DISKETTES", target_unit + 'A');
  286.       _exit (1);
  287.       }
  288. /*      
  289. ** Set up and write the FAT.
  290. **
  291. ** Note:  This first attempt to write is on cylinder 2, which will fail
  292. **        with a sector-not-found if a 48-tpi diskette is in the drive.
  293. */ 
  294.     setmem (fatbuf, FAT_BUFSIZE, 0x00);
  295.     
  296.     put_fat (fatbuf, 0, CLUSTER_MEDIA);
  297.     put_fat (fatbuf, 1, CLUSTER_EOF);
  298.     
  299.     write_sect (target_unit, FAT_START_1, FAT_SECTORS, fatbuf);
  300.     write_sect (target_unit, FAT_START_2, FAT_SECTORS, fatbuf);
  301. /*
  302. ** Set up and write the directory.
  303. */
  304.     setmem (dirbuf, DIR_BUFSIZE, 0x00);
  305.  
  306.     timestamp (&now);
  307.  
  308.     if (vol_name[0] != ' ')
  309.       {
  310.       p = dirbuf;
  311.       memcpy (p->Dir_name, vol_name, 11);
  312.       p->Dir_attr = Dirattr_VOL;
  313.       p->Dir_date.Dt_yr = now.Wyr - 1980;
  314.       p->Dir_date.Dt_mo = now.Wmo;
  315.       p->Dir_date.Dt_da = now.Wda;
  316.       p->Dir_time.Dt_hr = now.Whr;
  317.       p->Dir_time.Dt_mn = now.Wmn;
  318.       p->Dir_time.Dt_sc = now.Wsc / 2;
  319.       }
  320.     
  321.     write_sect (target_unit, DIR_START, DIR_SECTORS, dirbuf);
  322. /*
  323. ** Write the boot block in block 0.
  324. */
  325.     setmem (fatbuf, SECTOR_SIZE, 0x00);
  326.     memcpy (fatbuf, &boot_block, sizeof (boot_block));
  327.     write_sect (target_unit, 0, 1, fatbuf);
  328. /*
  329. ** Write an all-zero sector in block 1 (the IBM FAT position).
  330. */
  331.     setmem (fatbuf, SECTOR_SIZE, 0x00);
  332.     write_sect (target_unit, 1, 1, fatbuf);
  333. /*
  334. ** Write an all-zero sector in block 10 to forstall any attempted DECmate boot
  335. */
  336.     write_sect (target_unit, 10, 1, fatbuf);
  337. /*
  338. ** Done--announce success and exit.
  339. */
  340.     cputs ("\n    Diskette initialized");
  341.     if (vol_name[0] != ' ')
  342.       cputf (", volume name is %s", vol_name);
  343.     _exit (0);
  344.     }
  345.                 /******/
  346.