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

📄 lowl.c

📁 nucleus 文件系统,内核和彩色图形系统,在小系统上非常好用
💻 C
📖 第 1 页 / 共 4 页
字号:
        BOOL pc_pfpbyte( DDRIVE *pdr, COUNT index, UCOUNT *pvalue);

    Get a byte from the FAT at index and put the value at *value. Return YES if
    everything worked.
    Note: FAT page swaps will occur if they are needed. Called by pc_faxx().
        BOOL pc_pfgbyte( DDRIVE *pdr, COUNT index, UCOUNT *value);

    Flush any dirty blocks from the current FAT page. Called by pc_flushfat()
        BOOL pc_pfflush( DDRIVE *pdr);

Description
    Provide a cacheing mechanism for the file allocation table. We have a 
    byte map table indicating the offset in our data cache for each block
    in the FAT. If the value at dat_map[block] is zero the block is not 
    cached. We also maintain a bitmap of each block in the FAT. If the 
    bit is set the corresponding block must be flushed.

Returns

Example
****************************************************************************/

    
/* Flush buffers and then swap in the page containing index */            
/* Note: This routine must be called first with index == 0. see pc_dskinit */
UTINY FAR *pc_pfswap(DDRIVE *pdr, UCOUNT index, BOOL for_write)          /*__fn__*/
{
    FATSWAP *pfs = &pdr->fat_swap_structure;
    BLOCKT newblock;
    UCOUNT block_offset_in_fat;
    UCOUNT i;
    UTINY FAR *pdata;
    UTINY uc;
    UCOUNT byte_offset;
    UCOUNT bit_offset;
    UCOUNT data_block_to_use;
    ULONG ltemp;
    
    /* Convert the index (in words) to block values 
       divide by 256 since there are 256 FAT entries per block */
    block_offset_in_fat = (UCOUNT) (index >> 8);

    if (block_offset_in_fat >= pdr->secpfat) /* Check range */
        return (NULL);

    /* check if the block is already mapped. 
           Notice we use block_0_is_valid as a flag denoting whether
           the first block in the fat is buffered. We did this because
           we want to use:
                data_map[block_offset_in_fat] == 0;
           Where data_map[] indicates the offset into our cache memory
           (in blocks) of the the cached buffer.  
           To indicate that the disk block is not cached. Since offset 0
           is a valid number we chose to preload the first disk block in the
           fat to location 0 in our buffer cache. After this has occured we
           set block_0_is_valid. Yuk, but effective.. 
    */

    if ( ((block_offset_in_fat == 0) && pfs->block_0_is_valid) || 
         (pfs->data_map[block_offset_in_fat] != 0) )
    {
        /* Already in our cache. set up a pointer to it */
        data_block_to_use = pfs->data_map[block_offset_in_fat];
        ltemp = (ULONG) data_block_to_use;
        pdata = pfs->data_array + (ltemp << 9);
    }
    else
    {
        /* Not mapped, we have to read it in */
        if (pfs->n_blocks_used != pfs->n_blocks_total)
        {
        /* If we haven't reached steady state: use core until we 
           get there. */
            data_block_to_use = pfs->n_blocks_used;
            pfs->n_blocks_used += 1;
        }
        else
        {
            /* Flush the buffer
                Later make this more selective by only flushing the block we
                are swapping */
            if (!pc_pfflush(pdr))
                return(NULL);

            /* Select the block to swap out. Use a simple round-robin
               selection algorithm: pfs->n_to_swap is the current 
               target for swapping (block 0 is never swapped out)  */        
            if (!pfs->n_to_swap)
                pfs->n_to_swap += 1;
            if (pfs->n_to_swap >= pdr->secpfat)
                pfs->n_to_swap = 1;
            data_block_to_use = 0;
            while (data_block_to_use == 0)
            {
                for (i = pfs->n_to_swap; i < pdr->secpfat; i++)
                {
                   if (pfs->data_map[i])
                   {
                        /* swap this one out */
                       data_block_to_use = pfs->data_map[i];
                       pfs->data_map[i] = 0;
                       pfs->n_to_swap =(UCOUNT)(i+1);
                       break;
                   }
                }
                if (!data_block_to_use)
                    pfs->n_to_swap = 1;     /* Start at the beginining */
            }
        }       /* END IF we had to swap */

        /* Whether we are reusing a block or still coming up to speed.
           if the block is not currently in our pool we must mark the
           data block used and read it in */
        pfs->data_map[block_offset_in_fat] = (UTINY) data_block_to_use;
        newblock = pdr->fatblock + block_offset_in_fat;
        ltemp = (ULONG) data_block_to_use;
        pdata = pfs->data_array + (ltemp << 9);
        /* READ */
        PC_DRIVE_IO_ENTER(pdr->driveno)
        if (!pc_bdevsw[pdr->driveno].io_proc(pdr->driveno,newblock,pdata,1,YES))
        {
            pfs->data_map[block_offset_in_fat] = 0;
            PC_DRIVE_IO_EXIT(pdr->driveno)
            return(NULL);
        }
        pfs->block_0_is_valid = 1;
        PC_DRIVE_IO_EXIT(pdr->driveno)
    }        /* END IF the data needed reading in */

    /* If we should mark it dirty do so in the bit map */
    if (for_write)
    {
        byte_offset = (UCOUNT) (block_offset_in_fat >> 3);    /* divide by 8 */
        bit_offset = (UCOUNT) (block_offset_in_fat & 0x7);    /* mod 8 */
        uc = 1;
        uc <<= bit_offset;
        pfs->pdirty[byte_offset] |= uc;
    }
    return(pdata);
}

/* Put a WORD value into the fat at index  */            
BOOL pc_pfpword(DDRIVE *pdr, UCOUNT index, UCOUNT *pvalue)          /*__fn__*/
{
    UCOUNT FAR *ppage;
    UCOUNT offset;    
    /* Make sure we have access to the page. Mark it for writing */
    ppage = (UCOUNT FAR *)pc_pfswap(pdr,index,YES);

    if (!ppage)
        return(NO);
    else
    {
        /* there are 256 entries per page */
        offset = (UCOUNT) (index & 0xff);
        ppage[offset] = *pvalue;
    }
    return(YES);
}

/* Get a WORD value from the fat at index  */            
BOOL pc_pfgword(DDRIVE *pdr, UCOUNT index, UCOUNT *value)          /*__fn__*/
{
    UCOUNT FAR *ppage;
    UCOUNT offset;    
    /* Make sure we have access to the page. Don't Mark it for writing */
    ppage = (UCOUNT FAR *)pc_pfswap(pdr,index,NO);

    if (!ppage)
        return(NO);
    else
    {
        /* there are 256 entries per page */
        offset = (UCOUNT) (index & 0xff);
        *value = ppage[offset];
    }
    return(YES);
}

/* Consult the dirty fat block list and write any. write all copies
   of the fat */
BOOL pc_pfflush(DDRIVE *pdr)                                          /*__fn__*/
{
    FATSWAP *pfs = &pdr->fat_swap_structure;
    UTINY FAR *pdata;
    COUNT i;
    UCOUNT j;
    UTINY uc;
    UTINY bit_in_array;
    UCOUNT offset_div_8;    
    BLOCKT blockno;
    UCOUNT offset_in_block_map;
    ULONG  data_offset;
    ULONG  baseblock;                   /* BUG FIX */

    PC_DRIVE_IO_ENTER(pdr->driveno)
    for (j = 0; j < pdr->numfats;j++)
    {
        baseblock = (ULONG) j;          /* BUG FIX */
        baseblock *= pdr->secpfat;      /* BUG FIX */
        baseblock += pdr->fatblock;     /* BUG FIX */

        for (offset_div_8 = 0,i = 0; i < 32; i++,offset_div_8 += 8)
        {
            uc = pfs->pdirty[i];
            bit_in_array = 0;
            while (uc)
            {
                if (uc & 0x01)          /* If bit is dirty. */
                {
                    /* add (by oring) the byte index and the bit index
                       to get the block offset in the fat */
                    offset_in_block_map = (UCOUNT)(offset_div_8 | bit_in_array); 
                    /* map the offset to data through our map */
                    data_offset = (ULONG) pfs->data_map[offset_in_block_map];
                    /* Convert block offset to byte offset */
                    data_offset <<= 9;
                    /* Get its address in our data array */
                    pdata = pfs->data_array + data_offset;
                    /* Convert offset in fat to logical disk block */
                    blockno = baseblock + offset_in_block_map;     /* BUG FIX */
                    /* WRITE IT */
                    if(!pc_bdevsw[pdr->driveno].io_proc(pdr->driveno,blockno,pdata,1,NO))
                    {
                         pc_report_error(PCERR_FAT_FLUSH);
                         PC_DRIVE_IO_EXIT(pdr->driveno)
                         return(NO);
                     }
                }
                uc >>= 1;
                bit_in_array++;
            }            
        }
    }
    /* Clear the dirty map */
    pc_memfill(pfs->pdirty, 32, (UTINY) 0);
    PC_DRIVE_IO_EXIT(pdr->driveno)
    return (YES);
}


/****************************************************************************
    PC_GBLK0 -  Read block 0 and load values into a a structure

 Description
    Given a valid drive number, read block zero and convert
    its contents from intel to native byte order.

 Returns
    Returns YES if all went well.

****************************************************************************/
 
/* read block zero */
BOOL pc_gblk0(UCOUNT driveno, struct pcblk0 *pbl0)                  /*__fn__*/
{
    UTINY b[512];

    /* get 1 block starting at 0 from driveno */
   /* READ */
    PC_DRIVE_IO_ENTER(driveno)
    if (!pc_bdevsw[driveno].io_proc(driveno, 0L ,&b[0],1,YES))
    {
        PC_DRIVE_IO_EXIT(driveno)
        return(NO);
    }
    PC_DRIVE_IO_EXIT(driveno)

    /* Now load the structure from the buffer */
    pbl0->jump = b[0];
    copybuff( &pbl0->oemname[0],&b[3],8);
    pbl0->oemname[8] = '\0';
    pbl0->bytspsector = to_WORD(&b[0xb]);
    pbl0->secpalloc = b[0xd];
    pbl0->secreserved = to_WORD(&b[0xe]);
    pbl0->numfats = b[0x10];
    pbl0->numroot = to_WORD(&b[0x11]);
    pbl0->numsecs = to_WORD(&b[0x13]);
    pbl0->mediadesc = b[0x15];
    pbl0->secpfat = to_WORD(&b[0x16]);
    pbl0->secptrk = to_WORD(&b[0x18]);
    pbl0->numhead = to_WORD(&b[0x1a]);
    pbl0->numhide = to_WORD(&b[0x1c]);
    pbl0->numhide2 = to_WORD(&b[0x1e]);
    pbl0->numsecs2 = to_DWORD(&b[0x20]); /* # secs if > 32M (4.0) */
    pbl0->physdrv = b[0x24];            /* Physical Drive No. (4.0) */
    pbl0->filler = b[0x25];             /* Reserved (4.0) */
    pbl0->xtbootsig = b[0x26];      /* Extended signt 29H if 4.0 stuf valid */
    pbl0->volid = to_DWORD(&b[0x27]);   /* Unique number per volume (4.0) */
    copybuff( &pbl0->vollabel[0],&b[0x2b],11); /* Volume label (4.0) */

/*
*        printf ("Jump      %d\n",pbl0->jump);
*        printf ("Oem NAME  %s\n",pbl0->oemname);
*        printf ("Bytspsec  %d\n",pbl0->bytspsector);
*        printf ("secpallc  %d\n",pbl0->secpalloc);
*        printf ("secres    %d\n",pbl0->secreserved);
*        printf ("numfat    %d\n",pbl0->numfats);
*        printf ("numrot    %d\n",pbl0->numroot);
*        printf ("numsec    %d\n",pbl0->numsecs);
*        printf ("mediac    %d\n",pbl0->mediadesc);
*        printf ("secfat    %d\n",pbl0->secpfat);
*        printf ("sectrk    %d\n",pbl0->secptrk);
*        printf ("numhed    %d\n",pbl0->numhead);
*        printf ("numhide   %d\n",pbl0->numhide);
*/

    return(YES);
}



/***************************************************************************
    PC_CLZERO -  Fill a disk cluster with zeroes
      
 Description
    Write zeroes into the cluster at clusterno on the drive pointed to by 
    pdrive. Used to zero out directory and data file clusters to eliminate
    any residual data.

 Returns
    Returns NO on a write erro.

****************************************************************************/
 
/* Write zeros to all blocks in a cluster */
BOOL pc_clzero(DDRIVE *pdrive, UCOUNT cluster)                  /*__fn__*/
{
    BLKBUFF *pbuff;
    UCOUNT i;
    BLOCKT currbl;

    currbl = pc_cl2sector(pdrive , cluster);
    if (!currbl)
        return (NO);
    /*Init and write a block for each block in cl. Note: init clears the core*/
    for (i = 0; i < pdrive->secpalloc; i++, currbl++ )
    {
        pbuff = pc_init_blk( pdrive , currbl);
        if (!pbuff)
        {
            return (NO);
        }
        if ( !pc_write_blk ( pbuff ) )
        {
            pc_free_buf(pbuff,YES);

⌨️ 快捷键说明

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