home *** CD-ROM | disk | FTP | other *** search
- /* bformat.c */
-
- /* simple program to format drive df0:, creating a bitmap which marks
- bad tracks as 'in use'. Should work for any 3.5" floppy which can hold
- a format on track 0 and 80 (Dos minimum requirements).. I never could
- figure out why Dos didn't do this all by itself.. Should you really have
- to throw out a disk that has one or two lousy tracks? */
-
- /* I've been meaning to write this program for quite a long while but never
- took the time to figure out how AmigaDos stores/manipulates the block
- allocation map (aka bitmap). Well, finally took an evening and threw this
- together. To the best of my determination here is a description of
- the block allocation scheme (for 3.5" floppies anyway..) :
-
- When you format a diskette dos grabs 2 blocks for its own use.
- Block 880 is the Root block. Block 881 (normally on a fresh format) is
- the bitmap which in itself indicates the blocks that are available for use
- or currently in use. Generally, a '1' bit means the corresponding block
- is available. A '0' bit means that the block is in use. This sounds
- relatively simple but the AmigaDos implementation needs some
- explanation.
-
- AmigaDos Block Allocation Map (512 bytes -or- 128 longwords)
- ------------------------------------------------------------
- LongWord Usage
- -------- -----
- 0 location of the block checksum
- 1 first bitmap allocation longword, which breaks down as follows:
-
- hi-order bit (31) lo-order bit (0)
- / /
- | |
- 11111111111111111111111111111111 (32 bit longword)
- \\ \\\
- \\_block #32 \\\_block #2
- \_block #33 \\_block #3
- \_block #4
-
- (The above example indicates that blocks 2 thru 33 are available for use)
-
- You might wonder why the bitmap starts at block #2 and not block #0?
- I suppose since the first 2 blocks of every disk are not available for
- file storage, AmigaDos simply chooses to ignore the fact that they exist.
- Another reason could be that if the bitmap included blocks zero and one,
- it might be too easy to figure out.. Hmmmmm..
- Actually I think it corresponds to the well documented (ha) Mountlist
- parameter named 'Reserved' which can be used to segment a hard disk into
- more than one logical drive. If you look at it in that light, the first
- bit in the bitmap corresponds to a block number which is the same as the
- number of 'Reserved' blocks in the Mountlist file.. Have yet to verify
- this on my hard disk but it sounds logical..
-
- In any case, the remainder of the bitmap looks the same e.g. the next
- longword (lo order bit) starts the map for block #34 -- and so on, until
- the map terminates at block #1760...
-
- With the above info, you should be able to figure out how this program
- works.
- */
-
- /* Bob Bush cpu-73105,1332
- compiled with Lattice 4.0 28-Mar-88 */
-
- #include "stdio.h"
- #include "string.h"
- #include "exec/types.h"
- #include "exec/nodes.h"
- #include "exec/lists.h"
- #include "exec/memory.h"
- #include "exec/interrupts.h"
- #include "exec/ports.h"
- #include "exec/libraries.h"
- #include "exec/io.h"
- #include "exec/tasks.h"
- #include "exec/execbase.h"
- #include "exec/devices.h"
- #include "devices/trackdisk.h"
- #include "libraries/dosextens.h"
-
- struct IOStdReq *mreq = NULL;
- struct MsgPort *mport,*dosport = NULL;
- struct StandardPacket *dpacket ; /* packet for dos */
-
- #define DEVICE_NAME "trackdisk.device"
-
- long *buffer,*bitmap,*track = NULL;
-
- BOOL formatting = FALSE;
- BOOL correct = FALSE;
-
- /* handle ctrl-c, ctrl-d aborts */
- brk()
- {
- int c; char buf[20];
-
- printf("\n** BREAK **\n");
- if(formatting) {
- printf("Do you really want to abort? (y/n) ");
- gets(buf); c = buf[0];
- if(c == 'y' || c == 'Y') {
- cleanup(999);
- printf("Warning! disk may be un-useable..\n");
- return(1); }
- else
- return(0);
- }
- return(1);
- }
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- static int error,fstat,j,c,err,badcount;
- err = onbreak(&brk);
- badcount = 0;
-
- if(argc < 2)
- usage_err(0);
- if(!strcmp(argv[1],"?"))
- usage_err(1);
-
-
- if(argc == 3) {
- fix(argv[2]);
- if(!strcmp(argv[2],"-C"))
- correct = TRUE;
- else
- usage_err(1);
- }
-
- if(correct)
- printf("Insert Disk to be corrected in drive 'DF0:'.\n");
- else
- printf("Insert Disk to be formatted in drive 'DF0:'.\n");
- printf("Press Return when ready: ");
-
- c = getchar();
- chkabort();
-
- if(!(mport = (struct MsgPort *)CreatePort("FLOPPY0",0)))
- cleanup(100);
- if(!(dosport = (struct MsgPort *)CreatePort("DOSPORT",0)))
- cleanup(100);
- if(!(mreq = (struct IOStdReq *)CreateStdIO(mport)))
- cleanup(100);
- if(!(dpacket=(struct StandardPacket *)AllocMem(sizeof(struct StandardPacket),
- MEMF_PUBLIC|MEMF_CLEAR)))
- cleanup(100);
-
-
- if(error = OpenDevice(DEVICE_NAME,0,mreq,0))
- cleanup(1);
- inhibit(TRUE) ;
-
- if(!(bitmap = (long *)AllocMem(512,MEMF_CLEAR | MEMF_CHIP)))
- cleanup(8);
- if(!(buffer = (long *)AllocMem(512,MEMF_CLEAR | MEMF_CHIP)))
- cleanup(8);
- if(!(track = (long *)AllocMem(512 * 11,MEMF_CLEAR | MEMF_CHIP)))
- cleanup(8);
- formatting = TRUE;
-
- if(!correct)
- validate_required();
-
- /* format entire disk, building bitmap as we go.. */
-
- if(correct) {
- for(j = 0; j < 160; j++) {
- printf("\rVerify Track # %3ld",j);
- if(!(fstat = verify_track(j))) {
- printf(" -- Bad Track! allocated as used..\n");
- badcount += 11;
- }
- else
- set_track(j);
- }
- }
- else {
- for(j = 0; j < 160; j++) {
- printf("\rFormat Track # %3ld",j);
- format_track(j);
- printf("\rVerify Track # %3ld",j);
- if(!(fstat = verify_track(j))) {
- printf(" -- Bad Track! allocated as used..\n");
- badcount += 11;
- }
- else
- set_track(j);
- }
- }
-
- /* init root/bitmap blocks and write to disk.. */
-
- init_root(buffer,argv[1]);
- write_block(880,buffer);
- init_bitmap(bitmap);
- write_block(881,bitmap);
- Update();
- Clear();
-
- mreq->io_Length = 0;
- mreq->io_Command = TD_MOTOR; /* turn off motor */
- DoIO(mreq);
-
- printf("\n** Program Completed **\n");
- printf("%ld Bad blocks allocated as used\n",badcount);
- cleanup(0);
- }
-
- fix(s)
- char *s;
- {
- s++;
- *s = toupper(*s);
- }
-
- validate_required()
- {
- int fstat;
-
- /* try formatting block 0 */
- set_fbuff(track);
- format_track(0);
- formatting = TRUE;
- if(!(fstat = verify_track(0))) {
- printf("\nUnable to format track #0..disk not useable..\n\n");
- cleanup(100);
- }
-
- /* try formatting root block next */
- format_track(80);
- if(!(fstat = verify_track(80))) {
- printf("\nUnable to format root block..disk not useable..\n\n");
- cleanup(100);
- }
- }
-
- usage_err(b)
- int b;
- {
- if(b)
- printf("Command Error\n");
- printf("Usage: bformat volume_name <-c> (assumes df0:)\n");
- exit(0);
- }
-
- /* mark track as available */
-
- set_track(tnum)
- int tnum;
- {
- int j;
-
- for(j = (tnum * 11); j < (tnum * 11 + 11);j++)
- set_bitmap(j);
- }
-
-
- /* mark block as available for use */
-
- set_bitmap(block)
- int block;
- {
- int lindex;
- if((block - 2) > -1) {
- lindex = (block - 2) / 32 + 1;
-
- bitmap[lindex] = bitmap[lindex] | (1 << ((block-2) % 32));
- }
- }
-
- /* mark block as allocated (in use) */
-
- clear_bitmap(block)
- int block;
- {
- int lindex;
- if((block - 2) > -1) {
- lindex = (block - 2) / 32 + 1;
-
- bitmap[lindex] = bitmap[lindex] & (~(1 << ((block-2) % 32)));
- }
- }
-
- format_track(tnum)
- int tnum;
- {
- mreq->io_Length = 512 * 11;
- mreq->io_Data = (APTR)track;
- mreq->io_Command = TD_FORMAT;
- mreq->io_Offset = tnum * 11 * 512;
- DoIO(mreq);
- }
-
- /* verify track with abort on critical tracks */
-
- verify_track(tnum)
- int tnum;
- {
- mreq->io_Length = 512;
- mreq->io_Data = (APTR)buffer;
- mreq->io_Command = CMD_READ;
- mreq->io_Offset = tnum * 11 * 512;
- DoIO(mreq);
- if(mreq->io_Error) {
- if((tnum == 80) || (tnum == 0)) {
- printf("\nUnable to verify critical track # %d \n Aborted..\n");
- exit(100);
- }
- else
- return(0);
- }
- else
- return(1);
- }
-
- write_block(block,buff)
- int block;
- long *buff;
- {
- mreq->io_Length = 512;
- mreq->io_Data = (APTR)buff;
- mreq->io_Command = CMD_WRITE;
- mreq->io_Offset = block * 512;
- DoIO(mreq);
- }
-
- Update()
- {
- mreq->io_Length = 1;
- mreq->io_Command = CMD_UPDATE;
- DoIO(mreq);
- }
-
- Clear()
- {
- mreq->io_Length = 0;
- mreq->io_Command = CMD_CLEAR;
- DoIO(mreq);
- return(0);
- }
-
- set_fbuff(buff)
- ULONG buff[];
- {
- static int j;
-
- for(j = 0; j < 128;j++)
- buff[j] = 0x444f5300; /* fill buffer with ascii 'DOS' */
- }
-
- init_root(wp,vname) /* build initialized root block */
- ULONG wp[];
- char *vname;
- {
- ULONG check_sum();
-
- static ULONG temp;
- temp = 0;
- zblock(wp);
- wp[0] = 0x02; /* type */
- wp[3] = 0x48; /* hashtable size */
- wp[78] = 0xffffffff; /* 'true' bitmap flag */
- wp[79] = 0x371; /* block # of bitmap */
- DateStamp(&wp[105]); /* datestamp */
- set_name(&wp[108],vname); /* disk name (BCPL) string */
- DateStamp(&wp[121]); /* datestamp */
- wp[127] = 0x01; /* secondary type = root */
-
- wp[5] = check_sum(wp); /* create root block checksum */
-
- }
-
- /* set volume name into root block (BCPL string) */
-
- set_name(dest,vname)
- char *dest,*vname;
- {
- *dest = (char)strlen(vname);
- dest++;
- while(*vname) {
- *dest = *vname;
- dest++; vname++;
- }
- }
-
-
- zblock(wp) /* clear buffer to zeros */
- ULONG wp[];
- {
- static int j;
- for(j = 0; j < 128; j++)
- wp[j] = 0;
- }
-
- ULONG check_sum(buff) /* checksum= 2's complement of sum of all words in block */
-
- ULONG buff[];
- {
- static int j;
- static ULONG cksum;
-
- cksum = 0;
- for(j = 0; j < 128; j++)
- cksum += buff[j]; /* sum all words in block */
- return(-cksum);
- }
-
- init_bitmap(wp)
- ULONG wp[];
- {
- ULONG check_sum();
-
- clear_bitmap(880); /* set as allocated block 880 (root) and */
- clear_bitmap(881); /* block 881 (bitmap) */
-
- wp[0] = check_sum(wp); /* calculate checksum and insert */
- }
-
- /* Inhibits dos from trying to access drive while we have control. Also puts
- up DF0:BUSY message, causes dos to re-read disk info on termination.. */
-
- inhibit(t)
- long t ; /* true -or - false */
- {
- struct MsgPort *handler ;
- struct StandardPacket *packet = dpacket ;
-
- handler = (struct MsgPort *)DeviceProc("DF0:") ;
- if (handler == NULL || dosport == NULL)
- return ;
- packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt) ;
- packet->sp_Pkt.dp_Link = &(packet->sp_Msg) ;
- packet->sp_Pkt.dp_Port = dosport ;
- packet->sp_Pkt.dp_Type = ACTION_INHIBIT ;
- packet->sp_Pkt.dp_Arg1 = t ;
- PutMsg(handler, packet) ;
- WaitPort(dosport) ;
- GetMsg(dosport) ;
- }
-
-
- cleanup(err)
- int err;
- {
- inhibit(FALSE);
- if(mreq) {
- CloseDevice(mreq);
- DeleteStdIO(mreq);
- }
- if(mport)
- DeletePort(mport);
- if(dosport)
- DeletePort(dosport);
- if(dpacket)
- FreeMem(dpacket,sizeof(struct StandardPacket));
- if(bitmap)
- FreeMem(bitmap,512);
- if(buffer)
- FreeMem(buffer,512);
- if(track)
- FreeMem(track,512 * 11);
- if(err == 999)
- return(0);
- exit(0);
- }
-