home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / HARDWARE / WDIGITAL.ZIP / WDFMT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-27  |  21.5 KB  |  770 lines

  1.  
  2.  
  3.  
  4. /*************************************/
  5. /*                                   */
  6. /*                      */
  7. /*                                   */
  8. /*************************************/
  9.  
  10. /*
  11.   Western Digital Corp. Format Routine
  12.  
  13.         Author: Dave Evans
  14. Edited by Tom Devlin
  15.  
  16.         Creation Date:    08/08/86
  17.         Revision Date:    7/23/87
  18.         Revision: 2.00
  19.  
  20.     Formats drive based on #cylinders, #heads, #sectors, and
  21.     interleave entered at command line or on screen.  Does low-level format
  22.     followed by a Read-verify of the entire drive.  Shows errors
  23.     detected, then allows user to enter additional blocks to
  24.     format with bad block marks.  The program may be aborted
  25.     with an Escape at both the Format prompt and at the Format
  26.     Bad Block prompt.
  27.  
  28.     Rev. 1.01   dle
  29.     Added ability to format drive D:, and also the ability to
  30.     specify the precomp cylinder.
  31.     New command line format:
  32.         WDFMT drive #cyls #heads #sectors interleave precomp-cyl
  33.  
  34.     Rev.2.00    thd
  35.     Added ability to format up to 16 heads.
  36.     fix to enable format of drive 1.
  37.     New drive spec enrty by screen:
  38.  
  39. */
  40. #include <\c_lat\comp\dos.h>
  41. #include <\c_lat\comp\stdio.h>
  42. #include <\c_lat\comp\ctype.h>
  43. #include <\c_lat\comp\math.h>
  44. #include <\c_lat\comp\limits.h>
  45.  
  46.  
  47.  
  48. #define then
  49. #define esc    '\x1b'
  50. #define true -1
  51. #define false 0
  52.  
  53. #define buf_length (512+10)
  54. #define hard 1
  55. #define soft 0
  56.  
  57. #define curs(a,b) pcvscp((a-1), (b-1))
  58. #define bell printf("%c", 7)
  59. #define ARROW printf("%c", 16)
  60. #define BLANK printf(" ")
  61. #define char_ready pckchk()
  62.  
  63. /*  Global variables:
  64.  
  65.         Command parser modifies the tables, and global flags
  66.         indicate to the Main routine the requested action.
  67.  
  68. */
  69.  
  70. struct htable
  71. {
  72.     int drv_number;
  73.     int cyl_number;
  74.     int head_number;
  75.     int sec_number;
  76.     int blk_size;
  77.     int max_cyl;
  78.     int max_head;
  79.     int max_sec;
  80.     int precomp;
  81.     int retry;
  82.     int step;
  83.     int ileave;
  84.     int ecc_len;
  85.     float bits_read;
  86. } hd_table;
  87.  
  88. struct tfile
  89. {
  90.     int error;
  91.     int secnt;
  92.     int sector;
  93.     int cyllo;
  94.     int cylhi;
  95.     int SDH;
  96.     int status;
  97.     int secstat;
  98.     int DIR;
  99. } task_file;
  100.  
  101. struct esfile
  102. {
  103.     int xfrlo;
  104.     int xfrhi;
  105.     int plo;
  106.     int gap;
  107.     int stat;
  108. };
  109.  
  110. union scan
  111. {
  112.    int  c;
  113.    char ch[2];
  114. } scan_code;
  115.  
  116. char *rd_buffer, *wr_buffer, *fmt_buffer;
  117.  
  118. struct error
  119. {
  120.     int cyl;
  121.     int head;
  122. };
  123.  
  124. struct error err_table[100];
  125.  
  126. int err_count, errcnt;
  127. int temp;
  128.  
  129. main(argc, argv)
  130.  
  131. int argc;
  132. char *argv[];
  133.  
  134. {
  135.  
  136.     char *malloc();
  137.     char resp, temp_str[8];
  138.     int bad_count;
  139.  
  140.     wr_buffer = malloc(buf_length);
  141.     rd_buffer = malloc(buf_length);
  142.     fmt_buffer = malloc(buf_length);
  143.  
  144. /*************************************/
  145. /*                                   */
  146. /*  start of main body               */
  147. /*                                   */
  148. /*************************************/
  149.  
  150.     hd_table.sec_number = 1;              /*initialize hd_table to defalt */
  151.     hd_table.blk_size = 1;
  152.     hd_table.max_cyl = 615;
  153.     hd_table.max_head = 4;
  154.     hd_table.max_sec = 17;
  155.     hd_table.precomp = 306;
  156.     hd_table.retry = 0;
  157.     hd_table.step = 0;
  158.     hd_table.ileave = 3;
  159.     hd_table.drv_number = 0;
  160.  
  161.  
  162.    get_spec(argc, argv);     /* get specs user typed in when prog called */
  163.    screen_update();          /* out put screen */
  164.    get_2spec();              /* get drive specs from screen */
  165.    get_command();            /* get escape or F from standerd input */
  166.  
  167.                             /* set up hd_table with adjusted values  */
  168.  
  169.     hd_table.max_cyl--;
  170.     hd_table.max_head--;
  171.     hd_table.precomp = (int)(hd_table.precomp/4);
  172.  
  173.     at_reset();                 /* reset hard drive */
  174.     while(at_ckbsy());          /* check busy bit in controler */
  175.     while(at_ckbsy());          /* wait untill drive is ready */
  176.  
  177.     load_task_file();           /* load task file                    */
  178.     at_setp(hd_table.drv_number, hd_table.max_sec, hd_table.max_head);  /* set up param on controler */
  179.     while(at_ckbsy());          /* check busy bit in controler */
  180.     while(at_ckbsy());          /* wait untill drive is ready */
  181.  
  182.     load_task_file();           /* load task file                    */
  183.     at_rest(0);                 /* recal drive    */
  184.     while(at_ckbsy());          /* check busy bit in controler */
  185.     while(at_ckbsy());          /* check busy bit in controler */
  186.     load_task_file();           /* load task file                    */
  187.     at_rest(0);                 /* restore drive  */
  188.     while(at_ckbsy());          /* check busy bit in controler */
  189.     while(at_ckbsy());          /* check busy bit in controler */
  190.  
  191.     if (at_ckerr())             /* check if error for recal */
  192.         show_error();              /* show any errors */
  193.  
  194.     do_ilt(0);                            /* set up interleave for good blocks */
  195.     hd_table.blk_size = hd_table.max_sec; /* do all drive */
  196.  
  197.     format_all();               /* format all of disk */
  198.     verify_all();               /* verify all of disk */
  199.  
  200.     if (err_count > 1)
  201.  
  202. /*************************************/
  203. /*                                   */
  204. /* should we mark bad mark  sectors  */
  205. /*                                   */
  206. /*************************************/
  207.  
  208.     {
  209.         do_errors();
  210.         printf("\n\nDo you wish to mark these blocks bad? (y/n)");
  211.         resp = cget();
  212.         while (toupper(resp) != 'Y')
  213.         {
  214.             if (toupper(resp) == 'N')
  215.             {
  216.                 err_count = 1;
  217.                 break;
  218.             }
  219.             else
  220.                 bell;
  221.             resp = cget();
  222.         }
  223.     }
  224.  
  225. /*************************************/
  226. /*                                   */
  227. /* enter other bad sectors           */
  228. /*                                   */
  229. /*************************************/
  230.  
  231.  
  232.     clr_scrn();
  233.     printf("\n\nYou may now enter additional blocks to be marked bad.");
  234.     printf("\n\nEnter cylinder and head info (seperated by spaces) at");
  235.     printf("\nthe prompt. To end entry, press  ENTER  at the prompt\n");
  236.  
  237.     for (; err_count < 100; err_count++)
  238.     {
  239.         printf("Enter  <cylinder#> <head#>:  ");
  240.         cgets(temp_str);
  241.         if (strcmp(temp_str, "") == 0)
  242.             break;
  243.         if (sscanf(temp_str, "%d %d", &err_table[err_count].cyl,
  244.                 &err_table[err_count].head) != 2)
  245.         {
  246.             bell;
  247.             err_count--;
  248.         }
  249.     }
  250. /*************************************/
  251.  
  252.     if (err_count > 1)
  253.  
  254. /*************************************/
  255. /*                                   */
  256. /* mark bad sectors                  */
  257. /*                                   */
  258. /*************************************/
  259.  
  260.  
  261.     {
  262.         do_errors();
  263.         printf("\n\nReady to format bad blocks...........");
  264.         printf("\n\nPress <ESC> to abort, any other key to continue\n");
  265.         if (cget() == esc)
  266.             exit(0);
  267.         bad_count = 0;
  268.         do_ilt(128);
  269.         for (errcnt = 1; errcnt < err_count; errcnt++)
  270.         {
  271.             hd_table.cyl_number = err_table[errcnt].cyl;
  272.             hd_table.head_number = err_table[errcnt].head;
  273.             load_task_file();
  274.             at_fmt();
  275.             while(!( 0x08 & at_rstat())); /* wait for data request */
  276.             at_wrbfr(0, wr_buffer);
  277.             while(at_ckbsy());          /* check busy bit in controler */
  278.             while(at_ckbsy());          /* check busy bit in controler */
  279.             bad_count++;
  280.         }
  281.     }
  282. /*************************************/
  283.  
  284.     printf("\n\nFormat complete.....");
  285.     if (bad_count > 0)
  286.         printf("Bad blocks marked");
  287.     printf("\n\nRestart system before doing FDISK");
  288.  
  289.  
  290.  
  291. }
  292.  
  293. /*************************************/
  294. /*                                   */
  295. /* make block mark and sector #      */
  296. /* for one track                     */
  297. /*                                   */
  298. /*************************************/
  299.  
  300. do_ilt(block_mark)
  301.  
  302. char block_mark;
  303.  
  304. {
  305.  
  306.     int    offset,sec_count,ileave,maxcnt;
  307.     char    *p;
  308.  
  309.     p = wr_buffer;
  310.     for( sec_count=0; sec_count < 512; sec_count++ ) *p++ = 0xff;
  311.     if (hd_table.ileave > 8)
  312.     {
  313.         ileave = hd_table.ileave - 8;
  314.         sec_count = 0;
  315.         maxcnt = hd_table.max_sec - 1;
  316.     }
  317.     else
  318.     {
  319.         ileave = hd_table.ileave;
  320.         sec_count = 1;
  321.         maxcnt = hd_table.max_sec;
  322.     };
  323.  
  324.     offset = 0;
  325.  
  326.     while ( sec_count <= maxcnt )
  327.     {
  328.         if (hd_table.ileave > 8)
  329.         {
  330.                if ( offset > maxcnt ) offset = 0;
  331.         }
  332.         else
  333.         {
  334.             if ( offset >= maxcnt ) offset = 0;
  335.         }
  336.         p = wr_buffer + ( offset * 2 ) + 1;
  337.         if ( *p == 0xff )
  338.         {
  339.             *p = sec_count;
  340.             *--p = block_mark;
  341.             offset += ileave;
  342.             sec_count++;
  343.         }
  344.         else offset++;
  345.     };
  346. }
  347.  
  348. /*************************************/
  349. /*                                   */
  350. /* set up task file and load it      */
  351. /*                                   */
  352. /*************************************/
  353.  
  354. load_task_file()
  355.  
  356. {
  357.  
  358.     task_file.error = hd_table.precomp;
  359.     task_file.secnt = hd_table.blk_size;
  360.     task_file.sector = hd_table.sec_number;
  361.     task_file.cyllo = (hd_table.cyl_number % 256);
  362.     task_file.cylhi = (hd_table.cyl_number / 256);
  363.     task_file.SDH = (((hd_table.drv_number << 4) & 0x10) +
  364.         (hd_table.head_number & 0xf) + 0xa0);
  365.     at_wtskf(&task_file);
  366. }
  367.  
  368. /*************************************/
  369. /*                                   */
  370. /* display errors from reisters      */
  371. /*                                   */
  372. /*************************************/
  373.  
  374. show_error()
  375.  
  376. {
  377.     curs(22,1);
  378.     printf("   Error!!... Cyl. %4d   Head %2d  Status  %2x  Error  %2x",
  379.         hd_table.cyl_number, hd_table.head_number,
  380.         at_rstat(), at_rderr());
  381. }
  382.  
  383.  
  384. /*************************************/
  385. /*                                   */
  386. /*                      */
  387. /*                                   */
  388. /*************************************/
  389.  
  390. clr_scrn()
  391.  
  392. {
  393.     char window[4];
  394.     window[0]=0; window[1]=0;
  395.     window[2]=79; window[3]=24;
  396.  
  397.     pcvsu(window,0,7);
  398.     curs(1,1);
  399. }
  400.  
  401. /*************************************/
  402. /*                                   */
  403. /* display errors found in error table*/
  404. /*                                   */
  405. /*************************************/
  406.  
  407. do_errors()
  408. {
  409.     clr_scrn();
  410.     printf("Errors will be marked at the following cylinder/head locations:");
  411.     printf("\n\n");
  412.     for (errcnt = 1; errcnt < err_count; errcnt++)
  413.     {
  414.         printf("        %4d/%2d", err_table[errcnt].cyl,
  415.             err_table[errcnt].head);
  416.         if ((errcnt % 5) == 0)
  417.             printf ("\n");
  418.     }
  419. }
  420.  
  421. /*************************************/
  422. /*                                   */
  423. /* dimp 5 lines of buffer to screen  */
  424. /*                                   */
  425. /*************************************/
  426.  
  427. dump_5lines(buffer)
  428.  
  429. char *buffer;
  430.  
  431. {
  432.     int num_bytes, count;
  433.  
  434.     for (count = 0; count < 80; count++)
  435.     {
  436.         if ((count % 16) == 0)
  437.             printf("\n%04x    ", count);
  438.         printf("%02x  ", buffer[count]);
  439.     };
  440.     printf("\n");
  441. }
  442.  
  443. /*************************************/
  444. /*                                   */
  445. /*  get drive specs                  */
  446. /*                                   */
  447. /*************************************/
  448.  
  449. get_spec(argc, argv)
  450.  
  451. int argc;
  452. char *argv[];
  453.  
  454.  
  455. {
  456.     argc--;
  457.     
  458.     if (argc > 0)
  459.     {                                 /* get drive # */
  460.         sscanf(*++argv, "%d", &hd_table.drv_number);
  461.         argc--;
  462.     };
  463.  
  464.     if (argc > 0)
  465.     {                                 /* get max cylinder # */
  466.         sscanf(*++argv, "%d", &hd_table.max_cyl);
  467.         argc--;
  468.     };
  469.  
  470.     if (argc > 0)
  471.     {                                 /* get max head #  */
  472.         sscanf(*++argv, "%d", &hd_table.max_head);
  473.         argc--;
  474.     };
  475.  
  476.     if (argc > 0)
  477.     {                                 /* get max sectors/track */
  478.         sscanf(*++argv, "%d", &hd_table.max_sec);
  479.         argc--;
  480.     };
  481.  
  482.     if (argc > 0)
  483.     {                                 /* get interleave value */
  484.         sscanf(*++argv, "%d", &hd_table.ileave);
  485.         argc--;
  486.     };
  487.  
  488.     if (argc > 0)
  489.     {                                 /* get precomp cylinder # */
  490.         sscanf(*++argv, "%d", &hd_table.precomp);
  491.         argc--;
  492.     };
  493. }
  494.  
  495. /*************************************/
  496. /*                                   */
  497. /*    screen update                  */
  498. /*                                   */
  499. /*************************************/
  500.  
  501. screen_update()
  502.  
  503. {
  504.     clr_scrn();
  505.     printf("                   *** Western Digital Corporation ***\n");
  506.     printf("                         AT  Disk Format Utility\n");
  507.     printf("                                Rev. 2.00\n\n\n");
  508.     printf("     Current formatting parameters are:\n\n\n");
  509.     curs(9,1);
  510.     printf("                   Drive (0/1) :                           \n");
  511.     printf("                   Cylinders   :                           \n");
  512.     printf("                   Heads       :                           \n");
  513.     printf("                   Sectors     :                           \n");
  514.     printf("                   Interleave  :                           \n");
  515.     printf("                   Precomp     :                           \n");
  516.     curs(9, 34);printf(" %4d\n",  hd_table.drv_number);
  517.     curs(10,34);printf(" %4d\n",  hd_table.max_cyl);
  518.     curs(11,34);printf(" %4d\n",  hd_table.max_head);
  519.     curs(12,34);printf(" %4d\n",  hd_table.max_sec);
  520.     curs(13,34);printf(" %4d\n",  hd_table.ileave);
  521.     curs(14,34);printf(" %4d\n",  hd_table.precomp);
  522.  
  523. }
  524.  
  525. /*************************************/
  526. /*                                   */
  527. /*    get_2spec                      */
  528. /*                                   */
  529. /*    get drive spects from user     */
  530. /*                                   */
  531. /*************************************/
  532.  
  533. get_2spec()
  534.  
  535. {
  536.    int done;
  537.    char temp_str[8];
  538.  
  539.    done = false;
  540.    while(!done)
  541.    {
  542.  
  543.       curs(17,5);
  544.       printf("Enter drive specification at prompt or <CR> for default.              ");
  545.  
  546.       /* get input from screen */
  547.       prompt(9, &hd_table.drv_number);
  548.       prompt(10,&hd_table.max_cyl   );
  549.       prompt(11,&hd_table.max_head  );
  550.       prompt(12,&hd_table.max_sec   );
  551.       prompt(13,&hd_table.ileave    );
  552.       prompt(14,&hd_table.precomp   );
  553.  
  554.       /* redraw screen */
  555.       curs(9,1);
  556.       printf("                   Drive (0/1) :                           \n");
  557.       printf("                   Cylinders   :                           \n");
  558.       printf("                   Heads       :                           \n");
  559.       printf("                   Sectors     :                           \n");
  560.       printf("                   Interleave  :                           \n");
  561.       printf("                   Precomp     :                           \n");
  562.       curs(9, 34);printf(" %4d\n",  hd_table.drv_number);
  563.       curs(10,34);printf(" %4d\n",  hd_table.max_cyl);
  564.       curs(11,34);printf(" %4d\n",  hd_table.max_head);
  565.       curs(12,34);printf(" %4d\n",  hd_table.max_sec);
  566.       curs(13,34);printf(" %4d\n",  hd_table.ileave);
  567.       curs(14,34);printf(" %4d\n",  hd_table.precomp);
  568.  
  569.       curs(17,5);
  570.       printf("Enter <CR> if drive specification OK or enter 'C' for more changes : ");
  571.  
  572.       cgets(temp_str);                    /* get standerd input */
  573.       done=true;
  574.       if (strcmp(temp_str, "")!=0 ) done=false;   /* break out if <CR> */
  575.    };                              /* end of while */
  576.    curs(17,5);
  577.    printf("                                                                      ");
  578.    curs(17,5);
  579.    printf("  Warning!!!!  All data will be destroyed on drive : %c  ",
  580.    (char)('C' + hd_table.drv_number));
  581.    printf("\n       Press ESC to return to DOS,  F  to start format");
  582.  
  583. }
  584.  
  585.  
  586.  
  587. /*************************************/
  588. /*                                   */
  589. /* prompt(row,def)                   */
  590. /*                                   */
  591. /*  input:                           */
  592. /*   row : row to display stand input*/
  593. /*   def : pointer to default valvue */
  594. /*                                   */
  595. /*************************************/
  596.  
  597. prompt(row,def)
  598.  
  599. char row;
  600. int *def;
  601.  
  602. {
  603.    char temp_str[8];
  604.  
  605.    curs(row,18);ARROW;
  606.    curs(row,46);
  607.    cgets(temp_str);                    /* get standerd input */
  608.  
  609.    if (strcmp(temp_str, "") != 0)
  610.       sscanf(temp_str, "%d", def); /*change default if input */
  611.    curs(row,18);BLANK;
  612. }
  613.  
  614. /*************************************/
  615. /*                                   */
  616. /* get command                       */
  617. /*                                   */
  618. /*************************************/
  619.  
  620. get_command()
  621.  
  622. {
  623.  
  624.  char resp;
  625.  
  626.     resp = cget();
  627.     while (toupper(resp) != 'F')
  628.     {
  629.         if (resp == esc)
  630.             exit(0);
  631.         else
  632.             bell;
  633.         resp = cget();
  634.     }
  635. }
  636.  
  637. /*************************************/
  638. /*                                   */
  639. /* format whole disk                 */
  640. /*                                   */
  641. /*************************************/
  642. format_all()
  643.  
  644. {
  645.  
  646.    int start_head,last_head;
  647.  
  648.    curs(20, 12);
  649.    printf("Formatting cylinder: ");
  650.    curs(20, 40);
  651.    printf("head:");
  652.  
  653.    if(hd_table.max_head > 7) last_head = 7;
  654.     else last_head = hd_table.max_head;  /* set up last head to format this pass */
  655.    start_head = 0;
  656.    for(hd_table.cyl_number = 0; hd_table.cyl_number <= hd_table.max_cyl;
  657.        hd_table.cyl_number++)
  658.    {                                 /* format heads 0-7 or less */
  659.      format_loop(start_head,last_head);  /* do that format */
  660.    };                                  /* end "for" to  format 0-7 */
  661.  
  662.    if(hd_table.max_head > 7)
  663.    {                                 /* if more than 8 heads on disk drive */
  664.       hd_table.head_number = 8;          /* set up SDH to trick controler into */
  665.       load_task_file();                  /*    thinking that this is a new drive */
  666.       at_rest(0);                        /* recal with 35 micro second rate */
  667.       while(at_ckbsy());                 /* check busy bit in controler */
  668.       while(at_ckbsy());                 /* check busy bit in controler */
  669.       for(hd_table.cyl_number = 0; hd_table.cyl_number <= hd_table.max_cyl;
  670.           hd_table.cyl_number++)
  671.       {
  672.          last_head = hd_table.max_head;     /* last head to format */
  673.          start_head =8;                     /* first head to format */
  674.          format_loop(start_head,last_head); /* do that format */
  675.       };                                  /* end "for" loop */
  676.    };                                  /* end of if > 8*/
  677.  
  678. }                          /*end of format_all */
  679.  
  680.  
  681. /****************************************************/
  682. /*                                                  */
  683. /* format_loop                                      */
  684. /*                                                  */
  685. /* input: start_head; head # to start formating on  */
  686. /*        last_head;  last head to format           */
  687. /*                                                  */
  688. /****************************************************/
  689.  
  690. format_loop(start_head,last_head)
  691.  
  692. int start_head,last_head;
  693.  
  694. {
  695.    curs(20, 33);
  696.    printf("%4d", hd_table.cyl_number);
  697.    for(hd_table.head_number = start_head;
  698.        hd_table.head_number <= last_head;
  699.        hd_table.head_number++)
  700.    {
  701.      load_task_file();
  702.      at_fmt();                  /* send format command */
  703.      while(! (0x08 & at_rstat())); /* wait for data request */
  704.      at_wrbfr(0, wr_buffer);
  705.      while(at_ckbsy());          /* check busy bit in controler */
  706.      while(at_ckbsy());          /* check busy bit in controler */
  707.      if (at_ckerr()) show_error();
  708.  
  709.      curs(20, 46);printf("%2d", hd_table.head_number);
  710.    }                          /* end of for loop */
  711. }                          /* end of format_loop */
  712.  
  713.  
  714.  
  715. /*************************************/
  716. /*                                   */
  717. /* verify each sector                */
  718. /*                                   */
  719. /*************************************/
  720. verify_all()
  721.  
  722. {                                  /* start of verify procedure */
  723.  
  724.     int num_reads;
  725. int stat_byte;
  726.  
  727.     hd_table.blk_size = hd_table.max_sec;
  728.     err_count = 1;
  729.     curs(20, 12);printf("Verifying  ");
  730.     load_task_file();                  /*    thinking that this is a new drive */
  731.     at_rest(0);                        /* recal with 35 micro second rate */
  732.     while(at_ckbsy());                 /* check busy bit in controler */
  733.     while(at_ckbsy());                 /* check busy bit in controler */
  734.     for(hd_table.cyl_number = 0; hd_table.cyl_number <= hd_table.max_cyl;
  735.         hd_table.cyl_number++)
  736.     {                                 /* start of cyclinder loop */
  737.        if(err_count >= 100) break;
  738.        curs(20, 33);printf("%4d", hd_table.cyl_number);
  739.        for(hd_table.head_number = 0;
  740.            hd_table.head_number <= hd_table.max_head;
  741.            hd_table.head_number++)
  742.        {                              /* start of head loop */
  743.           for(num_reads = 0; num_reads < 3; num_reads++)
  744.           {                           /* start of 3 trys to read read */
  745.              load_task_file();
  746.              at_rdver(1);                 /* do that verify with out retry */
  747.              while(at_ckbsy());           /* check busy bit in controler */
  748.              while(at_ckbsy());           /* check busy bit in controler */
  749.              if(at_ckerr())
  750.              {                        /* start of "if error" */
  751.                 if (err_count < 100)
  752.                 {                     /* start of "if error < 100" */
  753.                    err_table[err_count].cyl = hd_table.cyl_number;
  754.                    err_table[err_count].head = hd_table.head_number;
  755.                    err_count++;
  756.                 }                       /* end of "if error < 100" */
  757.                 else
  758.                 {                     /* start of if error >= 100" */
  759.                    bell;
  760.                    printf("\n\nError count exceeded 100 errors!!!");
  761.                 }                       /* end of "if error >= 100" */
  762.                 break;                    /* break out of 3 tries */
  763.              }                          /* end of "if error" */
  764.           }                             /* end of 3 tries */
  765.        curs(20, 46);printf("%2d", hd_table.head_number);
  766.        }                                /* end of head loop */
  767.     }                                   /* end of cyclinder loop */
  768. }                                    /* end of verify procedure */
  769. /*************************************/
  770.