home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 118.lha / bformat.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  11KB  |  469 lines

  1. /* bformat.c */
  2.  
  3. /* simple program to format drive df0:, creating a bitmap which marks
  4.    bad tracks as 'in use'. Should work for any 3.5" floppy which can hold
  5.    a format on track 0 and 80 (Dos minimum requirements).. I never could
  6.    figure out why Dos didn't do this all by itself.. Should you really have
  7.    to throw out a disk that has one or two lousy tracks? */
  8.  
  9. /* I've been meaning to write this program for quite a long while but never
  10.    took the time to figure out how AmigaDos stores/manipulates the block
  11.    allocation map (aka bitmap). Well, finally took an evening and threw this
  12.    together. To the best of my determination here is a description of
  13.    the block allocation scheme (for 3.5" floppies anyway..) :
  14.  
  15.    When you format a diskette dos grabs 2 blocks for its own use.
  16.    Block 880 is the Root block. Block 881 (normally on a fresh format) is
  17.    the bitmap which in itself indicates the blocks that are available for use
  18.    or currently in use. Generally, a '1' bit means the corresponding block
  19.    is available. A '0' bit means that the block is in use. This sounds
  20.    relatively simple but the AmigaDos implementation needs some 
  21.    explanation.
  22.    
  23.    AmigaDos Block Allocation Map (512 bytes -or- 128 longwords)
  24.    ------------------------------------------------------------
  25.    LongWord   Usage
  26.    --------   -----
  27.       0       location of the block checksum
  28.       1       first bitmap allocation longword, which breaks down as follows:
  29.  
  30.      hi-order bit (31)              lo-order bit (0)
  31.     /                              /
  32.    |                              |
  33.    11111111111111111111111111111111 (32 bit longword)
  34.     \\                           \\\
  35.      \\_block #32                 \\\_block #2
  36.       \_block #33                  \\_block #3
  37.                                     \_block #4
  38.  
  39.  (The above example indicates that blocks 2 thru 33 are available for use)
  40.    
  41.    You might wonder why the bitmap starts at block #2 and not block #0?
  42.    I suppose since the first 2 blocks of every disk are not available for
  43.    file storage, AmigaDos simply chooses to ignore the fact that they exist.
  44.    Another reason could be that if the bitmap included blocks zero and one,
  45.    it might be too easy to figure out.. Hmmmmm..
  46.    Actually I think it corresponds to the well documented (ha) Mountlist
  47.    parameter named 'Reserved' which can be used to segment a hard disk into
  48.    more than one logical drive. If you look at it in that light, the first
  49.    bit in the bitmap corresponds to a block number which is the same as the 
  50.    number of 'Reserved' blocks in the Mountlist file.. Have yet to verify
  51.    this on my hard disk but it sounds logical..
  52.  
  53.    In any case, the remainder of the bitmap looks the same e.g. the next
  54.    longword (lo order bit) starts the map for block #34 -- and so on, until
  55.    the map terminates at block #1760...
  56.    
  57.    With the above info, you should be able to figure out how this program
  58.    works.
  59. */
  60.  
  61. /* Bob Bush cpu-73105,1332
  62.    compiled with Lattice 4.0 28-Mar-88 */
  63.  
  64. #include "stdio.h"
  65. #include "string.h"
  66. #include "exec/types.h"
  67. #include "exec/nodes.h"
  68. #include "exec/lists.h"
  69. #include "exec/memory.h"
  70. #include "exec/interrupts.h"
  71. #include "exec/ports.h"
  72. #include "exec/libraries.h"
  73. #include "exec/io.h"
  74. #include "exec/tasks.h"
  75. #include "exec/execbase.h"
  76. #include "exec/devices.h"
  77. #include "devices/trackdisk.h"
  78. #include "libraries/dosextens.h"
  79.  
  80. struct IOStdReq   *mreq  = NULL;
  81. struct MsgPort    *mport,*dosport = NULL;
  82. struct StandardPacket *dpacket ;   /* packet for dos */
  83.  
  84. #define DEVICE_NAME "trackdisk.device"
  85.  
  86. long *buffer,*bitmap,*track = NULL;
  87.  
  88. BOOL formatting = FALSE;
  89. BOOL correct    = FALSE;
  90.  
  91. /* handle ctrl-c, ctrl-d aborts */
  92. brk()
  93. {
  94.     int c; char buf[20];
  95.  
  96.     printf("\n** BREAK **\n");
  97.     if(formatting) {
  98.        printf("Do you really want to abort? (y/n) ");
  99.        gets(buf); c = buf[0];
  100.        if(c == 'y' || c == 'Y') {   
  101.          cleanup(999);
  102.          printf("Warning! disk may be un-useable..\n");
  103.          return(1); }
  104.        else
  105.      return(0);
  106.      }
  107.     return(1);
  108. }
  109.  
  110. main(argc,argv)
  111. int argc;
  112. char *argv[];
  113. {
  114.    static int error,fstat,j,c,err,badcount;
  115.    err = onbreak(&brk);
  116.    badcount = 0;
  117.  
  118.    if(argc < 2) 
  119.       usage_err(0);
  120.    if(!strcmp(argv[1],"?"))
  121.       usage_err(1);
  122.  
  123.  
  124.    if(argc == 3) {
  125.       fix(argv[2]);
  126.       if(!strcmp(argv[2],"-C"))
  127.       correct = TRUE;
  128.       else
  129.       usage_err(1);
  130.    }
  131.  
  132.    if(correct)
  133.        printf("Insert Disk to be corrected in drive 'DF0:'.\n");
  134.    else
  135.        printf("Insert Disk to be formatted in drive 'DF0:'.\n");
  136.    printf("Press Return when ready: ");
  137.  
  138.    c = getchar();
  139.    chkabort();
  140.  
  141.    if(!(mport = (struct MsgPort *)CreatePort("FLOPPY0",0)))
  142.       cleanup(100);
  143.    if(!(dosport = (struct MsgPort *)CreatePort("DOSPORT",0)))
  144.       cleanup(100);
  145.    if(!(mreq = (struct IOStdReq *)CreateStdIO(mport)))
  146.       cleanup(100);
  147.    if(!(dpacket=(struct StandardPacket *)AllocMem(sizeof(struct StandardPacket),
  148.       MEMF_PUBLIC|MEMF_CLEAR)))
  149.       cleanup(100);           
  150.  
  151.  
  152.    if(error = OpenDevice(DEVICE_NAME,0,mreq,0))
  153.     cleanup(1);
  154.    inhibit(TRUE) ;
  155.  
  156.    if(!(bitmap = (long *)AllocMem(512,MEMF_CLEAR | MEMF_CHIP)))
  157.       cleanup(8);
  158.    if(!(buffer = (long *)AllocMem(512,MEMF_CLEAR | MEMF_CHIP)))
  159.       cleanup(8);
  160.    if(!(track = (long *)AllocMem(512 * 11,MEMF_CLEAR | MEMF_CHIP)))
  161.       cleanup(8);
  162.    formatting = TRUE;
  163.  
  164.    if(!correct)
  165.     validate_required();
  166.  
  167. /* format entire disk, building bitmap as we go.. */
  168.  
  169.    if(correct) {
  170.        for(j = 0; j < 160; j++) {
  171.            printf("\rVerify Track # %3ld",j);
  172.              if(!(fstat = verify_track(j))) {
  173.            printf(" -- Bad Track! allocated as used..\n");
  174.            badcount += 11;
  175.              }
  176.              else
  177.             set_track(j);
  178.        }
  179.     }
  180.     else {
  181.        for(j = 0; j < 160; j++) {
  182.            printf("\rFormat Track # %3ld",j);
  183.            format_track(j);
  184.            printf("\rVerify Track # %3ld",j);
  185.              if(!(fstat = verify_track(j))) {
  186.            printf(" -- Bad Track! allocated as used..\n");
  187.            badcount += 11;
  188.            }
  189.            else
  190.           set_track(j);
  191.        }
  192.     }
  193.  
  194. /* init root/bitmap blocks and write to disk.. */
  195.  
  196.    init_root(buffer,argv[1]);
  197.    write_block(880,buffer);
  198.    init_bitmap(bitmap);
  199.    write_block(881,bitmap);
  200.    Update();
  201.    Clear();
  202.    
  203.    mreq->io_Length  = 0;
  204.    mreq->io_Command = TD_MOTOR;   /* turn off motor */
  205.    DoIO(mreq);
  206.  
  207.    printf("\n** Program Completed **\n");
  208.    printf("%ld Bad blocks allocated as used\n",badcount);
  209.    cleanup(0);
  210. }
  211.  
  212. fix(s)
  213. char *s;
  214. {
  215.     s++;
  216.     *s = toupper(*s);
  217. }
  218.  
  219. validate_required()
  220. {
  221.    int fstat;
  222.  
  223.    /* try formatting block 0 */
  224.    set_fbuff(track);
  225.    format_track(0);
  226.    formatting = TRUE;
  227.    if(!(fstat = verify_track(0))) {
  228.     printf("\nUnable to format track #0..disk not useable..\n\n");
  229.     cleanup(100);
  230.    }
  231.    
  232.    /* try formatting root block next */
  233.    format_track(80);
  234.    if(!(fstat = verify_track(80))) {
  235.     printf("\nUnable to format root block..disk not useable..\n\n");
  236.     cleanup(100);
  237.    }
  238. }
  239.  
  240. usage_err(b)
  241. int b;
  242. {
  243.     if(b)
  244.     printf("Command Error\n");
  245.     printf("Usage: bformat volume_name <-c> (assumes df0:)\n");
  246.     exit(0);
  247. }
  248.  
  249. /* mark track as available */
  250.  
  251. set_track(tnum)
  252. int tnum;
  253. {
  254.     int j;
  255.  
  256.     for(j = (tnum * 11); j < (tnum * 11 + 11);j++)
  257.     set_bitmap(j);
  258. }
  259.  
  260.  
  261. /* mark block as available for use */
  262.  
  263. set_bitmap(block)
  264. int block;
  265. {
  266.     int lindex;
  267.     if((block - 2) > -1) {
  268.       lindex = (block - 2) / 32 + 1;
  269.  
  270.       bitmap[lindex] = bitmap[lindex] | (1 << ((block-2) % 32));
  271.     }
  272. }
  273.  
  274. /* mark block as allocated (in use) */
  275.  
  276. clear_bitmap(block)
  277. int block;
  278. {
  279.     int lindex;
  280.     if((block - 2) > -1) {
  281.       lindex = (block - 2) / 32 + 1;
  282.  
  283.       bitmap[lindex] = bitmap[lindex] & (~(1 << ((block-2) % 32)));
  284.     }
  285. }
  286.  
  287. format_track(tnum)
  288. int tnum;
  289. {
  290.    mreq->io_Length = 512 * 11;
  291.    mreq->io_Data = (APTR)track;
  292.    mreq->io_Command = TD_FORMAT;
  293.    mreq->io_Offset = tnum * 11 * 512;
  294.    DoIO(mreq);
  295. }
  296.  
  297. /* verify track with abort on critical tracks */
  298.  
  299. verify_track(tnum)
  300. int tnum;
  301. {
  302.    mreq->io_Length = 512;
  303.    mreq->io_Data = (APTR)buffer;
  304.    mreq->io_Command = CMD_READ;
  305.    mreq->io_Offset = tnum * 11 * 512;
  306.    DoIO(mreq);
  307.    if(mreq->io_Error) {
  308.         if((tnum == 80) || (tnum == 0)) {
  309.        printf("\nUnable to verify critical track # %d \n Aborted..\n");
  310.        exit(100);
  311.         }
  312.     else
  313.        return(0);
  314.    }
  315.    else
  316.         return(1);
  317. }
  318.  
  319. write_block(block,buff)
  320. int block;
  321. long *buff;
  322. {
  323.    mreq->io_Length = 512;
  324.    mreq->io_Data = (APTR)buff;
  325.    mreq->io_Command = CMD_WRITE;
  326.    mreq->io_Offset = block * 512;
  327.    DoIO(mreq);
  328. }
  329.  
  330. Update()
  331. {
  332.    mreq->io_Length = 1;
  333.    mreq->io_Command = CMD_UPDATE;
  334.    DoIO(mreq);
  335. }
  336.  
  337. Clear()
  338. {
  339.    mreq->io_Length = 0;
  340.    mreq->io_Command = CMD_CLEAR;
  341.    DoIO(mreq);
  342.    return(0);
  343. }
  344.  
  345. set_fbuff(buff)
  346. ULONG buff[];
  347. {
  348.    static int j;
  349.  
  350.    for(j = 0; j < 128;j++)
  351.       buff[j] = 0x444f5300; /* fill buffer with ascii 'DOS' */
  352. }
  353.  
  354. init_root(wp,vname) /* build initialized root block */
  355. ULONG wp[];
  356. char *vname;
  357. {
  358.    ULONG check_sum();
  359.  
  360.    static ULONG temp;
  361.    temp = 0;
  362.    zblock(wp);
  363.    wp[0]   = 0x02;         /* type */
  364.    wp[3]   = 0x48;         /* hashtable size */
  365.    wp[78]  = 0xffffffff;   /* 'true' bitmap flag */
  366.    wp[79]  = 0x371;        /* block # of bitmap */
  367.    DateStamp(&wp[105]);    /* datestamp */
  368.    set_name(&wp[108],vname); /* disk name (BCPL) string */
  369.    DateStamp(&wp[121]);    /* datestamp */
  370.    wp[127] = 0x01;         /* secondary type = root */
  371.  
  372.    wp[5] = check_sum(wp); /* create root block checksum */
  373.  
  374. }
  375.  
  376. /* set volume name into root block (BCPL string) */
  377.  
  378. set_name(dest,vname)
  379.  char *dest,*vname;
  380. {
  381.    *dest = (char)strlen(vname);
  382.    dest++;
  383.    while(*vname) {
  384.       *dest = *vname;
  385.       dest++; vname++;
  386.    }
  387. }
  388.  
  389.  
  390. zblock(wp) /* clear buffer to zeros */
  391. ULONG wp[];
  392. {
  393.    static int j;
  394.    for(j = 0; j < 128; j++)
  395.          wp[j] = 0;
  396. }
  397.  
  398. ULONG check_sum(buff) /* checksum= 2's complement of sum of all words in block */
  399.  
  400.    ULONG buff[];
  401. {
  402.    static int j;
  403.    static ULONG cksum;
  404.  
  405.    cksum = 0;
  406.    for(j = 0; j < 128; j++)
  407.          cksum += buff[j];  /* sum all words in block */
  408.    return(-cksum);
  409. }
  410.  
  411. init_bitmap(wp)
  412. ULONG wp[];
  413. {
  414.    ULONG check_sum();
  415.  
  416.    clear_bitmap(880);        /* set as allocated block 880 (root) and */
  417.    clear_bitmap(881);       /*  block 881 (bitmap) */
  418.  
  419.    wp[0] = check_sum(wp);   /* calculate checksum and insert */
  420. }
  421.  
  422. /* Inhibits dos from trying to access drive while we have control. Also puts
  423.    up DF0:BUSY message, causes dos to re-read disk info on termination.. */
  424.  
  425. inhibit(t) 
  426. long t ; /* true -or - false */
  427. {
  428.    struct MsgPort *handler ;
  429.    struct StandardPacket *packet = dpacket ;
  430.  
  431.    handler = (struct MsgPort *)DeviceProc("DF0:") ;
  432.    if (handler == NULL || dosport == NULL)
  433.       return ;
  434.    packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt) ;
  435.    packet->sp_Pkt.dp_Link = &(packet->sp_Msg) ;
  436.    packet->sp_Pkt.dp_Port = dosport ;
  437.    packet->sp_Pkt.dp_Type = ACTION_INHIBIT ;
  438.    packet->sp_Pkt.dp_Arg1 = t ;
  439.    PutMsg(handler, packet) ;
  440.    WaitPort(dosport) ;
  441.    GetMsg(dosport) ;
  442. }
  443.  
  444.  
  445. cleanup(err)
  446. int err;
  447. {
  448.     inhibit(FALSE);
  449.     if(mreq) {
  450.     CloseDevice(mreq);    
  451.     DeleteStdIO(mreq);
  452.     }
  453.     if(mport)
  454.     DeletePort(mport);
  455.     if(dosport)
  456.         DeletePort(dosport);
  457.     if(dpacket)
  458.         FreeMem(dpacket,sizeof(struct StandardPacket));
  459.     if(bitmap)
  460.     FreeMem(bitmap,512);
  461.     if(buffer)
  462.     FreeMem(buffer,512);
  463.     if(track)
  464.     FreeMem(track,512 * 11);
  465.     if(err == 999)
  466.     return(0);
  467.     exit(0);
  468. }    
  469.