home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff236.lzh / DiskHandler / databuff.c < prev    next >
C/C++ Source or Header  |  1989-08-09  |  7KB  |  228 lines

  1. /* databuff.c - Buffer management routines */
  2.  
  3. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  4. /* |_o_o|\\ Copyright (c) 1988 The Software Distillery.  All Rights Reserved */
  5. /* |. o.| || This program may not be distributed without the permission of   */
  6. /* | .  | || the authors:                             BBS: (919) 481-6436    */
  7. /* | o  | ||   John Toebes     John Mainwaring    Jim Cooper                 */
  8. /* |  . |//    Bruce Drake     Gordon Keener      Dave Baker                 */
  9. /* ======                                                                    */
  10. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  11.  
  12. /* Buffer management routines : */
  13. /* ModBlock GetBlock */
  14. /* FindBuffer AllocBuffers FreeBuffers FlushBuffers FlushOne */
  15.  
  16. #include "handler.h"
  17.  
  18. char *GetBlock(global, key)
  19. GLOBAL global;
  20. KEY key;
  21. {
  22. int i;
  23.  
  24.    i = FindBuffer(global, key, 1);
  25.  
  26.    if (i == -1)
  27.       return(NULL);
  28.  
  29.    BUG(("GetBlock: Key %ld Buff %08lx\n", key, global->blkbuf[i].bb_blk));
  30.    return(global->blkbuf[i].bb_blk);
  31. }
  32.  
  33. char *ModBlock(global, key)
  34. GLOBAL global;
  35. KEY key;
  36. {
  37. int i;
  38.  
  39.    /* Make sure we have the rights to write to the disk */
  40.    if (global->diskstate != ID_VALIDATED)
  41.       {
  42.       BUG(("ModBlock - Write protected disk\n"));
  43.       global->pkt->dp_Res1 = DOS_FALSE;
  44.       global->pkt->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
  45.       return(NULL);
  46.       }
  47.  
  48.    /* Locate the block in a buffer */
  49.    i = FindBuffer(global, key, 1);
  50.  
  51.    /* Gee, it wasn't found, just return an error */
  52.    if (i == -1)
  53.       return(NULL);
  54.  
  55.    /* Mark it as having been touched so we flush it later */
  56.    global->blkbuf[i].bb_dirty = 1;
  57.  
  58.    BUG(("ModBlock: Key %ld Buff %08lx\n", key, global->blkbuf[i].bb_blk));
  59.    return(global->blkbuf[i].bb_blk);
  60. }
  61.  
  62. int FindBuffer(global, key, readin)
  63. register GLOBAL global;
  64. KEY key;
  65. int readin;
  66. {
  67. register int i;
  68. int num;
  69. struct BlockBuffer *tmpglob;
  70.  
  71.    /* First pass, go through and see if it is already in a buffer */
  72.    for (i = 0; i< global->dskenv.de_numbufs; i++)
  73.       {
  74.       if (global->blkbuf[i].bb_key == key &&
  75.           global->blkbuf[i].bb_used)
  76.          {
  77.          if (global->blkbuf[i].bb_priority < 0xff)
  78.             global->blkbuf[i].bb_priority++;
  79.          return(i);
  80.          }
  81.       }
  82.  
  83.    /* For some reason it wasn't in a buffer already (imagine that).  So we  */
  84.    /* want to go through and decrement all the priorities of the buffers    */
  85.    /* and select a candidate for flushing to hold our new block.  Note that */
  86.    /* an empty buffer is assumed to have a priority of 0 while a buffer in  */
  87.    /* use will never be decremented below 1                                 */
  88.    tmpglob = &global->blkbuf[0];
  89.    num = 0;
  90.    for (i = 0; i < global->dskenv.de_numbufs; i++)
  91.       {
  92.       if (global->blkbuf[i].bb_used &&
  93.           (global->blkbuf[i].bb_priority > 1))
  94.          global->blkbuf[i].bb_priority--;
  95.  
  96.       if (global->blkbuf[i].bb_priority < tmpglob->bb_priority)
  97.          {
  98.          tmpglob = &global->blkbuf[i];
  99.          num = i;
  100.          }
  101.       }
  102.  
  103.    /* Now tmpglob points to our new buffer.  Empty it out if necessary */
  104.    FlushOne(global, num);
  105.  
  106.    /* Mark it for the new buffer that we want to use it as */
  107.    tmpglob->bb_used = 1;
  108.    tmpglob->bb_key = key;
  109.    tmpglob->bb_priority = global->dskenv.de_numbufs;
  110.    tmpglob->bb_dirty = 0;   /* Hopefully FlushOne reset it but who knows */
  111.  
  112.    /* Did they ask us to read it in? */
  113.    if (readin)
  114.       {
  115.       if (ReadPhy(global, tmpglob->bb_blk, key))
  116.          {
  117.          BUG(("Failure reading in key %ld\n", key));
  118.          tmpglob->bb_used = 0;
  119.          tmpglob->bb_key = -1;
  120.          tmpglob->bb_priority = 0;
  121.          num = -1;  /* indicate the failure */
  122.          }
  123.       }
  124.  
  125.    return(num);
  126. }
  127. void FreeBlkBuffs(global)
  128. GLOBAL global;
  129. {
  130.     BUG(("FreeBlkBuffs\n"));
  131.     FreeMem((char *)global->blkbuf,((sizeof(struct BlockBuffer))*
  132.                                    (global->dskenv.de_numbufs)));
  133.     global->blkbuf = NULL;
  134. }
  135.  
  136. int AllocBlkBuffs(global, newsize)
  137. GLOBAL global;
  138. int newsize;    
  139. {
  140.     struct BlockBuffer *tmpbuff;
  141.     int     i;
  142.  
  143.     BUG(("AllocBlkBuffs size:%ld\n",newsize));
  144.     if ((tmpbuff = (struct BlockBuffer *)AllocMem(((sizeof(struct BlockBuffer))
  145.                    * newsize),(MEMF_PUBLIC | MEMF_CLEAR)))== NULL){  
  146.          BUG(("AllocBlkBuffs Failed\n")); 
  147.          return(0);
  148.     }
  149.     /* successfully allocated copy stuff over and free old */
  150.     if (global->blkbuf){
  151.         for(i=0;i < (global->dskenv.de_numbufs);i++){    
  152.           if (i < newsize){ 
  153.             tmpbuff[i].bb_blk = global->blkbuf[i].bb_blk;
  154.           }
  155.           if (i >= newsize){
  156.             FreeMem(global->blkbuf[i].bb_blk,
  157.                     ((global->dskenv.de_sizeblock) * BYTESPERLONG));
  158.           }
  159.         }  
  160.         FreeBlkBuffs(global);   
  161.     }
  162.     BUG(("Allocated blk buffs at:%08lx\n",tmpbuff));
  163.     /* allocate memory for data blocks */
  164.     for(i=0;i < newsize;i++){    
  165.        if (tmpbuff[i].bb_blk == NULL){
  166.           if((tmpbuff[i].bb_blk = (char *)
  167.              AllocMem(((global->dskenv.de_sizeblock) * BYTESPERLONG),
  168.                         global->dskenv.de_membuftype))==NULL){
  169.              /* we will loose some bytes here for now */
  170.              global->dskenv.de_numbufs = i;
  171.              return(NULL);
  172.           }
  173.        }
  174.        tmpbuff[i].bb_key = -1;
  175.     }
  176.     global->blkbuf = tmpbuff;
  177.     global->dskenv.de_numbufs = newsize;
  178.     return(-1);
  179. }
  180.  
  181. void FlushOne(global, num)
  182. GLOBAL global;
  183. int num;
  184. {
  185.    /* Does this buffer need to be written out to disk ? */
  186.    if (global->blkbuf[num].bb_dirty &&
  187.        global->blkbuf[num].bb_used)
  188.       {
  189.       /* Ok, see if it needs to be checksummed */
  190.       if (global->blkbuf[num].bb_used != ST_BITMAP)
  191.           DoCheckSum(global, global->blkbuf[num].bb_blk);
  192.  
  193.       /* At last we get to write out the block */
  194.       while(WritePhy(global,
  195.                      global->blkbuf[num].bb_blk, global->blkbuf[num].bb_key))
  196.          {
  197.          if (!request(global, REQ_ERROR, NULL))
  198.             break;
  199.          ResetDrive(global);
  200.          }
  201.       }
  202.  
  203.    /* Now we need to reset it so it doesn't get written out again */
  204.    global->blkbuf[num].bb_dirty = 0;
  205.  
  206. }
  207.  
  208. void FlushBuffers(global, purge)
  209. GLOBAL global;
  210. int purge;
  211. {
  212. register int i;
  213.  
  214.    for (i = 0; i < global->dskenv.de_numbufs; i++)
  215.       {
  216.       FlushOne(global, i);
  217.  
  218.       /* Did they want us to forget about when we are done ? */
  219.       if (purge)
  220.          {
  221.          /* If we don't want the buffer any more we need to zap it */
  222.          global->blkbuf[i].bb_used = 0;
  223.          global->blkbuf[i].bb_key = -1;
  224.          global->blkbuf[i].bb_priority = 0;
  225.          }
  226.       }
  227. }
  228.