home *** CD-ROM | disk | FTP | other *** search
- /* BitMap.c - BitMap support routines */
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* |_o_o|\\ Copyright (c) 1987 The Software Distillery. All Rights Reserved */
- /* |. o.| || This program may not be distributed without the permission of */
- /* | . | || the author. BBS: */
- /* | o | || John Toebes Dave Baker Jim Cooper (919)-471-6436 */
- /* | . |// */
- /* ====== */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- #include "handler.h"
-
- #define BMSIZE ((((global->dskenv.de_numblks)-(global->dskenv.de_reservedblks))/32)+1)
-
- int AllocBitMap(global)
- GLOBAL global;
- {
- struct RootBlock *tmpRoot;
- char *tmpblk;
- register int i, size = BMSIZE*4;
-
- /* allocate memory for the bit map in long words */
- if ((global->bitmap.bm_bitmap = (ULONG *)
- AllocMem(size,MEMF_PUBLIC|MEMF_CLEAR))==NULL) {
- BUG(("AllocBitMap Failed\n"));
- return(NULL);
- }
- BUG(("AllocBitMap - root %ld - bitmap %08lx - size %ld\n",
- global->Root,global->bitmap.bm_bitmap,BMSIZE));
- tmpRoot = (struct RootBlock *)GetBlock(global,global->Root);
- if (tmpRoot->rb_BitMapFlag == 0)
- {
- /* OH NO! The bitmap is INVALID!! Let's call the disk validator */
- return(NULL);
- }
-
- for (i=0; (i<BITMAPSIZE) && (tmpRoot->rb_BitMapPages[i]); i++)
- {
- tmpblk = GetBlock(global,tmpRoot->rb_BitMapPages[i]);
- memcpy((char *)&global->bitmap.bm_bitmap[i*127],&tmpblk[4],min(508,size));
- size -= 508;
- }
- global->bitmap.bm_blocks = i;
- return(-1);
- }
-
- int FreeBitMap(global)
- GLOBAL global;
- {
- if (global->bitmap.bm_bitmap) {
- FreeMem((char *)global->bitmap.bm_bitmap,(BMSIZE*4));
- global->bitmap.bm_blocks = 0;
- global->bitmap.bm_dirty = 0;
- global->bitmap.bm_bitmap = NULL;
- return(-1);
- }
- return(NULL);
- }
-
- int CountBlocks(global)
- GLOBAL global;
- {
- register int block, bit, count = 0;
-
- /* count number of used blocks. bit is 0 if used, 1 if free */
- for (block=0; block<BMSIZE; block++)
- for (bit=0; bit<32; bit++) {
- if ((block == BMSIZE-1) && (bit > 29)) continue;
- if (!(global->bitmap.bm_bitmap[block] & (1<<bit))) {
- count++;
- }
- }
- return(count);
- }
-
- void DoCheckSum(global,block)
- GLOBAL global;
- char *block;
- {
- struct DirBlock *dblock;
- register ULONG *ptr;
- register ULONG checksum;
-
- dblock = (struct DirBlock *)block;
- dblock->db_CheckSum = checksum = 0;
- for (ptr = (ULONG *)dblock; ptr < (ULONG *)(dblock+1);)
- checksum -= *ptr++;
- dblock->db_CheckSum = checksum;
- }
-
- void WriteBitMap(global)
- GLOBAL global;
- {
- register int i, j, block;
- long oldbitmap;
- KEY key;
- struct RootBlock *tmproot;
- ULONG *tmpblk;
- int size = BMSIZE*4;
-
- if (global->bitmap.bm_dirty)
- {
- tmproot = (struct RootBlock *)ModBlock(global,global->Root);
- if (tmproot == NULL)
- {
- BUG(("Unable to locate the Root block\n"));
- return;
- }
-
- /* Now update the root block to reset the bitmap valid flag */
- oldbitmap = tmproot->rb_BitMapFlag;
- tmproot->rb_BitMapFlag = 0;
-
- /* Next we need to force the root block out to disk. Note that we can */
- /* actually get away with not doing this IF it was already invalid on */
- /* disk */
- if (oldbitmap == NULL)
- {
- /* Ok, so it hasn't been updated - put it out there */
- FlushOne(global, FindBuffer(global,global->Root,0));
- }
-
- /* Next we get to allocate a new bitmap */
- for (block=0; block<global->bitmap.bm_blocks; block++)
- {
- #if 0
- key = AllocateBlock(global,global->Root,0);
- if (key == 0)
- {
- /* For some reason there was no room on the disk so we can't put */
- /* the bitmap onto the disk. Gee, what's a person to do. This */
- /* can occur with the standard file handler. */
- BUG(("No room to put bitmap on disk\n"));
- return;
- }
-
- #endif
- /* I know its not kosher to do this brute force, but I'd like to */
- /* see it WORK before I get fancy */
- tmproot = (struct RootBlock *)GetBlock(global,global->Root);
- if (tmproot == NULL)
- {
- BUG(("Unable to get root block\n"));
- return;
- }
-
- key = tmproot->rb_BitMapPages[block];
- i = FindBuffer(global, key, 0); /* do not read from disk */
- if (i == -1)
- {
- /* Some catastrophic error finding a buffer for the bitmap */
- /* Just propagate the error. However this error is quite */
- /* unlikely as we are not asking for any I/O */
- BUG(("How can this happen? can't find buffer for bitmap\n"));
- return;
- }
- global->blkbuf[i].bb_used = ST_BITMAP; /* Prevent the checksum */
- global->blkbuf[i].bb_dirty = 1; /* make sure it gets written */
- tmpblk = (ULONG *)global->blkbuf[i].bb_blk;
-
- /* clear the destination block (in case we don't use the whole thing) */
- memset((char *)tmpblk,0,sizeof(struct DataBlock));
-
- /* now copy the bitmap to the destination */
- memcpy((char *)&tmpblk[1],
- (char *)&global->bitmap.bm_bitmap[block*127],
- min(508, size));
-
- /* Calculate the checksum for the bitmap block we just created */
- for (j=min(127, size/4); j; j--)
- {
- tmpblk[0] -= tmpblk[j];
- }
-
- /* And cause it to be output IMMEDIATELY */
- FlushOne(global, i);
-
- size -= 508;
- }
-
- global->bitmap.bm_dirty = 0;
- tmproot = (struct RootBlock *)ModBlock(global, global->Root);
- if (tmproot == NULL)
- {
- BUG(("Unable to get Root block again!\n"));
- return;
- }
- tmproot->rb_BitMapFlag = -1;
- FlushOne(global, FindBuffer(global,global->Root,0));
- }
- }
-
-
- void SetBlock(global,key)
- GLOBAL global;
- KEY key;
- {
- ULONG bmindex;
- ULONG bmbit;
-
- bmindex = ((key-global->dskenv.de_reservedblks) >> 5);
- bmbit = ((key-global->dskenv.de_reservedblks) & 0x1f);
- if (!((global->bitmap.bm_bitmap[bmindex]) & (1<<bmbit)))
- {
- request(global, REQ_GENERAL, "Attempt to allocate used block");
- }
- (global->bitmap.bm_bitmap[bmindex]) &= ~(1<<bmbit);
- global->bitmap.bm_dirty = 1;
- }
-
- void FreeBlock(global,key)
- GLOBAL global;
- KEY key;
- {
- ULONG bmindex;
- ULONG bmbit;
-
- BUG(("FreeBlock: %ld\n", key));
- bmindex = ((key-global->dskenv.de_reservedblks) >> 5);
- bmbit = ((key-global->dskenv.de_reservedblks) & 0x1f);
- if ((global->bitmap.bm_bitmap[bmindex]) & (1<<bmbit))
- {
- request(global, REQ_GENERAL, "Attempt to free unused block");
- }
- (global->bitmap.bm_bitmap[bmindex]) |= (1<<bmbit);
- global->bitmap.bm_dirty = 1;
- }
-
- KEY AllocateBlock(global,key,type)
- GLOBAL global;
- KEY key;
- int type;
- {
- KEY trkstart, newkey = 0;
- ULONG bmindex;
- ULONG bmbit;
- register ULONG bmsize = BMSIZE;
-
- if (!(global->bitmap.bm_bitmap))
- AllocBitMap(global);
-
- trkstart = (key - (key - ((key / global->dskenv.de_blkspertrk) * global->dskenv.de_blkspertrk)));
- bmindex = ((trkstart - global->dskenv.de_reservedblks) >> 5);
- bmbit = ((trkstart - global->dskenv.de_reservedblks) & 0x1f);
-
- while (bmindex<bmsize) {
- if (global->bitmap.bm_bitmap[bmindex] & (1<<bmbit)) break;
- if (++bmbit > 31) bmbit = 0, bmindex++;
- }
- if (bmindex == bmsize) {
- bmbit=0; bmindex=0;
- while (bmindex<bmsize) {
- if (global->bitmap.bm_bitmap[bmindex] & (1<<bmbit)) break;
- if (++bmbit > 31) bmbit = 0, bmindex++;
- }
- if (bmindex == bmsize) {
- request(global,REQ_GENERAL,"Disk FULL on volume");
- return(newkey);
- }
- }
- newkey = (((bmindex)<<5)+bmbit+global->dskenv.de_reservedblks);
- SetBlock(global, newkey);
- /* Force the buffer to be allocated without reading from disk */
- FindBuffer(global, newkey, 0); /* Don't read it in from disk */
-
- BUG(("AllocateBlock: Key %ld\n", newkey));
-
- if ((newkey < global->dskenv.de_reservedblks) ||
- (newkey == global->Root) ||
- (newkey > global->dskenv.de_numblks))
- {
- BUG(("Allocated block %ld out of range %ld-%ld\n", newkey, global->dskenv.de_reservedblks,global->dskenv.de_numblks));
- request(global, REQ_GENERAL, "Key out of range on volume");
- }
- return(newkey);
- }
-