⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blockio.c

📁 开源DOS的C代码源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************/
/*                                                              */
/*                          blockio.c                           */
/*                            DOS-C                             */
/*                                                              */
/*      Block cache functions and device driver interface       */
/*                                                              */
/*                      Copyright (c) 1995                      */
/*                      Pasquale J. Villani                     */
/*                      All Rights Reserved                     */
/*                                                              */
/* This file is part of DOS-C.                                  */
/*                                                              */
/* DOS-C is free software; you can redistribute it and/or       */
/* modify it under the terms of the GNU General Public License  */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version.                    */
/*                                                              */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of   */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See    */
/* the GNU General Public License for more details.             */
/*                                                              */
/* You should have received a copy of the GNU General Public    */
/* License along with DOS-C; see the file COPYING.  If not,     */
/* write to the Free Software Foundation, 675 Mass Ave,         */
/* Cambridge, MA 02139, USA.                                    */
/*                                                              */
/****************************************************************/

#include "portab.h"
#include "globals.h"

#ifdef VERSION_STRINGS
static BYTE *blockioRcsId =
    "$Id: blockio.c,v 1.31 2004/04/20 18:43:03 bartoldeman Exp $";
#endif

#define b_next(bp) ((struct buffer FAR *)(MK_FP(FP_SEG(bp), bp->b_next)))
#define b_prev(bp) ((struct buffer FAR *)(MK_FP(FP_SEG(bp), bp->b_prev)))
#define bufptr(fbp) ((struct buffer FAR *)(MK_FP(FP_SEG(bp), fbp)))

/************************************************************************/
/*                                                                      */
/*                      block cache routines                            */
/*                                                                      */
/************************************************************************/
/* #define DISPLAY_GETBLOCK */

STATIC BOOL flush1(struct buffer FAR * bp);

/*
    this searches the buffer list for the given disk/block.
    
    returns:
    a far pointer to the buffer.

    If the buffer is found the UNCACHE bit is not set and else it is set.
        
    new:
        upper layer may set UNCACHE attribute
        UNCACHE buffers are recycled first.
        intended to be used for full sector reads into application buffer
        resets UNCACHE upon a "HIT" -- so then this buffer will not be
        recycled anymore.
*/

STATIC void move_buffer(struct buffer FAR *bp, size_t firstbp)
{
  /* connect bp->b_prev and bp->b_next */
  b_next(bp)->b_prev = bp->b_prev;
  b_prev(bp)->b_next = bp->b_next;

  /* insert bp between firstbp and firstbp->b_prev */
  bp->b_prev = bufptr(firstbp)->b_prev;
  bp->b_next = firstbp;
  b_next(bp)->b_prev = FP_OFF(bp);
  b_prev(bp)->b_next = FP_OFF(bp);
}

STATIC struct buffer FAR *searchblock(ULONG blkno, COUNT dsk)
{
  int fat_count = 0;
  struct buffer FAR *bp;
  size_t lastNonFat = 0;
  size_t uncacheBuf = 0;
  seg bufseg = FP_SEG(firstbuf);
  size_t firstbp = FP_OFF(firstbuf);

#ifdef DISPLAY_GETBLOCK
  printf("[searchblock %d, blk %ld, buf ", dsk, blkno);
#endif

  /* Search through buffers to see if the required block  */
  /* is already in a buffer                               */

  bp = MK_FP(bufseg, firstbp);
  do
  {
    if ((bp->b_blkno == blkno) &&
        (bp->b_flag & BFR_VALID) && (bp->b_unit == dsk))
    {
      /* found it -- rearrange LRU links      */
#ifdef DISPLAY_GETBLOCK
      printf("HIT %04x:%04x]\n", FP_SEG(bp), FP_OFF(bp));
#endif
      bp->b_flag &= ~BFR_UNCACHE;  /* reset uncache attribute */
      if (FP_OFF(bp) != firstbp)
      {
        *(UWORD *)&firstbuf = FP_OFF(bp);
        move_buffer(bp, firstbp);
      }
      return bp;
    }

    if (bp->b_flag & BFR_UNCACHE)
      uncacheBuf = FP_OFF(bp);

    if (bp->b_flag & BFR_FAT)
      fat_count++;
    else
      lastNonFat = FP_OFF(bp);
    bp = b_next(bp);
  } while (FP_OFF(bp) != firstbp);

  /*
     now take either the last buffer in chain (not used recently)
     or, if we are low on FAT buffers, the last non FAT buffer
   */

  if (uncacheBuf)
  {
    bp = bufptr(uncacheBuf);
  }
  else if (bp->b_flag & BFR_FAT && fat_count < 3 && lastNonFat)
  {
    bp = bufptr(lastNonFat);
  }
  else
  {
    bp = b_prev(bufptr(firstbp));
  }

  bp->b_flag |= BFR_UNCACHE;  /* set uncache attribute */

#ifdef DISPLAY_GETBLOCK
  printf("MISS, replace %04x:%04x]\n", FP_SEG(bp), FP_OFF(bp));
#endif

  if (FP_OFF(bp) != firstbp)          /* move to front */
  {
    move_buffer(bp, firstbp);
    *(UWORD *)&firstbuf = FP_OFF(bp);
  }
  return bp;
}

BOOL DeleteBlockInBufferCache(ULONG blknolow, ULONG blknohigh, COUNT dsk, int mode)
{
  struct buffer FAR *bp = firstbuf;
        
  /* Search through buffers to see if the required block  */
  /* is already in a buffer                               */

  do
  {
    if (blknolow <= bp->b_blkno &&
        bp->b_blkno <= blknohigh &&
        (bp->b_flag & BFR_VALID) && (bp->b_unit == dsk))
    {
      if (mode == XFR_READ)
        flush1(bp);
      else
        bp->b_flag = 0;
    }
    bp = b_next(bp);
  }
  while (FP_OFF(bp) != FP_OFF(firstbuf));

  return FALSE;
}

#if TOM
void dumpBufferCache(void)
{
  struct buffer FAR *bp = firstbuf;
  int printed = 0;

  /* Search through buffers to see if the required block  */
  /* is already in a buffer                               */

  do
  {
    printf("%8lx %02x ", bp->b_blkno, bp->b_flag);
    if (++printed % 6 == 0)
      printf("\n");
    bp = b_next(bp);
  }
  while (FP_OFF(bp) != FP_OFF(firstbuf));
  printf("\n");
}
#endif
/*                                                                      */
/*      Return the address of a buffer structure containing the         */
/*      requested block.                                                */
/*      if overwrite is set, then no need to read first                 */
/*                                                                      */
/*      returns:                                                        */
/*              requested block with data                               */
/*      failure:                                                        */
/*              returns NULL                                            */
/*                                                                      */
struct buffer FAR *getblk(ULONG blkno, COUNT dsk, BOOL overwrite)
{
  /* Search through buffers to see if the required block  */
  /* is already in a buffer                               */

  struct buffer FAR *bp = searchblock(blkno, dsk);

  if (!(bp->b_flag & BFR_UNCACHE))
  {
    return bp;
  }

  /* The block we need is not in a buffer, we must make a buffer  */
  /* available, and fill it with the desired block                */

  /* take the buffer that lbp points to and flush it, then read new block. */
  if (!flush1(bp))
    return NULL;

  /* Fill the indicated disk buffer with the current track and sector */

  if (!overwrite && dskxfer(dsk, blkno, bp->b_buffer, 1, DSKREAD))
  {
    return NULL;
  }

  bp->b_flag = BFR_VALID | BFR_DATA;
  bp->b_unit = dsk;
  bp->b_blkno = blkno;

  return bp;
}

/*                                                                      */
/*      Mark all buffers for a disk as not valid                        */
/*                                                                      */
VOID setinvld(REG COUNT dsk)
{
  struct buffer FAR *bp = firstbuf;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -