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

📄 lowl.c

📁 nucleus 文件系统,内核和彩色图形系统,在小系统上非常好用
💻 C
📖 第 1 页 / 共 4 页
字号:
 Description
    Given a DDRIVE and a cluster number. Get the value in the fat at clusterno
    (the next cluster in a chain.) Handle 16 and 12 bit fats correctly.

 Returns
    Returns the the value at clno. In pvalue. 
    If any error occured while FAT swapping return NO else return YES.
    Note: If fat buffering is disabled, always returns yes
***************************************************************************/
 
/* Retrieve a value from the fat */
BOOL pc_faxx(DDRIVE *pdr, UCOUNT clno, UCOUNT *pvalue)               /*__fn__*/
{
    UCOUNT  wtry;
    ULONG   ltry;
    UCOUNT  result;
    UTINY   wrdbuf[2];          /* Temp storage area */
    UTINY   FAR *fat_data = pdr->fat_swap_structure.data_array;

    if (pdr->fasize == 3)       /* 3 nibble ? */
    {
        wtry = (UCOUNT) (clno + (UCOUNT) (clno >> 1));    /* multiply by 1.5 */

           /* And use the product as index */
        wrdbuf[0] = fat_data[wtry];     /* Use a temp variable since in */
        wrdbuf[1] = fat_data[wtry+1];   /* small model we can't call with
                                           fat_data (it's a far pointer) */
        result = to_WORD(wrdbuf);   /* And use the product as index */

        if ( ((clno << 1) + clno) == (wtry << 1) )  /* If whole number */
            result &= 0xfff;            /* Return it */
        else
            result =(UCOUNT) ((UCOUNT) (result >> 4) & 0xfff ); /* shift right 4 */
    }
    else    /* 16 BIT fat. ret the value at 2 * clno */
    {
        if (pdr->use_fatbuf)
        {
            if ( pc_pfgword( pdr, clno, (UCOUNT *) &wrdbuf[0] ))
                result = to_WORD(&wrdbuf[0]);   /* And use the product as index */
            else
                return (NO);
        }
        else
        {
            ltry = (ULONG) clno;
            ltry <<= 1;
            wrdbuf[0] = fat_data[ltry];     /* Use a temp variable since in */
            wrdbuf[1] = fat_data[ltry+1];   /* intel small model we can't call
                                               with  fat_data (it's a far pointer) */
            result = to_WORD(wrdbuf);   /* And use the product as index */
        }
    }

    *pvalue = result;
    return (YES);
}

/****************************************************************************
    PC_FLUSHFAT -  Write any dirty FAT blocks to disk

 Description
    Given a valid drive number. Write any fat blocks to disk that
    have been modified. Updates all copies of the fat.

 Returns
    Returns NO if driveno is not an open drive. Or a write failed.

****************************************************************************/

/* Consult the dirty fat block list and write any. write all copies
   of the fat */
BOOL pc_flushfat(COUNT driveno)                                      /*__fn__*/
{
    UTINY FAR *pf;
    UTINY *pd;
    UCOUNT i;
    UCOUNT j;
    BLOCKT baseblock;
    DDRIVE *pdr;
    BOOL is_last;

    pdr = pc_drno2dr(driveno);

    if (!pdr)
    {
        return(NO);
    }

    if (!pdr->fat_is_dirty)
        return(YES);

    if (pdr->use_fatbuf)
    {
        if (pc_pfflush(pdr) )
        {
            pdr->fat_is_dirty = NO;
            return(YES);
        }
        else
            return(NO);
    }

    /* else ... */
    PC_DRIVE_IO_ENTER(pdr->driveno)
    for (j = 0; j < pdr->numfats;j++)
    {
        baseblock = (BLOCKT) j;
        baseblock *= pdr->secpfat;
        baseblock += pdr->fatblock;

        if (j == (UCOUNT) (pdr->numfats - 1) )
            is_last = YES;
        else
            is_last = NO;

        /* NOTE: data_array is the fat data. data_map is a byte map of dirty
           fat blocks                                                       */
        pf = pdr->fat_swap_structure.data_array;
        pd = pdr->fat_swap_structure.data_map;
        if (!pf)
        {
            PC_DRIVE_IO_EXIT(pdr->driveno)
            pc_report_error(PCERR_FAT_NULLP);
            return (NO);
        }

        /* Check each block in the fat */
        for (i = 0; i < pdr->secpfat; i++,pd++,baseblock++)
        {
            /* If the block is dirty */
            if (*pd)
            {
                /* Write it */
                if(!pc_bdevsw[pdr->driveno].io_proc(pdr->driveno,baseblock,pf,1,NO))
                {
                    PC_DRIVE_IO_EXIT(pdr->driveno)
                    pc_report_error(PCERR_FAT_FLUSH);
                    return(NO);
                }
                if (is_last)
                    *pd = (UTINY) 0;
            }
            pf += 512;
        }
    }
    pdr->fat_is_dirty = NO;
    PC_DRIVE_IO_EXIT(pdr->driveno)
    return (YES);
}

/****************************************************************************
    PC_FREECHAIN - Free a cluster chain associated with an inode.

 Description
    Trace the cluster chain starting at cluster and return all the clusters to
    the free state for re-use. The FAT is not flushed.

 Returns
    Nothing.

****************************************************************************/

VOID pc_freechain(DDRIVE *pdr, UCOUNT cluster)                        /*__fn__*/
{
    UCOUNT nextcluster;
    
    nextcluster = pc_clnext(pdr , cluster);

    while (cluster)
    {
        pc_clrelease(pdr , cluster);
        cluster = nextcluster;
        nextcluster = pc_clnext(pdr , nextcluster);
    }
}

/******************************************************************************
    PC_GET_CHAIN  -  Return as many contiguous clusters as possible.


 Description
        Starting at start_cluster return the number of contiguous clusters
        allocated in the chain containing start_cluster or n_clusters,
        whichever is less.
    
 Returns
    Returns the number of contiguous clusters found. Or zero on an error.
    This function should always return at least one. (start_cluster). Unless
    an error occurs.

    The word at *pnext_cluster is filled with on of the following:
       . If we went beyond a contiguous section it contains
         the first cluster in the next segment of the chain.
       . If we are still in a section it contains
         the next cluster in the current segment of the chain.
       . If we are at the end of the chain it contains the last cluster 
         in the chain.

****************************************************************************/
 
UCOUNT pc_get_chain(DDRIVE *pdr, UCOUNT start_cluster, UCOUNT *pnext_cluster, UCOUNT n_clusters) /*__fn__*/
{
    UCOUNT clno;
    UCOUNT n_contig;
    UCOUNT value;
    COUNT  nibs_per_entry;

    if (start_cluster < 2)
        return (0);
    if (start_cluster > pdr->maxfindex)
        return (0);
    nibs_per_entry = pdr->fasize;

    clno = start_cluster;
    n_contig = 1;
    *pnext_cluster = 0;        
 
    /* Get each FAT entry. If its value points to the next contiguous entry
       continue. Otherwise we have reached the end of the contiguous chain.
       At which point we return the number of contig's found and by reference
       the address of the FAT entry beginning the next chain segment.
    */

    while(YES)
    {
        if (!pc_faxx(pdr, clno, &value))
           return(0);
            /* check for a bad cluster and skip it if we see it */
        if ( ( value == 0xff7 && nibs_per_entry == 3)
             || (value == 0xfff7 && nibs_per_entry == 4) )
        {
            clno += 1;
        }
            /* check for end markers set next cluster to the last 
               cluster in the chain if we are at the end */
        else if ( ( value > 0xff7 && nibs_per_entry == 3)
             || (value > 0xfff7 && nibs_per_entry == 4) )
        {
            value = clno;
            break;
        }
        else if (value == ++clno)
        {
            if (n_contig >= n_clusters)
               break;
            n_contig++;
        }
        else
            break;
   }
   *pnext_cluster = value;
   return (n_contig);
}

/******************************************************************************
    PC_PFAXX - Write a value to the FAT at clno.
  
 Description
    Given a DDRIVE,cluster number and value. Write the value in the fat
    at clusterno. Handle 16 and 12 bit fats correctly.

 Returns
    No if an io error occurred during fat swapping, else YES.

*****************************************************************************/
 
/* Given a clno & fatval Put the value in the table at the index (clno)  */
BOOL pc_pfaxx(DDRIVE   *pdr, UCOUNT  clno, UCOUNT  value)             /*__fn__*/
{
    UCOUNT  wtry;
    ULONG   ltry;
    UTINY   wrdbuf[2];          /* Temp storage area */
    UTINY   FAR *fat_data = pdr->fat_swap_structure.data_array;

    pdr->fat_is_dirty = YES;
    if (!pdr->use_fatbuf)
    {
    /* Using the in-memory FAT Buffers */
        if (pdr->fasize == 3)       /* 3 nibble ? */
        {
            value &= 0x0fff;        /* 3 nibble clusters */
            wtry = (UCOUNT) (clno + (UCOUNT) (clno >> 1)); /* multiply by 1.5 */
            if ( ((clno << 1) + clno) == (wtry << 1) )  /* If whole number */
            {
                fat_data[wtry] = (UTINY)((UTINY)value & 0xff); /* Low Byte to NIBBLE 1 & 2 */
                fat_data[wtry+1] &= 0xf0; /* clr low NIBBLE of next byte */
                /* Put the high nibble of value in the low nibble ofnext byte */
                fat_data[wtry+1] |= ( ((UTINY)(value>>8)) & 0x0f );
            }
            else
            {
                fat_data[wtry+1]= (UTINY)((UTINY)(value>>4) & 0xff); /* high to NIB 2 & 3*/
                fat_data[wtry] &= 0x0f; /* clr high NIBBLE of byte */
                /* Put the low nibble of value in the high nibble of byte */
                fat_data[wtry] |= ( ((UTINY)(value & 0xf) << 4) & 0xf0 );
            }
            /* Now mark the dirty flags block == index/512 */
            /* Note try>>9 and try+1 >> 9 are usually the same */
            /* NOTE: data_map is a byte map of dirty fat blocks */
            pdr->fat_swap_structure.data_map[(wtry>>9)]  = (UTINY) 1;
            pdr->fat_swap_structure.data_map[(wtry+1)>>9] = (UTINY) 1;
        }
        else        /* 16 BIT entries */
        {
            /* Byte offset in fat ==s cluster number * 2 */
            ltry = (ULONG) clno;
            ltry <<= 1;
            /* Use temp buffer since fat_data is far , can't call fr word with
               it directly in intel small model */
            fr_WORD(&wrdbuf[0],value);
            fat_data[ltry] = wrdbuf[0];
            fat_data[ltry+1] = wrdbuf[1];
            /* Now mark the dirty flags block == index/512 */
            /* NOTE: data_map is a byte map of dirty fat blocks */
            pdr->fat_swap_structure.data_map[(ltry>>9)]  = (UTINY) 1;
        }
    }
    else
    {
        /* fat swapping. Always 16 bit entries */
        fr_WORD(&wrdbuf[0],value);
        /* Now put the values back into the FAT */
        if (!pc_pfpword( pdr, clno, (UCOUNT *) &wrdbuf[0] ))
        {
            return (NO);
        }
    }
    return (YES);
}



/***************************************************************************
    PC_FATSW - FAT Access code when fat buffering is enabled.
Summary

    Free all core associated with the drive's fat
        VOID pc_pfclose( DDRIVE *pdr);

    Flush the current page (if needed. And read in a new page such that
    "index" is contained therein. (Called by pc_pfpbyte() and pc_pfgbyte())
        BOOL pc_pfswap( DDRIVE *pdr, UCOUNT index);

    Put a byte (value) into the FAT at index. Return YES if everything worked. 
    Note: FAT page swaps will occur if they are needed. Called by pc_pfaxx().

⌨️ 快捷键说明

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