home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDX501 / HDX.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  54.9 KB  |  2,273 lines

  1. /* hdx.c */
  2.  
  3. /*
  4.  * Atari Hard Disk Installation Utility
  5.  * Copyright 1988 Atari Corp.
  6.  *
  7.  * Associated files
  8.  *    hdx.rsc        resource file
  9.  *    wincap        hard disk database (text file)
  10.  *
  11.  *    hdx.h        object tree definitions
  12.  *    defs.h        constant definitions
  13.  *    part.h        ST structure definitions
  14.  *    ipart.h        IBM structure definitions
  15.  *
  16.  *    hdx.c        top level, user interface (this file)
  17.  *    epart.c        edit partition sizes
  18.  *    fmt.c        disk formatting
  19.  *    part.c        partition reading/writing
  20.  *    sect.c        sector reading, writing, zeroing
  21.  *    string.c    string functions (matching, concat, ...)
  22.  *    assist.c    markbad(), zero()
  23.  *    wincap.c    hard disk parameter / partition size database
  24.  *    st.c        random ST functions (delay, reboot, ...)
  25.  *
  26.  *----
  27.  * 11-May-1988    ml.    Cleaned up the memory management in the program
  28.  *            (ie. for all files).  Memory chunks which are for
  29.  *            sure will be < 32k is allocated using malloc(),
  30.  *            whereas chunks >= 32k is allocated using Malloc().
  31.  *            When using malloc(), you will get the 'Stack Over-
  32.  *            flow message if you are in Supervisor mode and 
  33.  *            you have your own supervisor stack.  To get around
  34.  *            this, have to use mymalloc() (in mymalloc.s).
  35.  * 15-Mar-1988    ml.    Changed interface to Markbad.
  36.  * 11-Jan-1988    ml.    Modified dialogue boxes.
  37.  * 07-Dec-1987    ml.    Started to add in concept of Bad Sector List.
  38.  * ??-Oct-1987  ml.    Partition and Disk type menu now has 15 entries 
  39.  *            instead of 16.
  40.  * 30-Sep-1987    ml.    Inherited 'this' from Landon Dyer.
  41.  * 24-Mar-1986 lmd    Released to software test.
  42.  * 15-Mar-1986 lmd    Hacked up from earlier version by Jim Tittsler.
  43.  * 8-Nov-1988  jye. change and add some codes so that can be used for extended
  44.  *                    and big partition.
  45.  * 13-Jun-1989 jye. Change and add some codes so that HDX can be deal with
  46.  *                    acsi and scsi drives.
  47.  * 22-Jan-1990 jye. Change the HDX so that we don't have to put a informations
  48.  *                    of a drive into the Wincap file.
  49.  * 13-Mar-1990 jye. change the HDX to a genetic one so that the user don't
  50.  *                    need know what kind of drive.
  51.  * 20-Jul-1990 jye. change the interface about the unit select. In the new 
  52.  *                    interface, user tells the type of drive is acsi or scsi,
  53.  *                    then selects unit.
  54.  * 01-Aug-1990 jye. Change hard disk size request from mdsence to readcap.
  55.  * 25-Jul-1991 jye. Change the Hdx so that can be used for IDE-AT drive.
  56.  * 11-Nov-1991 jye. change the hdx so that can got the hard disk size from
  57.  *                    page 0, or 3, or 4, or from the wincap. For the SCSI drive,
  58.  *                    getting the disk size from wincap or readcap.
  59.  * 7-Jul-1992  jye. Change the hdx so that can be used for the sparrow scsi.
  60.  */
  61.  
  62. #include "obdefs.h"
  63. #include "gemdefs.h"
  64. #include "osbind.h"
  65. #include "mydefs.h"
  66. #include "part.h"
  67. #include "bsl.h"
  68. #include "hdx.h"
  69. #include "ipart.h"
  70. #include "addr.h"
  71. #include "myerror.h"
  72.  
  73. #define MFM 17
  74.  
  75. extern char sbuf[];
  76. extern int rebootp;
  77. extern long gbslsiz();
  78. extern long get3bytes();
  79. extern long get4bytes();
  80. extern long bslsiz;
  81. extern BYTE *bsl;
  82. extern int uplim;            /* the number of partitions */
  83. extern long sptrk;
  84. extern long spcyl;
  85. extern int ibmpart;
  86. extern int yesscan;
  87. extern long disksiz;
  88. extern long ratio;
  89. extern int typedev;
  90. extern int typedrv;
  91. extern int prevnpart;
  92. extern int atexst;        /* set for AT drive exist */
  93.  
  94. /* Globals */
  95. int rebootp = 0;    /* 1: must reboot (not return to desktop) */
  96. int tformat;            /* TRUE: just formatted disk */
  97. int running;        /* 1: continue evnt_multi() loop */
  98. char sbuf[512];        /* error message buffer */
  99. long extsiz;        /* the size of extened partition */
  100. long ostack;        /* old stack pointer */
  101. int toibm;            /* the flag of partition to ibm format */
  102. int ibm2st;            /* the flag for IBM partition to ST */
  103. long bps;            /* bytes per sector */
  104. int npart;            /* number of partition */
  105. int ext;            /* the index of extended partition */
  106. int extend;            /* the index of end extended partition */
  107. int showmany;        /* the flag that show the too much device alert box */
  108. char ttscsi;        /* SCSI hard disk drive */
  109. char spscsixst;        /* set for sparrow scsi drive exist */
  110. int noacsi;            /* set for no ACSI dirve in the system */
  111. int needscan;        /* TRUE: if info in the LOGMAP update */
  112. int noinfo=1;            /* 1: no informations in the wincap */
  113. int athead;            /* the # of data heads on the AT drive */
  114. int atcyl;            /* the # of cylinders on the AT drive */
  115. int atspt;            /* the # of sectors per track on the AT drive */
  116. int ok2draw;        /* go ahead to draw the change part of dialog box */
  117. int ndevs;            /* the # of devices */
  118. char *drvid[] ={    /* for the id of the drives */
  119.     "123456789012345678901234567",
  120.     "123456789012345678901234567",
  121.     "123456789012345678901234567",
  122.     "123456789012345678901234567",
  123.     "123456789012345678901234567",
  124.     "123456789012345678901234567",
  125.     "123456789012345678901234567",
  126.     "123456789012345678901234567",
  127.     "123456789012345678901234567",
  128.     "123456789012345678901234567",
  129.     "123456789012345678901234567",
  130.     "123456789012345678901234567",
  131.     "123456789012345678901234567",
  132.     "123456789012345678901234567",
  133.     "123456789012345678901234567",
  134.     "123456789012345678901234567",
  135.     "123456789012345678901234567",
  136.     "Identification unavaliable",
  137.     "Not responding",
  138.     "ACSI 0",        /* index is 19 */
  139.     "ACSI 1",
  140.     "ACSI 2",
  141.     "ACSI 3",
  142.     "ACSI 4",
  143.     "ACSI 5",
  144.     "ACSI 6",
  145.     "ACSI 7",
  146.     "SCSI 0",        /* index is 27 */
  147.     "SCSI 1",
  148.     "SCSI 2",
  149.     "SCSI 3",
  150.     "SCSI 4",
  151.     "SCSI 5",
  152.     "SCSI 6",
  153.     "SCSI 7",
  154.     "IDE 0",            /* index is 35 */
  155.     " "
  156. };
  157.  
  158. DEVSET devid[17];
  159.  
  160. /*  Logical-to-dev+partition mapping table. */
  161. extern int nlogdevs;        /* #logical devs found */
  162. extern LOGMAP logmap[];        /* logical dev map */
  163. extern int livedevs[];        /* live physical dev flag */
  164. extern int idevs[];            /* the devise have a id */
  165. extern char cachexst;        /* 0: no cache. 1: with cache */
  166.  
  167. /* Partition related variables */
  168. long mxpsiz = MAXPSIZ;
  169.  
  170. /* AES (windows and messages) related variables */
  171. int gl_hchar;        /* height of system font (pixels) */
  172. int gl_wchar;        /* width of system font (pixels) */
  173. int gl_wbox;        /* width of box able to hold system font */
  174. int gl_hbox;        /* height of box able to hold system font */
  175.  
  176. int phys_handle;    /* physical workstation handle */
  177. int handle;        /* virtual workstation handle */
  178. int wi_handle;        /* window handle */
  179.  
  180. int formw, formh, sx, sy, lx, ly;    /* dialogue box dimensions */
  181. int xdesk, ydesk, hdesk, wdesk;        /* window X, Y, width, height */
  182. int xwork, ywork, hwork, wwork;        /* desktop and work areas */
  183.  
  184. int msgbuff[8];        /* event message buffer */
  185. int keycode;        /* keycode returned by event-keyboard */
  186. int mx, my;        /* mouse x and y pos. */
  187. int butdown;        /* button state tested for, UP/DOWN */
  188. int ret;        /* dummy return variable */
  189. int pnf;        /* 1: partition or format; 0: zero or markbad */
  190. int hidden;        /* current state of cursor */
  191. int contrl[12];
  192. int intin[128];
  193. int ptsin[128];
  194. int intout[128];
  195. int ptsout[128];    /* storage wasted for idiotic bindings */
  196. int work_in[11];    /* Input to GSX parameter array */
  197. int work_out[57];    /* Output from GSX parameter array */
  198. int pxyarray[10];    /* input point array */
  199. int blitxst;        /* the flag for check the BLiTTER */
  200.  
  201. /*
  202.  * Top level;
  203.  * we get control from the desktop.
  204.  */
  205. main()
  206. {
  207.     pnf = 0;        /* set the flag to it isn't partition yet */
  208.     appl_init();
  209.     phys_handle=graf_handle(&gl_wchar, &gl_hchar, &gl_wbox, &gl_hbox);
  210.     wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk);
  211.     open_vwork();
  212.     wi_handle=wind_create(0x0040&0x0080, xdesk, ydesk, wdesk, hdesk);
  213.  
  214.     hidden = FALSE;
  215.     butdown = TRUE;
  216.  
  217.     /* doing a checking see if the cache in the system */
  218.     cachexst = (char) chkcache();
  219.  
  220.     /* check the existence of the BLiTTER */
  221.     blitxst = chkblit();
  222.  
  223.     if (!rsrc_load(RESOURCEFILE)) {
  224.     errs("[2][|", RESOURCEFILE, "][ EXIT ]");
  225.     goto punt;
  226.     }
  227.  
  228.     
  229.     /* Get all addresses of dialogues from resource file */
  230.     if (getalladdr() != OK) {
  231.     errs("[2][|", RESOURCEFILE, "][ EXIT ]");
  232.     goto punt;
  233.     }
  234.  
  235.  
  236.     /*
  237.      * Get maximum partition size from
  238.      * wincap "@@" entry.
  239.      */
  240.     /*
  241.     if (wgetent("Parameters", "@@") == OK) {
  242.     if (wgetnum("ms", &mxpsiz) != OK)
  243.         mxpsiz = MAXPSIZ;
  244.     } else {
  245.         goto punt;
  246.     }
  247.     */
  248.  
  249.     needscan = TRUE;
  250.  
  251. redomul:
  252.     ARROW_MOUSE;
  253.  
  254.     /* display menu bar */
  255.     menu_bar(menuobj, 1);
  256.  
  257.     running = TRUE;
  258.     while (running) {
  259.         domulti();
  260.     }
  261.  
  262.     /*
  263.      * If nothing has been done to the hard disks
  264.      * then just get out, back to the desktop.
  265.      * Otherwise reboot the system.
  266.      */
  267.     menu_bar(menuobj, 0);        /* erase menu bar */
  268.  
  269. punt:
  270.     /*
  271.      * If we have to reboot,
  272.      * tell the user and then do it.
  273.      *
  274.      */
  275.     if (rebootp) {
  276.         if (form_alert(2, autoboot) == 1)    {
  277.             reboot();
  278.         } else {
  279.             goto redomul;
  280.         }
  281.     }
  282.  
  283.     wind_delete(wi_handle);
  284.     v_clsvwk(handle);
  285.     appl_exit();
  286. }
  287.  
  288.  
  289. /*
  290.  * Get a single event, process it, and return.
  291.  *
  292.  */
  293. domulti(){
  294.     int event;
  295.     
  296.     event = evnt_multi(MU_MESAG,
  297.             1,1,butdown,
  298.             0,0,0,0,0,
  299.             0,0,0,0,0,
  300.             msgbuff,0,0,&mx,&my,&ret,&ret,&keycode,&ret);
  301.  
  302.     if (event & MU_MESAG) {
  303.         wind_update(TRUE);
  304.     switch (msgbuff[0]) {
  305.         case WM_REDRAW:
  306.         do_redraw(msgbuff[4],msgbuff[5],msgbuff[6],msgbuff[7]);
  307.         break;
  308.  
  309.         case MN_SELECTED:
  310.             BEE_MOUSE;
  311.         switch(msgbuff[3]) {
  312.             case MNDISK:
  313.             switch (msgbuff[4]) {
  314.                 case DIFORM:
  315.                     if ((needscan) && (rescan(0,1) == ERROR))    {
  316.                         break;    /* don't report medium changed */
  317.                     }
  318.                     tformat = TRUE;
  319.                     needscan = FALSE;
  320.                     dodiform();
  321.                     tformat = FALSE;
  322.                     break;
  323.                 case DIPART:
  324.                     if ((needscan)&&(rescan(0,2) == ERROR))    {
  325.                         break;    /* don't report medium changed */
  326.                     }
  327.                     needscan = FALSE;
  328.                     dodipart(-1, NULL, NULL);
  329.                     break;
  330.                 case DIZERO:
  331.                     if (pnf)    {
  332.                         err(needboot);
  333.                     } else {
  334.                         if ((needscan)&&(rescan(0,0) == ERROR))    {
  335.                             break;    /* don't report medium changed */
  336.                         }
  337.                         needscan = FALSE;
  338.                         dodizero();
  339.                     }
  340.                     break;
  341.                 case DIMARK:
  342.                     if (pnf)    {
  343.                         err(needboot);
  344.                     } else {
  345.                         if ((needscan)&&(rescan(0,0) == ERROR))    {
  346.                             break;    /* don't report medium changed */
  347.                         }
  348.                         needscan = FALSE;
  349.                         dodimark();
  350.                     }
  351.                     break;
  352.                 /*
  353.                 case DISHIP:
  354.                     if ((needscan)&&(rescan(0,1) == ERROR))    {
  355.                         break; don't report medium changed
  356.                     }
  357.                     needscan = FALSE;
  358.                     dodiship();
  359.                     break;
  360.                 */
  361.                 default:        break;
  362.             }
  363.             break;
  364.  
  365.             case MNFILE:
  366.             switch (msgbuff[4]) {
  367.                 case FIQUIT:
  368.                 running = 0;
  369.                 break;
  370.  
  371.                 default:
  372.                 break;
  373.             }
  374.             break;
  375.             
  376.             case MNDESK:
  377.             if(msgbuff[4] == DEABOUT) {
  378.                 strcpy(abtdial[ABVERSN].ob_spec, "Version 5.00");
  379.                  abtdial[ABOK].ob_state = NORMAL;
  380.                 execform(abtdial);
  381.             }
  382.             break;        /* "cannot happen" */
  383.         }
  384.  
  385.         menu_tnormal(menuobj, msgbuff[3], 1);    /* back to normal */
  386.             ARROW_MOUSE;
  387.         break;
  388.         
  389.         case WM_NEWTOP:
  390.         case WM_TOPPED:
  391.         wind_set(wi_handle, WF_TOP, 0, 0, 0, 0);
  392.         break;
  393.  
  394.         case WM_CLOSED:
  395.         running = FALSE;
  396.         break;
  397.  
  398.         default:
  399.         break;
  400.     }
  401.     wind_update(FALSE);
  402.     }
  403. }
  404.  
  405.  
  406. /*
  407.  * Default partition name (no "pt" entry).
  408.  */
  409. #define    DEF_PARTNAME    "4-6-10"
  410.  
  411.  
  412. /*
  413.  * Map from button in format dial.
  414.  */
  415. int pfmt[] = {
  416.     PFMT0, PFMT1, PFMT2, PFMT3,
  417.     PFMT4, PFMT5, PFMT6, PFMT7,
  418.     PFMT8, PFMT9, PFMT10, PFMT11,
  419.     PFMT12, PFMT13, PFMT14, PFMT15
  420. };
  421.  
  422.  
  423. /*
  424.  * Handle [FORMAT] item.
  425.  *
  426.  */
  427. dodiform()
  428. {
  429.   extern char bootstop;
  430.   extern char bootend;
  431.   int dev, v, w, i, br;
  432.   int modesel;            /* flag for mode select */
  433.   long cnt, hdsiz;
  434.   char *s, *d, *wgetstr();
  435.   char buf[10], bs[512], sendata[32];
  436.   char pnam[128];
  437.   char *seldev = "ACSI unit 0", *id = "XXXXX";
  438.   char *seldv =  "IDE  unit 0";
  439.   HINFO hinfo;
  440.   char devnames[NAMSIZ];    /* device type name buffer */
  441.   long nbad;
  442.   extern long gbslsiz(), nument(), dsmarkbad();
  443.   long pattern, temp, cyl;
  444.   long longrandom();
  445.   char pr_id[10];    /* partition scheme id */
  446.   int mask = 0x0001;
  447.   int set, scsidrv, bsiz, other = 0;
  448.   int page=4, spt, ret;
  449.   int head=0, domark=YESMK;
  450.   
  451.   /*
  452.    * Throw up generic formatting/partition warning,
  453.    * then get physical dev they want to clobber.
  454.    */
  455.   yesscan = 0;
  456.   noinfo = 1;
  457.   for (i = 0; i < NAMSIZ; i++)
  458.       devnames[i] = "\0";
  459.   fwarning[FWARNCN].ob_state = NORMAL;
  460.   fwarning[FWARNOK].ob_state = NORMAL;
  461.   if (execform(fwarning) != FWARNOK) return BAILOUT;
  462.  
  463.   if ((dev = gphysdev()) < 0) {
  464.       return BAILOUT;
  465.   }
  466.   strcpy(id, "mn");
  467.   br = 0;
  468.  
  469.   /* display doing SCSI massage */
  470.  
  471.   inqfmt:
  472.   /* Get all available disk types from wincap 'mn' entries */  
  473.   wallents(devnames, id);
  474.   if (!*devnames)     {/* no informations */
  475.       goto stfm;
  476.   }
  477.   noinfo = 0;
  478.   /* Shove format name text into buttons */
  479.   for (i = 0, s = devnames; i < 14 && *s; ++i) {
  480.       dsknames[pfmt[i]].ob_type = G_BUTTON;    /* button */
  481.       dsknames[pfmt[i]].ob_spec = (long)s;
  482.       dsknames[pfmt[i]].ob_state = NORMAL;
  483.       dsknames[pfmt[i]].ob_flags = SELECTABLE | RBUTTON;
  484.       while (*s++)
  485.     ;
  486.   }
  487.   other = i;                            /* the other button */
  488.   dsknames[pfmt[i]].ob_type = G_BUTTON;    /* button */
  489.   dsknames[pfmt[i]].ob_spec = "OTHER";
  490.   dsknames[pfmt[i]].ob_state = NORMAL;
  491.   dsknames[pfmt[i]].ob_flags = SELECTABLE | RBUTTON;
  492.   i++;
  493.  
  494.   /* rest of buttons are invisible and untouchable */
  495.   for (; i < 16; ++i) {
  496.       dsknames[pfmt[i]].ob_type = G_IBOX;    /* invisible box */
  497.       dsknames[pfmt[i]].ob_spec = 0;        /* no thickness */
  498.       dsknames[pfmt[i]].ob_state = DISABLED;    /* nobody home */
  499.       dsknames[pfmt[i]].ob_flags = NONE;        /* disabled */
  500.   }
  501.   
  502.   /* clean up rest of the form and throw it up */
  503.   dsknames[PFOK].ob_state = NORMAL;
  504.   dsknames[PFCN].ob_state = NORMAL;
  505.   if (execform(dsknames) != PFOK)
  506.     return BAILOUT;
  507.   
  508.   /* search for format they picked */
  509.   for (i = 0; i < 18; ++i)
  510.     if (dsknames[pfmt[i]].ob_state & SELECTED)
  511.       break;
  512.   if (i >= 18) {        /* nothing picked */
  513.       return BAILOUT;
  514.   } else if (other == i)    {  /* the OTHER button was selected */
  515.         noinfo = 1;
  516.       goto stfm;
  517.   }
  518.   
  519.     if ((!br) && (dev < 8))        {
  520.           if (wgetent(dsknames[pfmt[i]].ob_spec, "mn") == ERROR)    {
  521.               strcpy(id, "mn");
  522.             noinfo = 1;
  523.             goto stfm;
  524.             /*
  525.             nofmt[NOSCHFMT].ob_spec = dsknames[pfmt[i]].ob_spec;
  526.             nofmt[NOSCHFMT].ob_state = NORMAL;
  527.             execform(nofmt, 0);
  528.             return ERROR;
  529.             */
  530.         }
  531.         if ((s = wgetstr("br")) != NULL)    {
  532.             strcpy(id, s);
  533.             br = 1;            /* processing the branch */
  534.             goto inqfmt;    /* start over */
  535.         }
  536.     }
  537.  
  538. stfm:
  539.     modesel = 1;
  540.   if(gfparm(dev, &noinfo, &modesel, &hinfo, dsknames[pfmt[i]].ob_spec,id)!= 0) {
  541.       return ERROR;
  542.   }
  543.   
  544.   /* get data pattern to test the disk */
  545.   if (wgetnum("dp", &pattern) != OK) {
  546.       pattern = longrandom();  /* can't find pattern from wincap, make one */
  547.   } else {
  548.       temp = pattern;
  549.       pattern <<= 16;    /* shift pattern to hi word */
  550.       pattern |= temp;
  551.   }
  552.  
  553.   if (dev > 15)    { /* IDE-AT drive */
  554.       br = dev - 16;
  555.   } else {            /* it is a scsi or acsi drive */
  556.       br = (dev > 7) ? (dev-8) : (dev);    /* minus 8 for the scsi drive number */
  557.   }
  558.  
  559.   /* asking the user do the marking bad or not */
  560.   mkornot[YESMK].ob_state = NORMAL;
  561.   mkornot[NOTMK].ob_state = NORMAL;
  562.   domark = execform(mkornot);
  563.  
  564.   /*
  565.    * One last chance to bail out.
  566.    */
  567.   *seldev = 'A';
  568.   if (dev > 15)    { /* it is a IDE-AT drive */
  569.       seldev = seldv;
  570.   } else if (dev > 7)    { /* it is a SCSI drive */
  571.           *seldev = 'S';
  572.   }
  573.   *(seldev + 10) = br + '0';
  574.   (fmtfnl[FUNIT].ob_spec)->te_ptext = seldev;
  575.   fmtfnl[FMTYES].ob_state = NORMAL;
  576.   fmtfnl[FMTNO].ob_state = NORMAL;
  577.   if (execform(fmtfnl) != FMTYES) return BAILOUT;
  578.  
  579.   /* For REAL !! */  
  580.   dsplymsg(fmtmsg);
  581.  
  582.   bsl = 0L;
  583.   
  584.   if ((dev > 15) && (!(athead*atcyl*atspt)))    {
  585.       formaterr(dev);
  586.     ret = ERROR;
  587.     goto formend;
  588.   }
  589.   /* Get size of Bad Sector List */
  590.   if ((bslsiz = gbslsiz(dev)) > 0L) {
  591.       /* Allocate memory for existing BSL */
  592.       if ((bsl = (BYTE *)mymalloc((int)bslsiz*512)) <= 0) {
  593.           ret = err(nomemory);
  594.           goto formend;
  595.       }
  596.       
  597.       /* Read in BSL */
  598.       if ((ret = rdbsl(dev)) != OK) {
  599.           /* Create a new BSL if current one is unusable */
  600.           if (creabsl(dev, NEW, 0L) != OK) {
  601.               ret = ERROR;
  602.               goto formend;
  603.           }
  604.       } else {
  605.             /* Remove USER BSL */
  606.             if (creabsl(dev, EXPAND, nument(VENDOR)) != OK) {
  607.                 ret = ERROR;
  608.                 goto formend;
  609.             }
  610.       }
  611.   } else if (bslsiz == 0L || bslsiz == ERROR) {    /* no bsl or read error */
  612.       if (creabsl(dev, NEW, 0L) != OK) {
  613.           ret = ERROR;
  614.           goto formend;
  615.       }
  616.   } else {    /* bslsiz == MDMERR; medium changed error */
  617.       ret = ERROR;
  618.       goto formend;
  619.   }
  620.   
  621.   /*
  622.    * In supervisor mode
  623.    * set disk format parameters
  624.    * and format the disk.
  625.    */
  626.   ostack = Super(NULL);
  627.   delay();
  628.   if (dev > 15)        { /* do the IDE-AT format */
  629.      if ((ret = fmtunt(dev)) != OK)    {
  630.       delay();
  631.         Super(ostack);
  632.       ret = errcode(dev);
  633.       if (tsterr(ret) != OK)
  634.           formaterr(dev);
  635.       ret = ERROR;
  636.     } else {
  637.         if (dev == 16)    {/* it is a master IDE-AT */
  638.             hdsiz = athead*atcyl*atspt; 
  639.         } 
  640.           disksiz = hdsiz;
  641.         delay();
  642.           Super(ostack);
  643.     }
  644.     goto formend;
  645.   } 
  646.   set = typedev & (mask << dev);
  647.   scsidrv = typedrv & (mask << dev);
  648.   bsiz = ((set) || (scsidrv)) ? (16) : (22);
  649.   if (!noinfo)    {            /* there are info in the wincap */
  650.     if ((set) || (scsidrv))    {
  651.           v = mdsense(dev, 4, 0, 32, sendata);
  652.           delay();                    /* kludge delay */
  653.           sqms(dev, sendata);
  654.     } else {
  655.           if (modesel) {
  656.               v = ms(dev, &hinfo);    /* Yes, do noprmal mode set */
  657.         }
  658.     }
  659.       /* Find formatted capacity of drive */
  660.       hdsiz = (long)hinfo.hi_cc * (long)hinfo.hi_dhc * (long)hinfo.hi_spt;
  661.   }    else if (dev < 8)    {        /* No, do special mode set */
  662.     for (i = 0; i < 32; i++)
  663.         sendata[i] = 0;
  664.     if ((set) || (scsidrv))    {
  665.           if (mdsense(dev, 0, 0, bsiz, sendata) == OK)        {
  666.             if (hdsiz = get3bytes(sendata+5))    {
  667.                   delay();                    /* kludge delay */
  668.                 sqms(dev, sendata);
  669.                 v = OK;
  670.                 goto kkk;
  671.             }
  672.         }
  673.   redopg:
  674.         for (i = 0; i < 32; i++)
  675.             sendata[i] = 0;
  676.           v = mdsense(dev, page, 0, 32, sendata);
  677.           for (i = 0; i < 32; i++) /* the lenght of sendata */
  678.               if (sendata[i])
  679.                 break;
  680.           if ((i == 32) && (page == 4))    { /* no informations returned */
  681.             page = 3;
  682.             goto redopg;
  683.           } else if (i == 32)    {
  684.             ret = 111;
  685.               delay();                    /* kludge delay */
  686.               Super(ostack);
  687.             goto formend;
  688.         }
  689.         if (page == 4)    {
  690.             if (!(hdsiz = get3bytes(sendata+5)))    {
  691.                 page = 3;
  692.                 /*
  693.                 cyl = get3bytes(sendata+14);
  694.                 head = *(sendata+17);
  695.                 if ((!cyl) || (!head))    {
  696.                     ret = 111;
  697.                       delay();        
  698.                       Super(ostack);
  699.                     goto formend;
  700.                 }
  701.                 */
  702.                 sqms(dev, sendata);
  703.                 goto redopg;
  704.             }
  705.             sqms(dev, sendata);
  706.             goto kkk;
  707.         } 
  708.         if (!(hdsiz = get3bytes(sendata+5)))    {
  709.             /*
  710.             spt = getword(sendata+22);
  711.             hdsiz = cyl*head*spt;
  712.             */
  713.             if (!hdsiz)        {
  714.                 ret = 111;
  715.                   delay();                    /* kludge delay */
  716.                   Super(ostack);
  717.                 goto formend;
  718.             }
  719.         }
  720.         goto kkk;
  721.     } else {    /* it is the acsi drivers */
  722.           hdsiz = (long)hinfo.hi_cc * (long)hinfo.hi_dhc * (long)hinfo.hi_spt;
  723.           delay();                    /* kludge delay */
  724.           v = ms(dev, &hinfo);    /* Yes, do noprmal mode set */
  725.     }
  726.   }    else {
  727.         if ((v = readcap(dev, 0, (long)0, buf)) == OK)    {
  728.             if ((hdsiz = get4bytes(buf)))    {
  729.                 hdsiz += 1;
  730.                 ret = OK;
  731.                 goto kkk;
  732.             } 
  733.         } 
  734.           delay();                    /* kludge delay */
  735.         for (i = 0; i < 32; i++)
  736.             sendata[i] = 0;
  737.           if ((v=mdsense(dev, 0, 0, bsiz, sendata)) == OK)        {
  738.             if (hdsiz = get3bytes(sendata+5))    {
  739.                 ret = OK;
  740.                 goto kkk;
  741.             }
  742.         }
  743.         for (i = 0; i < 32; i++)
  744.             sendata[i] = 0;
  745.           delay();                    /* kludge delay */
  746.           if ((v=mdsense(dev, 4, 0, 32, sendata)) == OK)        {
  747.             if (hdsiz = get3bytes(sendata+5))    {
  748.                 ret = OK;
  749.                 goto kkk;
  750.             }
  751.         }
  752.         for (i = 0; i < 32; i++)
  753.             sendata[i] = 0;
  754.           delay();                    /* kludge delay */
  755.           if ((v=mdsense(dev, 3, 0, 32, sendata)) == OK)        {
  756.             if (hdsiz = get3bytes(sendata+5))    {
  757.                 ret = OK;
  758.                 goto kkk;
  759.             }
  760.         }
  761.         ret = 111;
  762.           delay();                    /* kludge delay */
  763.           Super(ostack);
  764.         goto formend;
  765.   }
  766. kkk:
  767.   disksiz = hdsiz;
  768.   delay();                    /* kludge delay */
  769.   if (v == OK)    {
  770.       v = format(dev, (UWORD)hinfo.hi_in);  /* format */
  771.   }
  772. lll:
  773.   delay();                    /* kludge delay */
  774.   Super(ostack);
  775.   
  776.   if (v != 0)  {
  777.       ret = errcode(dev);
  778.       if (tsterr(ret) != OK)
  779.           formaterr(dev);
  780.       ret = ERROR;
  781.       goto formend;
  782.   }
  783.   
  784.   ret = OK;
  785.   rebootp = 1;
  786. formend:
  787.   erasemsg();    /* Erase formatting box */
  788.   if (ret == 111)        /* HDX may not support this drive */
  789.           ret = err(needinfo);
  790.   if (ret < 0) {
  791.       if (bsl > 0) free(bsl);
  792.       return ERROR;
  793.   }
  794.   
  795.   /*------------------------------------------*
  796.    * Markbad the device destructively.          *
  797.    * Bad Sectors found are added to the BSL.  *
  798.    * Write BSL to device.              *
  799.    *------------------------------------------*/
  800.   if (domark == YESMK)    { /* need to do the markbad */
  801.       if ((nbad = dsmarkbad(dev, hdsiz, 1, pattern)) < 0) {
  802.           free(bsl);
  803.           return ERROR;
  804.       }
  805.   }
  806.   if (wrbsl(dev) != OK) {
  807.       free(bsl);
  808.       return ERROR;
  809.   }
  810.   free(bsl);
  811.  
  812.     
  813.   /*
  814.    * Install boot-stopper in sector image;
  815.    * write root sector to device.
  816.    * 6-13-88  Setting of soft format parameters in root sector sets
  817.    *        the hard disk size only.
  818.    */
  819.   fillbuf(bs, 512L, 0L);    /* create new root sector */
  820.   sbslparm(bs);            /* set BSL parameters */
  821.   if (modesel)    {
  822.       sfmtparm(bs, &hinfo);
  823.   } else {
  824.       sdisksiz(bs, disksiz);
  825.   }
  826.   for (d = bs, s = &bootstop, cnt = (long)(&bootend - &bootstop); --cnt;)
  827.     *d++ = *s++;
  828.   Protobt(bs, -1L, -1, 1);    /* make root sector executable */
  829.   
  830.   if ((ret = putroot(dev, bs, (SECTOR)0)) != OK) {
  831.       if (tsterr(ret) != OK)
  832.           err(rootwrit);
  833.       return ERROR;
  834.   }
  835.  
  836.   /*
  837.    * Make a copy of the default partition name.
  838.    * Figure out the partition scheme id.
  839.    */
  840.   if (!noinfo)    {
  841.       s = wgetstr("pt");
  842.       strcpy(pnam, s);
  843.   }
  844.   /* ??
  845.   figprid(disksiz, pr_id);
  846.   */
  847.   dodipart(dev, pnam, disksiz);
  848.   return OK;
  849. }
  850.  
  851.  
  852.  
  853. /*
  854.  * Handle [PARTITION] item;
  855.  * if `xdev' is -1, throw up dialog boxes;
  856.  * if `xdev' >= 0, just partition the dev,
  857.  * using `pnam' as the partition type, 
  858.  * and `pr_id' to search for the type.
  859.  *
  860.  */
  861. dodipart(xdev, pnam, hsize)
  862. int xdev;
  863. char *pnam;
  864. long hsize;
  865. {
  866.     int dev, i, ret =OK, fine;
  867.     int choice;
  868.     char *seldev = "ACSI unit 0";
  869.       char *seldv =  "IDE  unit 0";
  870.     char *s;
  871.     char bs[512];
  872.     PART *pinfo;
  873.     int tem1, tem2;
  874.     long disksiz;
  875.     int mask = 0x0001;
  876.  
  877.     if (xdev < 0) {
  878.     /*
  879.      * Throw up warning saying that partition is dangerous;
  880.      * then get physical dev they want to clobber.
  881.      */
  882.     pwarning[PWARNCN].ob_state = NORMAL;
  883.     pwarning[PWARNOK].ob_state = NORMAL;
  884.     if (execform(pwarning) != PWARNOK) return BAILOUT;
  885.     tformat = FALSE;
  886.     if ((dev = gphysdev()) < 0) {
  887.         return BAILOUT;
  888.     }
  889.     /*
  890.      * Let the user edit/pick partitions.
  891.      */
  892.     fine = 0;
  893.     while (!fine) {
  894.         if (sfigpart(bs, dev, (PART *)&pinfo) != OK)    {
  895.             if (pinfo > 0)    Mfree(pinfo);
  896.             return BAILOUT;
  897.         }
  898.         if ((ret = chkpart(dev, pinfo)) != OK) {
  899.             if (ret < 0)    {    /* size too big */
  900.                 err(nexsmem);
  901.             } else {    /* some other errors  */
  902.                 if (pinfo > 0)    Mfree(pinfo);
  903.                 return BAILOUT;
  904.             }
  905.         } else {
  906.             fine = 1;
  907.         }
  908.     }
  909.  
  910.       fine = dev;            /* default for the acsi unit */
  911.     *seldev = 'A';
  912.       if (dev > 15)    { /* it is a IDE-AT drive */
  913.         fine = dev - 16;
  914.         seldev = seldv;
  915.     } else if (dev > 7)     {    /* minus 8 for the scsi drive number */
  916.         fine = dev - 8;
  917.         *seldev = 'S';
  918.     }
  919.     *(seldev + 10) = fine + '0';
  920.  
  921.     /* Last chance to bail out */
  922.     (partfnl[PUNIT].ob_spec)->te_ptext = seldev;
  923.     partfnl[PARTYES].ob_state = NORMAL;
  924.     partfnl[PARTNO].ob_state = NORMAL;
  925.     if (execform(partfnl) != PARTYES)    {
  926.         if (pinfo > 0)    Mfree(pinfo);
  927.         return BAILOUT;
  928.     }
  929.  
  930.     } else {
  931.         /* ??
  932.         if ((!noinfo) && (!ttscsi) && (wgetent(pnam, pr_id) != OK)) {
  933.             nopart[NOSCHPOK].ob_state = NORMAL;
  934.             (nopart[NOSCHPR].ob_spec)->te_ptext = pnam;
  935.             execform(nopart);
  936.             return ERROR;
  937.         }
  938.         */
  939.         npart = 4;
  940.         ext = NO_EXT;    /* set the extended partition flag to not exists */
  941.         dev = xdev;
  942.         if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)    {
  943.             err(nomemory);
  944.             if (pinfo > 0)    Mfree(pinfo);
  945.             return ERROR;
  946.         }
  947.         inipart(pinfo, npart);
  948.         npart = 0;
  949.         setpart(pinfo, pnam, hsize);
  950.         /* ??
  951.         if (ttscsi)        {     SCSI bus drive 
  952.             setpart(pinfo, hsize);
  953.         } else {             regular drvie 
  954.             for (i = 0; i < 4; ++i)
  955.                 fillpart(i, &pinfo[i]);
  956.         }
  957.         */
  958.     }
  959.  
  960.     /* For REAL!! */
  961.     dsplymsg(partmsg);
  962.     
  963.     bsl = 0L;
  964.     
  965.     /* Get size of BSL */
  966.     if ((bslsiz = gbslsiz(dev)) > 0L) {
  967.         /* Allocate memory for existing BSL */
  968.         if ((bsl = (BYTE *)mymalloc((int)bslsiz*512)) <= 0) {
  969.             ret = err(nomemory);
  970.             goto partend;
  971.         }
  972.             
  973.         /* Read in BSL */
  974.         if ((ret = rdbsl(dev)) != OK) {
  975.             if (ret == INVALID)
  976.                 err(cruptbsl);
  977.             ret = ERROR;
  978.             goto partend;
  979.         }
  980.     } else if (bslsiz == 0) {
  981.         ret = err(oldfmt);
  982.         goto partend;
  983.     } else if (bslsiz == ERROR) {
  984.         ret = err(rootread);
  985.         goto partend;
  986.     } else {
  987.         ret = ERROR;
  988.         goto partend;
  989.     }
  990.  
  991.     
  992.     /* Lay out partition headers */
  993.     if (spheader(dev, &pinfo[0]) != OK) {
  994.         ret = ERROR;
  995.         goto partend;
  996.     }
  997.     
  998.     if (wrbsl(dev) != OK) {        /* write BSL */
  999.         ret = ERROR;
  1000.         goto partend;
  1001.     }
  1002.  
  1003.     /* check and change the structure's id after 'spheader()' */
  1004.     changeid(pinfo);
  1005.  
  1006.     /* Shove partition parms into root sector */
  1007.     if ((ret = getroot(dev, bs, (SECTOR)0)) != 0)    {
  1008.         if (tsterr(ret) != OK)
  1009.             err(rootread);
  1010.         ret = ERROR;
  1011.         goto partend;
  1012.     }
  1013.  
  1014.     if ((ret = stlayroot(bs, dev, pinfo)) != OK)    {
  1015.         goto partend;
  1016.     }
  1017.     tem1 = npart;            /* save the number of partitions */
  1018.     tem2 = ext;                /* save the index of extended partition */
  1019.     if (rescan(1,2)) {        /* has to be here because map changed    */
  1020.         ret = ERROR;        /* after partitions are moved around,    */
  1021.         goto partend;        /* report medium change error.        */
  1022.     }
  1023.     npart = tem1;
  1024.     ext = tem2;
  1025.     /* Partition the device with parameters given in pinfo */
  1026.     if (stlaybs(dev, &pinfo[0]) != OK)
  1027.         ret = ERROR;
  1028.     else
  1029.         ret = OK;
  1030.         
  1031.     rebootp = 1;
  1032.     /*  add on Jul 2, 90 for removable drive
  1033.     if ((typedev & (mask << dev)))             it is a removable drive 
  1034.         if (npart <= prevnpart)                 if less or equal than prevous 
  1035.             rebootp = 0;                      partition, don't reboot 
  1036.     change and add over on Jul 2, 90 for the removable drive on Oct 1, 90
  1037.     if ((typedev & (mask << dev)))    {         it is a removable drive 
  1038.         for (i = 0; i < 10; i++)     {
  1039.             if (!mediach(dev))            
  1040.                 break;
  1041.             if (i == 10)
  1042.                 rebootp = 1;
  1043.             else
  1044.                 rebootp = 0;
  1045.         }
  1046.     }
  1047.     */
  1048.     pnf = 1;        /* set the flag to just doing the partition */
  1049. partend:
  1050.     if (bsl > 0) free(bsl);
  1051.     inipart(pinfo, npart);
  1052.     if (pinfo > 0)    Mfree(pinfo);
  1053.     erasemsg();
  1054.     return (ret);
  1055. }
  1056.  
  1057.  
  1058. /*
  1059.  * get root sector informations and write them into that sector 
  1060.  */
  1061.  
  1062. stlayroot(bs, dev, part)
  1063. char *bs;
  1064. int dev;
  1065. PART *part;
  1066. {
  1067.     int i;
  1068.     UWORD sum = 0x1234;
  1069.     long cnt, disksiz, prvst;
  1070.     char *d, *s;
  1071.     extern char bootstop;
  1072.     extern char bootend;
  1073.  
  1074.     /* do the prime partition */
  1075.     spart(bs, part, 0, &prvst);    /* set ST partition parameters */
  1076.     /*
  1077.       sfmtparm(bs, &hinfo);
  1078.       for (d = bs, s = &bootstop, cnt = (long)(&bootend - &bootstop); --cnt;)
  1079.         *d++ = *s++;
  1080.     */
  1081.     sbslparm(bs);                /* set bsl parameters */
  1082.     Protobt(bs, -1L, -1, 1);        /* make root sector executable */
  1083.     if ((ret = putroot(dev, bs, (SECTOR)0)) != OK) {
  1084.         if (tsterr(ret) != OK)
  1085.             err(rootwrit);
  1086.         return(ERROR);
  1087.     }
  1088.     if (ext == NO_EXT)    return OK;        /* no extended partition */
  1089.     /* do the extended partitions */
  1090.     extsiz = part[ext].p_siz;
  1091.     for (i = 4; i < npart; i++)    {
  1092.         if (!(part[i].p_flg & P_EXISTS))    {     /* skip if not exists */
  1093.             return OK;
  1094.         }
  1095.         spart(bs, part, i, &prvst);    /* set IBM partition parameters */
  1096.         if ((ret = putroot(dev, bs, part[i].p_st)) != OK) {
  1097.             if (tsterr(ret) != OK)
  1098.                 err(rootwrit);
  1099.             return(ERROR);
  1100.         }
  1101.     }
  1102.     return OK;
  1103. }
  1104.  
  1105.  
  1106.  
  1107.  
  1108. /*
  1109.  * Put information into the root structure
  1110.  */
  1111.  
  1112. spart(image, pinfo, pnm, prvst)
  1113.  
  1114. char *image;            /* root sector buffer */
  1115. register PART *pinfo;    /* partition information */
  1116. int pnm;                /* partition number */
  1117. long *prvst;            /* The previous partition start sector */
  1118.  
  1119. {
  1120.     PART *rpart;
  1121.     long numcyl;
  1122.     int i, j;
  1123.  
  1124.     if (pnm)     {
  1125.         fillbuf(image, 512L, 0L);
  1126.     }
  1127.     rpart = &((RSECT *)(image + 0x200 - sizeof(RSECT)))->hd_p[0];
  1128.     if (pnm < 4)    {
  1129.         for (i = 0; i < NPARTS; i++, rpart++)    {
  1130.             if (pinfo->p_flg & P_EXISTS)    {
  1131.                 rpart->p_flg = P_EXISTS;
  1132.                 for (j = 0; j < 3; j++)
  1133.                     rpart->p_id[j] = pinfo->p_id[j];
  1134.                 rpart->p_st = pinfo->p_st;
  1135.                 rpart->p_siz = pinfo->p_siz;
  1136.             } else {
  1137.                 rpart->p_flg = 0;
  1138.                 for (j = 0; j < 3; j++)
  1139.                     rpart->p_id[j] = 0;
  1140.                 rpart->p_st = 0L;
  1141.                 rpart->p_siz = 0L;
  1142.             }
  1143.             pinfo++;
  1144.         }
  1145.  
  1146.     } else {    /* pnm => 4 */
  1147.         rpart->p_flg = pinfo[pnm].p_flg;
  1148.         for (j = 0; j < 3; j++)
  1149.             rpart->p_id[j] = pinfo[pnm].p_id[j];
  1150.         rpart->p_st = ROOTSECT;
  1151.         rpart->p_siz = pinfo[pnm].p_siz - ROOTSECT;
  1152.         rpart++;
  1153.         if (((pnm + 1) != npart) && (pinfo[pnm+1].p_flg & P_EXISTS)) { 
  1154.             /* need extened partition */
  1155.             rpart->p_flg = P_EXISTS;
  1156.             rpart->p_id[0] = 'X';
  1157.             rpart->p_id[1] = 'G';
  1158.             rpart->p_id[2] = 'M';
  1159.             rpart->p_siz = pinfo[pnm+1].p_siz;
  1160.             rpart->p_st = (pnm == 4) ? (pinfo[4].p_siz) :
  1161.                                     (pinfo[pnm].p_siz + *prvst);
  1162.             *prvst = rpart->p_st;
  1163.         }
  1164.  
  1165.     }
  1166. }
  1167.  
  1168.  
  1169.  
  1170. /*
  1171.  * Setup partitions on the disk;
  1172.  * write boot sectors and zero FATs and root directories.
  1173.  *
  1174.  */
  1175. stlaybs(physdev, pinfo)
  1176. int physdev;
  1177. register PART *pinfo;
  1178. {
  1179.     int i, ldev, ret;
  1180.     int kindfat;
  1181.     SECTOR data, nsect;
  1182.     char *devno="X";
  1183.     long ndirs;
  1184.     UWORD fatsiz;
  1185.     BOOT *bs;
  1186.     long serialno;
  1187.     extern long longrandom();
  1188.     extern long cell();
  1189.     char *buf;
  1190.     long size;
  1191.  
  1192.     if ((bslsiz = gbslsiz(physdev)) < 0L) {
  1193.         if (bslsiz == ERROR)
  1194.             err(rootread);
  1195.         return ERROR;
  1196.     }
  1197.     /* SCAN_BS: pinfo is for scan() and laybs() use */
  1198.     if (ext != NO_EXT)    sortpart(pinfo, SCAN_BS);    
  1199.  
  1200.     for (i = 0; i < npart; ++i, ++pinfo) {
  1201.         
  1202.         /* don't care if partition does not exist */
  1203.         if (!(pinfo->p_flg & P_EXISTS)) {
  1204.             return OK;
  1205.         }
  1206.  
  1207.  
  1208.     /*
  1209.      * Compute boot sector parameters.
  1210.      */
  1211.         if (pinfo->p_siz > disksiz) {        /* partition >? disk size */
  1212.             *devno = i + '0';
  1213.             (part2big[BGPART].ob_spec)->te_ptext = devno;
  1214.             part2big[BGPARTOK].ob_state = NORMAL;
  1215.             execform(part2big);
  1216.             return ERROR;
  1217.         }
  1218.  
  1219.     /* estimat the bps */
  1220.     /* MAXSECT = 16MB - 8 */
  1221.     bps = cell((pinfo->p_siz-7)*BPS, (long)MAXSECT);
  1222.  
  1223.     /* the real bps */
  1224.     bps = BPS * n2power((UWORD)cell(bps, (long)BPS));
  1225.     ratio = bps / BPS;
  1226.     nsect = pinfo->p_siz / ratio;
  1227.  
  1228.     size = (long)BPS * ratio;
  1229.     if ((buf = (char *)Malloc(size)) <= 0)    {
  1230.         err(nomemory);
  1231.         if (buf > 0) Mfree((long)buf);
  1232.         return ERROR;
  1233.     }
  1234.  
  1235.     /*
  1236.      * Install entries in boot sector image;
  1237.      * force sector checksum to zero (non-executable);
  1238.      * write boot sector to media.
  1239.      *
  1240.       *    512 bytes/sector
  1241.      *    2 or 4 sectors/cluster (partition > 16Mb has 4 spc)
  1242.      *    1 reserved sector (for boot)
  1243.      *    2 FATs
  1244.      *    ... dir slots
  1245.      *    ... # sectors
  1246.      *    F8 means media is a hard disk
  1247.      *    ... FAT size
  1248.      *
  1249.      */
  1250.      
  1251.     /* Make a clean boot sector */
  1252.     fillbuf(buf, bps, 0L);
  1253.     bs = (BOOT *)buf;
  1254.         
  1255.  
  1256.     /* bytes per sector */
  1257.     iw((UWORD *)&bs->b_bps[0], (UWORD)bps);
  1258.     
  1259.     /* sectors per cluster */
  1260.     bs->b_spc = SPC;
  1261.         
  1262.     /* number of reserved sectors */
  1263.     iw((UWORD *)&bs->b_res[0], (UWORD)1);
  1264.     
  1265.     /* number of FATs */
  1266.     bs->b_nfats = 2;
  1267.     
  1268.  
  1269.     /*
  1270.      * Compute root directory size
  1271.      * 256 entries, plus fudge on devs > 10Mb
  1272.      */
  1273.     if (pinfo->p_siz < 0x5000L) ndirs = NUMEN;
  1274.     else ndirs = nsect / 80;    /* 1 dir entry per 80 sectors */
  1275.     /* round to nearest sector */
  1276.     ndirs = (ndirs + ((UWORD)bps/BPDIR - 1)) & ~((UWORD)bps/BPDIR - 1);    
  1277.     iw((UWORD *)&bs->b_ndirs[0], (UWORD)ndirs);
  1278.     
  1279.     /* number of sectors on media (partition) */
  1280.     iw((UWORD *)&bs->b_nsects[0], (UWORD)nsect);
  1281.  
  1282.     /* media descriptor */
  1283.     bs->b_media = 0xf8;
  1284.  
  1285.     /*--------------------------------------------------------------*
  1286.      * Compute FAT size                        *
  1287.      *                                *
  1288.      * Num entries to map the entire partition            *
  1289.      *    = partition's size in clusters                *
  1290.      *    = partition's size in sectors / spc            *
  1291.      *                                *
  1292.      * Num entries in FAT                        *
  1293.      *    = Num entries to map partition + reserved entries    *
  1294.      *    = (partition's size in sectors / spc) + 2        *
  1295.      *                                *
  1296.      * Num sectors FAT occupies                    *
  1297.      *    = Num entries in FAT / Num entries of FAT per sector    *
  1298.      *    = Num entries in FAT / (512 / 2)    <16-bit FAT>    *
  1299.      *    = ((partition's size in sectors / spc) + 2) / 256 + 1    *
  1300.      *                        <+1 to round up>    *
  1301.      *--------------------------------------------------------------*/
  1302.     fatsiz = ((((nsect / bs->b_spc) + 2) * 2) / bps) + 1;
  1303.     iw((UWORD *)&bs->b_spf[0], (UWORD)fatsiz);
  1304.  
  1305.     /* write the serial number to the bs */ 
  1306.     Protobt(bs, 0x01000000, -1, -1);
  1307.  
  1308.     /*
  1309.      * Write partition's boot sector
  1310.      */
  1311.     forcesum((UWORD *)buf, (UWORD)0);    /* force image checksum */
  1312.     if ((ret = wrsects(physdev,(UWORD)ratio,buf,(SECTOR)pinfo->p_st))!= OK) {
  1313.         if (tsterr(ret) != OK)
  1314.             err(bootwrit);
  1315.         return ERROR;
  1316.     }
  1317.  
  1318.     /*
  1319.      * Zero the partition
  1320.      */
  1321.     if ((ret = zerosect(physdev, (SECTOR)(pinfo->p_st+ratio),
  1322.              ((UWORD)((fatsiz*2 + ndirs*BPDIR/bps) * ratio)))) != OK) {
  1323.         if (tsterr(ret) != OK)
  1324.             err(hdrwrite);
  1325.         return ERROR;
  1326.     }
  1327.              
  1328.     /*
  1329.      * Make first 2 entries in FATs more IBM-like.
  1330.      */
  1331.     if ((ret = rdsects(physdev,(UWORD)ratio,buf,
  1332.                         (SECTOR)(pinfo->p_st+ratio)))!= 0){
  1333.         if (tsterr(ret) != OK)
  1334.             err(fatread);
  1335.         return ERROR;
  1336.     }
  1337.     *(UWORD *)&buf[0] = 0xf8ff;
  1338.     *(UWORD *)&buf[2] = 0xffff;
  1339.     if ((ret = wrsects(physdev,(UWORD)ratio,
  1340.                         buf,(SECTOR)(pinfo->p_st+ratio)))!= 0 ||
  1341.         (ret = wrsects(physdev,(UWORD)ratio,buf,
  1342.                         (SECTOR)(pinfo->p_st+ratio+fatsiz*ratio)))
  1343.         != 0) {
  1344.         if (tsterr(ret) != OK)
  1345.             err(fatwrite);
  1346.         return ERROR;
  1347.     }
  1348.  
  1349.     /*
  1350.      * Mark bad sectors recorded in the BSL into the FATs.
  1351.      * Calculating parameters:
  1352.      *    ldev - from physdev and i.
  1353.      *    fat0 - always equals 1.
  1354.      *    fatsiz - calculated above.
  1355.      *    data - starts after the boot sector, 2 FATs and rootdir.
  1356.      */
  1357.  
  1358.         if (bslsiz > 0) {
  1359.             if ((ldev = phys2log(physdev, i)) == ERROR)
  1360.                 return parterr(physdev);
  1361.             data = (SECTOR)1 + (SECTOR)(fatsiz*2) + (SECTOR)(ndirs*BPDIR/bps);
  1362.             bsl2fat(ldev, (SECTOR)ratio, (UWORD)(fatsiz*ratio), 
  1363.                                                 data*ratio, MEDIA);
  1364.         }
  1365.         if (buf > 0) Mfree((long)buf);
  1366.     }
  1367.     return OK;
  1368. }
  1369.  
  1370.  
  1371.  
  1372.  
  1373. /*
  1374.  * Handle [ZERO] item.
  1375.  *
  1376.  */
  1377. dodizero()
  1378. {
  1379.     int ldev, ret;
  1380.     char *seldev = "X";
  1381.     int i; 
  1382.  
  1383.     zwarning[ZWOK].ob_state = NORMAL;
  1384.     zwarning[ZWCN].ob_state = NORMAL;
  1385.     if (execform(zwarning) != ZWOK)
  1386.     return BAILOUT;
  1387.     if (showmany)    err(manyldev);
  1388.  
  1389.     if ((ldev = glogdev()) < 0) return BAILOUT;
  1390.  
  1391.     /* Find out if logical device has assumed parameters */
  1392.     if (chkparm(ldev) != OK) {
  1393.         wronparm[WRONOK].ob_state = NORMAL;
  1394.     execform(wronparm);
  1395.     return ERROR;
  1396.     }
  1397.         
  1398.     *seldev = ldev;
  1399.     (zerofnl[ZDRV].ob_spec)->te_ptext = seldev;
  1400.     strcat((zerofnl[ZDRV].ob_spec)->te_ptext, ":");
  1401.     zerofnl[ZYES].ob_state = NORMAL;
  1402.     zerofnl[ZNO].ob_state = NORMAL;
  1403.     if (execform(zerofnl) != ZYES)  return BAILOUT;
  1404.  
  1405.     dsplymsg(zeromsg);
  1406.     if (zero(ldev) == OK) {
  1407.     if (!rebootp) {
  1408.         for (i = 0; i < 10; i++) {
  1409.         if (!mediach(ldev-'A')) break;
  1410.         }
  1411.         if (i == 10) {
  1412.             rebootp = 1;
  1413.         err(mdach);
  1414.             }
  1415.     }
  1416.     }
  1417.     erasemsg();
  1418. }
  1419.  
  1420.  
  1421. /*
  1422.  * Handle [MARKBAD] item.
  1423.  *
  1424.  */
  1425. dodimark()
  1426. {
  1427.     int ldev, ret;
  1428.     int i;
  1429.  
  1430.     mwarning[MWARNOK].ob_state = NORMAL;
  1431.     mwarning[MWARNCN].ob_state = NORMAL;
  1432.     if (execform(mwarning) == MWARNCN)
  1433.         return BAILOUT;
  1434.     if (showmany)    err(manyldev);
  1435.  
  1436.     if ((ldev = glogdev()) < 0)
  1437.         return BAILOUT;
  1438.         
  1439.     /* Find out if logical device has assumed parameters */
  1440.     if (chkparm(ldev) != OK) {
  1441.         wronparm[WRONOK].ob_state = NORMAL;
  1442.     execform(wronparm);
  1443.     return ERROR;
  1444.     }
  1445.          
  1446.     dsplymsg(lmrkmsg);
  1447.     if (markbad(ldev) != OK) {
  1448.         erasemsg();
  1449.     } else {
  1450.         if (!rebootp) {
  1451.         for (i = 0; i < 10; i++) {
  1452.         if (!mediach(ldev-'A')) break;
  1453.         }
  1454.         if (i == 10) {
  1455.             rebootp = 1;
  1456.         err(mdach);
  1457.             }
  1458.         }
  1459.     }
  1460. }
  1461.  
  1462.  
  1463. /*
  1464.  * Translate unit number to tree index.
  1465.  *
  1466.  */
  1467. static int physxlat[] = {
  1468.     UNIT0, UNIT1, UNIT2, UNIT3
  1469. };
  1470.  
  1471. static int physid[] = {
  1472.     DRVID0, DRVID1, DRVID2, DRVID3
  1473. };
  1474.  
  1475. #define ROLL1 1            /* move the bar one step */
  1476. #define ROLL4 4            /* move the bar four steps */
  1477.  
  1478. /*
  1479.  * Ship selected devices.
  1480.  */
  1481. dodiship()
  1482. {
  1483.   
  1484.     int xrun = 1;
  1485.     int index=0, i, ret;
  1486.  
  1487.     linkdev();            /* link all live devices into a list */
  1488.     /* set form for first display */
  1489.     physdial[PHYSOK].ob_state = NORMAL;
  1490.     physdial[PHYSCN].ob_state = NORMAL;
  1491.     physdial[SLBOX].ob_y = 0;
  1492.     if (ndevs <= 4)    {
  1493.         physdial[SLBOX].ob_height = physdial[SLTRK].ob_height;
  1494.     } else {
  1495.         physdial[SLBOX].ob_height = physdial[SLTRK].ob_height / (ndevs/4.0);
  1496.     }
  1497.     ok2draw = 0;
  1498.     drawdev(index);    /* draw the devices into the dialog box */
  1499.     ARROW_MOUSE;
  1500.     dsplymsg(physdial);
  1501.     ++ok2draw;
  1502.     while (xrun)     {
  1503.         switch (form_do(physdial, -1))     {
  1504.             case PHYSOK:xrun = 0;
  1505.                         break;
  1506.             case PHYSCN:xrun = 0;            /* return */
  1507.                         break;
  1508.             case SLTRK: if (ndevs > 5)    {
  1509.                             scrupdn(ROLL4, &index);
  1510.                         }
  1511.                         break;
  1512.             case SLUP:  if (index != 0)    {
  1513.                             scrupdn(ROLL1, &index);
  1514.                         }
  1515.                         break;
  1516.             case SLDN:  if ((index < 12) && (index+4 < ndevs))    {
  1517.                             scrupdn(ROLL1, &index);
  1518.                         }
  1519.                         break;
  1520.             case SLBOX: if (ndevs > 5)    {
  1521.                             slidebox(physdial, &index);
  1522.                         }
  1523.                         break;
  1524.           }
  1525.       }
  1526.  
  1527.   /*
  1528.    * Draw shrinking box and cleanup the screen;
  1529.    * return thing that caused our exit.
  1530.    */
  1531.     erasemsg();
  1532.  
  1533.     if (ret == PHYSCN)    {
  1534.         return BAILOUT;
  1535.     }
  1536.     /* search for the selected unit */
  1537.     for (i=0; i < 4; i++)    {
  1538.         if (physdial[physxlat[i]].ob_state & SELECTED)    {
  1539.               /* Throw up final shipping warning. */
  1540.               shipfnl[SFNLCN].ob_state = NORMAL;
  1541.               shipfnl[SFNLOK].ob_state = NORMAL;
  1542.               if (execform(shipfnl) != SFNLOK) return BAILOUT;
  1543.             ship(devid[index+i].dev);
  1544.               /* Put out final message about turning off hard disks */
  1545.               scommand[TRNOFFOK].ob_state = NORMAL;
  1546.               execform(scommand);
  1547.         }
  1548.     }
  1549.     return BAILOUT;
  1550. }
  1551.   
  1552.  
  1553. /*
  1554.  * Get physical device#,
  1555.  * return devno or -1.
  1556.  *
  1557.  */
  1558. gphysdev()
  1559.  
  1560. {
  1561.     int xrun = 1, tpdev=0;
  1562.     int index=0, i, ret;
  1563.  
  1564.     linkdev();            /* link all live devices into a list */
  1565.     if (tformat)    {    /* when format, enable all devices in dialog box */
  1566.         if (spscsixst)    {
  1567.             ndevs = 9;
  1568.             tpdev = 8;
  1569.         } else if (ttscsi) {
  1570.             ndevs = 16;
  1571.         } else if ((!ttscsi) && (!noacsi))    {/* Mega ST */
  1572.             ndevs = 8;
  1573.         } else {    /* notebook */    
  1574.             ndevs = 1;
  1575.         }
  1576.     }
  1577.     /* set form for first display */
  1578.     physdial[PHYSOK].ob_state = NORMAL;
  1579.     physdial[PHYSCN].ob_state = NORMAL;
  1580.     physdial[SLBOX].ob_y = 0;
  1581.     if (ndevs <= 4)    {
  1582.         physdial[SLBOX].ob_height = physdial[SLTRK].ob_height;
  1583.     } else {
  1584.         physdial[SLBOX].ob_height = physdial[SLTRK].ob_height / (ndevs/4.0);
  1585.     }
  1586.     for (i=0; i < 4; i++)    {
  1587.         physdial[physxlat[i]].ob_state = NORMAL;
  1588.         physdial[physid[i]].ob_state = NORMAL;
  1589.     }
  1590.     ok2draw = 0;
  1591.     drawdev(index);    /* draw the devices into the dialog box */
  1592.     ARROW_MOUSE;
  1593.     dsplymsg(physdial);
  1594.     ++ok2draw;
  1595.     while (xrun)     {
  1596.         switch (ret=form_do(physdial, -1))     {
  1597.             case PHYSOK:xrun = 0;
  1598.                         break;
  1599.             case PHYSCN:xrun = 0;            /* return */
  1600.                         break;
  1601.             case SLTRK: if (ndevs > 5)    {
  1602.                             scrupdn(ROLL4, &index);
  1603.                         }
  1604.                         break;
  1605.             case SLUP:  if (index != 0)    {
  1606.                             scrupdn(ROLL1, &index);
  1607.                         }
  1608.                         break;
  1609.             case SLDN:  if ((index < 12) && (index+4 < ndevs))    {
  1610.                             scrupdn(ROLL1, &index);
  1611.                         }
  1612.                         break;
  1613.             case SLBOX: if (ndevs > 5)    {
  1614.                             slidebox(physdial, &index);
  1615.                         }
  1616.                         break;
  1617.             case DRVID0:physdial[UNIT0].ob_state = SELECTED;
  1618.                        objc_draw(physdial,UNIT0, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1619.                         break;;
  1620.             case DRVID1:physdial[UNIT1].ob_state = SELECTED;
  1621.                        objc_draw(physdial,UNIT1, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1622.                         break;;
  1623.             case DRVID2:physdial[UNIT2].ob_state = SELECTED;
  1624.                        objc_draw(physdial,UNIT2, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1625.                         break;;
  1626.             case DRVID3:physdial[UNIT3].ob_state = SELECTED;
  1627.                        objc_draw(physdial,UNIT3, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1628.                         break;;
  1629.             case UNIT0:physdial[DRVID0].ob_state = SELECTED;
  1630.                        objc_draw(physdial,DRVID0, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1631.                         break;;
  1632.             case UNIT1:physdial[DRVID1].ob_state = SELECTED;
  1633.                        objc_draw(physdial,DRVID1, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1634.                         break;;
  1635.             case UNIT2:physdial[DRVID2].ob_state = SELECTED;
  1636.                        objc_draw(physdial,DRVID2, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1637.                         break;;
  1638.             case UNIT3:physdial[DRVID3].ob_state = SELECTED;
  1639.                        objc_draw(physdial,DRVID3, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1640.                         break;;
  1641.           }
  1642.       }
  1643.  
  1644.   /*
  1645.    * Draw shrinking box and cleanup the screen;
  1646.    * return thing that caused our exit.
  1647.    */
  1648.     erasemsg();
  1649.  
  1650.     if (ret == PHYSCN)    {
  1651.         return ERROR;
  1652.     }
  1653.     /* search for the selected unit */
  1654.     for (i=0; i < 4; i++)    {
  1655.         if (physdial[physxlat[i]].ob_state & SELECTED)    {
  1656.             if (tformat)    {
  1657.                 return(index+tpdev+i);
  1658.             } else {
  1659.                 return(devid[index+i].dev);
  1660.             }
  1661.         }
  1662.     }
  1663.     return ERROR;
  1664. }
  1665.  
  1666. /* draw the select devices dialog box for the format operation */
  1667.  
  1668. fdrawdev(index)
  1669. int index;
  1670. {
  1671.  
  1672.     int i, st=0;
  1673.  
  1674.     if (spscsixst)    {
  1675.         st = 8;
  1676.     }
  1677.     
  1678.     for (i=0; i < 4; i++)    {
  1679.         /*
  1680.         (physdial[physxlat[i]].ob_spec)->te_ptext = &drvid[36][0];
  1681.         (physdial[physid[i]].ob_spec)->te_ptext = &drvid[36][0];
  1682.         */
  1683.         if (i+index+st < 8)    {
  1684.               (physdial[physxlat[i]].ob_spec)->te_ptext = &drvid[19+i+index][0];
  1685.         } else if (i+index+st < 16)    {
  1686.         (physdial[physxlat[i]].ob_spec)->te_ptext = &drvid[27+i+index+st-8][0];
  1687.         } else {
  1688.             (physdial[physxlat[i]].ob_spec)->te_ptext = &drvid[35][0];
  1689.         }
  1690.         physdial[physxlat[i]].ob_state = NORMAL;
  1691.         physdial[physid[i]].ob_state = NORMAL;
  1692.         if (i+index+st == 16)    {    /* it is sparrow */
  1693.             (physdial[physid[i]].ob_spec)->te_ptext = &drvid[i+index+st][0];
  1694.         } else if (livedevs[i+index+st])    {
  1695.             if (idevs[i+index+st])    {
  1696.                 (physdial[physid[i]].ob_spec)->te_ptext = &drvid[i+index+st][0];
  1697.             } else {
  1698.                 (physdial[physid[i]].ob_spec)->te_ptext = &drvid[17][0];
  1699.             }
  1700.         } else {
  1701.             if (idevs[i+index+st])    {
  1702.                 (physdial[physid[i]].ob_spec)->te_ptext = &drvid[i+index+st][0];
  1703.             } else {
  1704.                 (physdial[physid[i]].ob_spec)->te_ptext = &drvid[18][0];
  1705.             }
  1706.             /*
  1707.             physdial[physid[i]].ob_state = NORMAL;
  1708.             */
  1709.         }
  1710.         if (ok2draw)    {
  1711.             /*
  1712.             objc_draw(physdial,physlat[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  1713.             */
  1714.             objc_draw(physdial,physxlat[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  1715.             objc_draw(physdial,physid[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  1716.         }
  1717.     }
  1718. }
  1719.     
  1720. /* draw the select devices dialog box for the partition operation */
  1721.  
  1722. drawdev(index)
  1723. int index;
  1724. {
  1725.  
  1726.     int i, j;
  1727.  
  1728.     if (tformat)    {
  1729.         fdrawdev(index);
  1730.         return OK;
  1731.     }
  1732.  
  1733.     for (i=0; i < 4; i++)    {
  1734.         (physdial[physxlat[i]].ob_spec)->te_ptext = &drvid[36][0];
  1735.         (physdial[physid[i]].ob_spec)->te_ptext = &drvid[36][0];
  1736.         if (devid[i+index].flg)    {
  1737.                physdial[physxlat[i]].ob_state = NORMAL;
  1738.                physdial[physid[i]].ob_state = NORMAL;
  1739.             /*
  1740.             if (devid[i+index].flg == 2)    {
  1741.                 physdial[physxlat[i]].ob_state = NORMAL;
  1742.             } else {
  1743.                 physdial[physxlat[i]].ob_state = NORMAL | OUTLINED;
  1744.             }
  1745.             */
  1746.             j = devid[i+index].dev;
  1747.             if (j < 8)    {
  1748.                 /*
  1749.                 drvid[19][10] = devid[i+index].dev + '0';
  1750.                 */
  1751.                 (physdial[physxlat[i]].ob_spec)->te_ptext = &drvid[19+j][0];
  1752.             } else if (j < 16)    {
  1753.                 /*
  1754.                 drvid[20][10] = devid[i+index].dev - 8 + '0';
  1755.                 */
  1756.                 (physdial[physxlat[i]].ob_spec)->te_ptext = &drvid[27+j-8][0];
  1757.             } else {
  1758.                 (physdial[physxlat[i]].ob_spec)->te_ptext = &drvid[35][0];
  1759.             }
  1760.             /*
  1761.             physdial[physid[i]].ob_state = NORMAL;
  1762.             */
  1763.             (physdial[physid[i]].ob_spec)->te_ptext = devid[i+index].id;
  1764.         } else {
  1765.             physdial[physxlat[i]].ob_state = DISABLED;
  1766.             physdial[physid[i]].ob_state = DISABLED;
  1767.             /*
  1768.             (physdial[physid[i]].ob_spec)->te_ptext = &drvid[18][0];
  1769.             */
  1770.         }
  1771.         if (ok2draw)    {
  1772.             objc_draw(physdial,physxlat[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  1773.             objc_draw(physdial,physid[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  1774.             /*
  1775.             objc_draw(physdial,physlat[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  1776.             */
  1777.         }
  1778.     }
  1779. }
  1780.  
  1781. scrupdn(roll, index)
  1782. int roll;
  1783. int *index;
  1784.  
  1785. {
  1786.      int gr_mkmx, gr_mkmy;
  1787.     int gr_mkmstate, gr_mkkstate;
  1788.     int barht, barx, bary;
  1789.     int eptx, epty, eptht;
  1790.  
  1791.     barht = physdial[SLTRK].ob_height;
  1792.     eptht = physdial[SLBOX].ob_height;
  1793.     graf_mkstate(&gr_mkmx, &gr_mkmy, &gr_mkmstate, &gr_mkkstate);
  1794.     objc_offset(physdial, SLBOX, &eptx, &epty);
  1795.     objc_offset(physdial, SLTRK, &barx, &bary);
  1796.     /* check which part of bar was clicked */
  1797.     if (gr_mkmy > (epty+eptht))    {    /* low part of bar was clicked */
  1798.         if (roll == ROLL4)    {
  1799.             /*
  1800.             if (eptht > (bary+barht-epty-eptht))    {
  1801.             if ((spscsixst) && (*index+5 >= ndevs))    {
  1802.                 *index = ndevs - 4;
  1803.                 physdial[SLBOX].ob_y = barht - eptht;
  1804.             } else if (*index+5 >= ndevs)    {
  1805.             */
  1806.             if ((*index+5 >= ndevs) || (eptht > (bary+barht-epty-eptht)))    {
  1807.                 physdial[SLBOX].ob_y = barht - eptht;
  1808.                 *index = ndevs - 4;    /* the last 4 to display */
  1809.             } else if (*index+4 < ndevs)    {
  1810.                 /*
  1811.                 physdial[SLBOX].ob_y += barht / 4;
  1812.                 */
  1813.                 physdial[SLBOX].ob_y += eptht;
  1814.                 *index += 4;
  1815.             }
  1816.         } else {    /* ROLL1 */
  1817.             if ((*index+5 >= ndevs)||((barht/ndevs)>(bary+barht-epty-eptht))){
  1818.                 physdial[SLBOX].ob_y = barht - eptht;
  1819.                 *index = ndevs - 4;    /* the last 4 to display */
  1820.             } else {
  1821.                 physdial[SLBOX].ob_y += barht / ndevs;
  1822.                 *index += 1;
  1823.             }
  1824.         }
  1825.     } else if (gr_mkmy < epty)    {    /* upper part of bar was clicked */
  1826.         if (roll == ROLL4)    {
  1827.             if ((eptht > (epty - bary)) || (*index <= 4))    {
  1828.                 physdial[SLBOX].ob_y = 0;
  1829.                 *index = 0;
  1830.             } else {
  1831.                 /*
  1832.                 physdial[SLBOX].ob_y -= barht / 4;
  1833.                 */
  1834.                 physdial[SLBOX].ob_y -= eptht;
  1835.                 *index -= 4;
  1836.             }
  1837.         } else {
  1838.             if (*index <= 1)    {
  1839.                 physdial[SLBOX].ob_y = 0;
  1840.                 *index = 0;
  1841.             } else {
  1842.                 physdial[SLBOX].ob_y -= barht / ndevs;
  1843.                 *index -= 1;
  1844.             }
  1845.         }
  1846.     } else {
  1847.       return OK;
  1848.     }
  1849.     objc_draw(physdial,SLTRK, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1850.     drawdev(*index);
  1851. }
  1852.  
  1853.  
  1854. slidebox(tree, index)
  1855.  
  1856. OBJECT *tree;
  1857. int *index;
  1858.  
  1859. {
  1860.     int gr_wreturn, eptatmax;
  1861.     int ind, tmp;
  1862.  
  1863.     ind = ndevs - 4;
  1864.     eptatmax = tree[SLTRK].ob_height - tree[SLBOX].ob_height;
  1865.     gr_wreturn = graf_slidebox(tree, SLTRK, SLBOX, 1);
  1866.     tmp = (ind * gr_wreturn) / 1000;
  1867.     if (tmp == *index)    {    /* slide box is in the same place */
  1868.         return OK;    
  1869.     } else {
  1870.         *index = tmp;
  1871.     }
  1872.     if (*index+4 > ndevs)    {
  1873.         *index = ndevs-4;
  1874.     } 
  1875.     tree[SLBOX].ob_y = (eptatmax * (*index)) / ind;
  1876.     objc_draw(tree, SLTRK, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1877.     drawdev(*index);
  1878. }
  1879.  
  1880.  
  1881.  
  1882. /* put the live device into a list */
  1883.  
  1884. linkdev()
  1885. {
  1886.  
  1887.     int i, j=0;
  1888.  
  1889.     for (i=0; i<16; i++)    {
  1890.         devid[i].flg = 0;
  1891.         devid[i].id = &drvid[18][0];
  1892.         if (livedevs[i])    {
  1893.             devid[j].flg = P_EXISTS;
  1894.             devid[j].dev = i;
  1895.             if (idevs[i])    {
  1896.                 devid[j++].id = &drvid[i][0];
  1897.             } else {
  1898.                 devid[j++].id = &drvid[17][0];
  1899.             }
  1900.         } else if (idevs[i])    {
  1901.             devid[j].flg = 2;
  1902.             devid[j].dev = i;
  1903.             devid[j++].id = &drvid[i][0];
  1904.         }
  1905.     }
  1906.     if (spscsixst)    {
  1907.         devid[j].flg = P_EXISTS;
  1908.         devid[j].dev = i;
  1909.         devid[j++].id = &drvid[i][0];
  1910.     }
  1911.  
  1912.     ndevs = j;    /* number of live devices */
  1913.  
  1914. }
  1915.  
  1916. ggphysdev()
  1917. {
  1918.     int i, j, endup, start, index=0;
  1919.     int ret, unit=8;
  1920.  
  1921.     /* Set up the dialog box for SCSI or ACSI or IDE-AT driver selection */
  1922. redogphy:
  1923.     typedial[SCSIYES].ob_state = NORMAL;
  1924.     typedial[ACSIYES].ob_state = NORMAL;
  1925.     typedial[IDEYES].ob_state = NORMAL;
  1926.     if (!tformat)    {
  1927.         /* check which type of unit was selected */
  1928.         if ((!ttscsi)&&(!spscsixst)&&(noacsi))    { /* don't need select */
  1929.             index = 16;
  1930.             unit = 2;
  1931.         } else if ((!ttscsi)&&(!spscsixst)&&(!atexst))    {/* don't need select */
  1932.             ;
  1933.         } else if ((!atexst) && (noacsi))    { /* don't need select */
  1934.             index = 8;
  1935.         } else {
  1936.             if ((!ttscsi)&&(!spscsixst))    {
  1937.                 typedial[SCSIYES].ob_state = DISABLED;
  1938.             } else if (!atexst)    {
  1939.                 typedial[IDEYES].ob_state = DISABLED;
  1940.             } else if (noacsi)    {
  1941.                 typedial[ACSIYES].ob_state = DISABLED;
  1942.             }
  1943.             if ((ret = execform(typedial)) == SCSIYES)    {
  1944.                 index = 8;
  1945.             } else if (ret == IDEYES)    {
  1946.                 index = 16;
  1947.                 unit = 2;
  1948.             }
  1949.         } 
  1950.     } else {     /* do format */
  1951.         if ((ret = execform(typedial)) == SCSIYES)    {
  1952.             index = 8;
  1953.         } else if (ret == IDEYES)    {
  1954.             index = 16;
  1955.             unit = 2;
  1956.         }
  1957.     }
  1958.     /*
  1959.      * Clean up and exec object;
  1960.      * shadow devs we KNOW are there.
  1961.      */
  1962.     physdial[PHYSOK].ob_state = NORMAL;
  1963.     physdial[PHYSCN].ob_state = NORMAL;
  1964.     
  1965.     /*
  1966.     if (tformat == TRUE) {
  1967.         start = 1;        start initializing at unit 0 
  1968.         physdial[physxlat[0]].ob_state = NORMAL;
  1969.     } else {
  1970.         start = 0;        start initializing at unit 1
  1971.     }
  1972.     */
  1973.     
  1974.     endup = index + unit;
  1975.     if (index == 16)    {
  1976.         physdial[physxlat[0]].ob_state = NORMAL;
  1977.         if ((spscsixst) || (atexst))    {
  1978.             (physdial[physid[0]].ob_spec)->te_ptext = &drvid[16][0];
  1979.         } else {
  1980.             (physdial[physid[0]].ob_spec)->te_ptext = &drvid[18][0];
  1981.         }
  1982.         for (i = 1; i < 8; i++)    {
  1983.             (physdial[physid[i]].ob_spec)->te_ptext = &drvid[18][0];
  1984.             physdial[physid[i]].ob_state = DISABLED;
  1985.             physdial[physxlat[i]].ob_state = DISABLED;
  1986.         }
  1987.     } else {
  1988.         for (i = 0; i < 8; i++)    {
  1989.             (physdial[physid[i]].ob_spec)->te_ptext = &drvid[18][0];
  1990.             if ((spscsixst)&&(tformat)&&(!index))    {
  1991.                 physdial[physid[i]].ob_state = DISABLED;
  1992.                 physdial[physxlat[i]].ob_state = DISABLED;
  1993.             } else if (tformat)    {    /* when format, all devices are on */
  1994.                 physdial[physxlat[i]].ob_state = NORMAL;
  1995.                 physdial[physid[i]].ob_state = NORMAL;
  1996.             } else {
  1997.                 physdial[physid[i]].ob_state = DISABLED;
  1998.                 physdial[physxlat[i]].ob_state = DISABLED;
  1999.             }
  2000.         }
  2001.     }
  2002.     /*
  2003.     if (ttscsi)             the hard drive is a SCSI drive 
  2004.         physdial[physxlat[8]].ob_state = NORMAL;
  2005.     */
  2006.     for (i = index, j = 0; i < endup; ++i, j++)        {
  2007.         if (livedevs[i])    {
  2008.             physdial[physxlat[j]].ob_state = NORMAL | SHADOWED;
  2009.             physdial[physid[j]].ob_state = NORMAL;
  2010.             if ((i < 16) && (idevs[i]))    {
  2011.                 (physdial[physid[j]].ob_spec)->te_ptext = &drvid[i][0];
  2012.             } else if ((i < 16) && (!index))    {
  2013.                 (physdial[physid[j]].ob_spec)->te_ptext = &drvid[17][0];
  2014.             }
  2015.         }
  2016.     }
  2017.  
  2018.  
  2019.     if (execform(physdial) != PHYSOK)
  2020.         return ERROR;
  2021.      
  2022.     /* search for the selected unit */
  2023.     for (i = 0; i < unit; ++i)
  2024.         if (physdial[physxlat[i]].ob_state & SELECTED)    {
  2025.             return(index+i);
  2026.             /*
  2027.             if (livedevs[index+i])
  2028.                 return(index+i);
  2029.             else    {    
  2030.                 form_alart(1, nodev);
  2031.                 goto redogphy;
  2032.             }
  2033.             */
  2034.         }
  2035.  
  2036.  
  2037.     return ERROR;            /* if no object selected */
  2038. }
  2039.  
  2040. /*
  2041.  * Translate from logical device number
  2042.  * to object number in logical device
  2043.  * dialouge box.
  2044.  */
  2045. int logxlat[] = {
  2046.     CCOLON, DCOLON, ECOLON, FCOLON,
  2047.     GCOLON, HCOLON, ICOLON, JCOLON,
  2048.     KCOLON, LCOLON, MCOLON, NCOLON,
  2049.     OCOLON, PCOLON
  2050. };
  2051.  
  2052.  
  2053. /*
  2054.  * Get logical device,
  2055.  * return 'C'...'P'
  2056.  * or -1.
  2057.  *
  2058.  */
  2059. glogdev()
  2060. {
  2061.     int i, flg;
  2062.  
  2063.     /*
  2064.      * Setup tree; selectively enable drive buttons
  2065.      * and so on.
  2066.      */
  2067.     logdial[LOGOK].ob_state = NORMAL;
  2068.     logdial[LOGCN].ob_state = NORMAL;
  2069.     for (i = 0; i < MAXLOGDEVS; ++i) {
  2070.     if (logmap[i].lm_physdev < 0)
  2071.         flg = DISABLED;
  2072.         else flg = NORMAL;
  2073.     logdial[logxlat[i]].ob_state = flg;
  2074.     }
  2075.  
  2076.     if (execform(logdial) != LOGOK) return -1;
  2077.  
  2078.     for (i = 0; i < MAXLOGDEVS; ++i)
  2079.     if (logdial[logxlat[i]].ob_state & SELECTED)
  2080.         return i + 'C';
  2081.  
  2082.     return -1;
  2083. }
  2084.  
  2085.  
  2086. /*
  2087.  * Open virtual workstation.
  2088.  *
  2089.  */
  2090. open_vwork()
  2091. {
  2092.     int i;
  2093.  
  2094.     for (i = 0; i < 10;)
  2095.     work_in[i++] = 1;
  2096.     work_in[10] = 2;
  2097.     handle = phys_handle;
  2098.     v_opnvwk(work_in, &handle, work_out);
  2099. }
  2100.  
  2101.  
  2102. /*
  2103.  * Find and redraw all clipping rectangles
  2104.  *
  2105.  */
  2106. do_redraw(xc, yc, wc, hc)
  2107. int xc, yc, wc, hc;
  2108. {
  2109.     GRECT t1, t2;
  2110.     int temp[4];
  2111.  
  2112.     hide_mouse();
  2113.     t2.g_x=xc;
  2114.     t2.g_y=yc;
  2115.     t2.g_w=wc;
  2116.     t2.g_h=hc;
  2117.     vsf_interior(handle, 1);
  2118.     vsf_color(handle, 0);
  2119.     wind_get(wi_handle, WF_FIRSTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  2120.     while (t1.g_w && t1.g_h) {
  2121.     if (rc_intersect(&t2, &t1)) {
  2122.         set_clip(t1.g_x, t1.g_y, t1.g_w, t1.g_h);
  2123.         temp[0] = xwork;
  2124.         temp[1] = ywork;
  2125.         temp[2] = xwork + wwork - 1;
  2126.         temp[3] = ywork + hwork - 1;
  2127.         v_bar(handle, temp);
  2128.     }
  2129.     wind_get(wi_handle, WF_NEXTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  2130.     }
  2131.  
  2132.     show_mouse();
  2133. }
  2134.  
  2135.  
  2136. /*
  2137.  * Hide the mouse.
  2138.  *
  2139.  */
  2140. hide_mouse()
  2141. {
  2142.     if (!hidden) {
  2143.     graf_mouse(M_OFF, 0L);
  2144.     hidden = TRUE;
  2145.     }
  2146. }
  2147.  
  2148.  
  2149. /*
  2150.  * Show the mouse.
  2151.  *
  2152.  */
  2153. show_mouse() 
  2154. {
  2155.     if (hidden) {
  2156.     graf_mouse(M_ON, 0L);
  2157.     hidden = FALSE;
  2158.     }
  2159. }
  2160.  
  2161.  
  2162. /*
  2163.  * Set clipping rectangle.
  2164.  *
  2165.  */
  2166. set_clip(x, y, w, h)
  2167. int x, y, w, h;
  2168. {
  2169.     int clip[4];
  2170.  
  2171.     clip[0] = x;
  2172.     clip[1] = y;
  2173.     clip[2] = x + w;
  2174.     clip[3] = y + h;
  2175.     vs_clip(handle, 1, clip);
  2176. }
  2177.  
  2178.  
  2179. /*
  2180.  * "Execute" form,
  2181.  * return thingy that caused the exit.
  2182.  *
  2183.  */
  2184. execform(tree)
  2185. OBJECT tree[];
  2186. {
  2187.     int thingy;
  2188.  
  2189.     ARROW_MOUSE;
  2190.     dsplymsg(tree);
  2191.     thingy = form_do(tree, 0);
  2192.     erasemsg();
  2193.     BEE_MOUSE;
  2194.     return thingy;
  2195. }
  2196.  
  2197.  
  2198. /*
  2199.  *  Display a dialogue box on the screen.
  2200.  *    Input:
  2201.  *        tree - object tree for dialogue box to be displayed.
  2202.  *    Output:
  2203.  *        formw, formh, sx, sy, lx, ly - dimensions of box.
  2204.  */
  2205. dsplymsg(tree)
  2206. OBJECT *tree;
  2207. {
  2208.     form_center(tree,&lx, &ly, &formw, &formh);
  2209.  
  2210.     /*
  2211.     sx = lx + formw / 2;
  2212.     sy = ly + formh / 2;
  2213.     */
  2214.     
  2215.     form_dial(1, 0, 0, 0, 0, lx, ly, formw, formh);
  2216.     objc_draw(tree, 0, MAX_DEPTH, 0, 0, wdesk, hdesk);
  2217. }
  2218.  
  2219.  
  2220. /*
  2221.  *  Erase a dialogue box from the screen.
  2222.  *    Input:
  2223.  *        formw, formh, sx, sy, lx, ly - dimensions of box.
  2224.  */
  2225. erasemsg()
  2226. {
  2227.     form_dial(3, 0, 0, 0, 0, lx, ly, formw, formh);
  2228. }
  2229.  
  2230.  
  2231.  
  2232. /*
  2233.  *  Make a long (4-byte) random.
  2234.  */ 
  2235. long
  2236. longrandom()
  2237. {
  2238.     long pattern;
  2239.     
  2240.     pattern = Random();
  2241.     pattern <<= 16;
  2242.     pattern ^= Random();
  2243.     
  2244.     return (pattern);
  2245. }
  2246.  
  2247. changeid(part)
  2248. PART *part;
  2249. {
  2250.     int i;
  2251.     long psiz;
  2252.  
  2253.     for(i = 0; i < npart; i++)    {
  2254.         if (i == ext)    continue;
  2255.         if (!(part[i].p_flg & P_EXISTS)) return OK;
  2256.         if (i > 3)    {
  2257.             psiz = part[i].p_siz - ROOTSECT;
  2258.         } else {
  2259.             psiz = part[i].p_siz;
  2260.         }
  2261.         if (psiz < MB16)    {
  2262.             part[i].p_id[0] = 'G';
  2263.             part[i].p_id[1] = 'E';
  2264.             part[i].p_id[2] = 'M';
  2265.         } else {
  2266.             part[i].p_id[0] = 'B';
  2267.             part[i].p_id[1] = 'G';
  2268.             part[i].p_id[2] = 'M';
  2269.         }
  2270.     }
  2271. }
  2272.  
  2273.