📄 diskio.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel / Standard Extension * * Copyright (C) 2006 by Ken Sakamura. All rights reserved. * T-Kernel / Standard Extension is distributed * under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * * Version: 1.00.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* * diskio.c (file) * * File management * Disk I/O related */#include "diskio.h"LOCAL void fmpDiskErrorHandler( DiskErrInfo *info );LOCAL VP fmpMapPhyBlks( PhyBlk padr[], MapClass mapc, MapModeClr clear, ID_ERR *mid, FsInfo *fsinfo );LOCAL VP fmcMapPhyBlks( PhyBlk padr[], DiskMapInfo *dmInfo, ID_ERR *mid );LOCAL VP fmcMapLogBlk( UW lblk, W sblk, DiskMapInfo *dmInfo, ID_ERR *mid );LOCAL ER fmcScanFileSystemHeader( DiskMapInfo *dmInfo, PhyBlk pblk[2] );#define TSD_DIO_BLK_2 2#define TSD_FMB_VAL_M1 (-1)#define TSD_FCD_SFT_MC1 ((UW)BIGENDIAN << 16)#define TSD_FCD_SFT_MC2 (((UW)BIGENDIAN ^ 1) << 16)/* * Disk exception handler */LOCAL void fmpDiskErrorHandler( DiskErrInfo *info ){ MapClass mapc; FsInfo *fsinfo; mapc = (MapClass)info->mode.info; fsinfo = GetFsInfo(info->taskid); if ( (mapc == MAP_SYNC) || (mapc == MAP_ASYN) ) { /* Error occurred in common section */ if ( fsinfo != NULL ) { fsinfo->dskErr = info->err; } } else if ( mapc == MAP_FSTSK ) { /* Error occurred in individual mapping section */ if ( fsinfo != NULL ) { fsinfo->dskErr = info->err; } } else { /* Error occurred in file individual section */ ((OFCB*)mapc)->dskErr = info->err; }}/* * Register/Deregister the disk exception handler. * init = TRUE Register * FALSE Deregister */EXPORT ER fmpDefineDiskErrorHandler( BOOL init ){ ER err; FP errhdr = ( init != 0 )? fmpDiskErrorHandler: NULL; err = NotifyDiskErr(errhdr); if ( err < E_OK ) { DEBUG_PRINT(("fmpDefineDiskErrorHandler err = %d\n", err)); return err; } return E_OK;}/* * Check an exception occurrence. * ofcb == NULL Check only the error occurred in common section. * ofcb != NULL Check also the error occurred in individual section (File of ofcb). */EXPORT ER fmpCheckDiskError( OFCB *ofcb, FsInfo *fsinfo ){ UW psw; ER err, error = E_OK; /*** Take note that it must work exclusively with the exception handler. ***/ if ( ofcb != NULL ) { DI(psw); err = ofcb->dskErr; ofcb->dskErr = E_OK; EI(psw); if ( err < E_OK ) { error = err; } } DI(psw); err = fsinfo->dskErr; fsinfo->dskErr = E_OK; EI(psw); if ( err < E_OK ) { error = err; } return error;}/* * Error reset * Clear when the recorded error is the same as err. */EXPORT void fmpResetDiskError( ER err, MapClass mapc, FsInfo *fsinfo ){ UW psw; /*** Take note that it must work exclusively with the exception handler. ***/ if ( (mapc == MAP_SYNC) || (mapc == MAP_ASYN) || (mapc == MAP_FSTSK) ) { DI(psw); if ( fsinfo->dskErr == err ) { fsinfo->dskErr = E_OK; } EI(psw); } else { DI(psw); if ( ((OFCB*)mapc)->dskErr == err ) { ((OFCB*)mapc)->dskErr = E_OK; } EI(psw); }}/* ----------------------------------------------------------------------- *//* * Disk mapping * Map the non-contiguous physical block (PkyBlk[]) of the disk * to a contiguous address space, and return the first address. */LOCAL VP fmpMapPhyBlks( PhyBlk padr[], MapClass mapc, MapModeClr clear, ID_ERR *mid, FsInfo *fsinfo ){ MapMode mode = DefaultMapMode; ER err; mode.info = (VW)mapc; mode.clear = clear; *mid = err = MapDisk(fsinfo->dskid, padr, &mode); if ( err < E_OK ) { fmpResetDiskError(err, mapc, fsinfo); if ( err == E_TMOUT ) { *mid = E_SYSMEM; } DEBUG_PRINT(("fmpMapPhyBlks err = %d\n", err)); return NULL; } return mode.addr;}/* * Disk mapping * Map the size bytes from the byte address (DskAdrS) of the disk, * and return the first address. */EXPORT VP fmpMapDskAdrS( DskAdrS dadr, W size, MapClass mapc, ID_ERR *mid, FsInfo *fsinfo ){ PhyBlk blks[TSD_DIO_BLK_2]; UW start, end; /* Physical block number */ UW offset; /* Offset in the block */ VB *adr; start = (UW)dadr / (UW)fsinfo->dskInfo.blocksize; offset = (UW)dadr % (UW)fsinfo->dskInfo.blocksize; end = ((UW)dadr + (UW)size - 1U) / (UW)fsinfo->dskInfo.blocksize; blks[0].blk = start + (UW)fsinfo->pbadj; blks[0].len = end - start + 1U; blks[1].len = 0; adr = fmpMapPhyBlks(blks, mapc, MapNoClr, mid, fsinfo); if ( adr == NULL ) { return NULL; } return (VP)(adr + offset);}/* * Disk mapping * Map the size bytes from the disk address (DskAdr), * and return the first address. */EXPORT VP fmpMapDskAdr( DskAdr dadr, W size, MapClass mapc, ID_ERR *mid, FsInfo *fsinfo ){ PhyBlk blks[TSD_DIO_BLK_2]; UW start, end; /* Physical block number */ UW offset; /* Offset in the block */ VB *adr; start = end = dadr.lblk * fsinfo->blkRatio; start += (UW)dadr.offset / (UW)fsinfo->dskInfo.blocksize; offset = (UW)dadr.offset % (UW)fsinfo->dskInfo.blocksize; end += ((UW)dadr.offset + (UW)size - 1U) / (UW)fsinfo->dskInfo.blocksize; blks[0].blk = start + (UW)fsinfo->pbadj; blks[0].len = end - start + 1U; blks[1].len = 0; adr = fmpMapPhyBlks(blks, mapc, MapNoClr, mid, fsinfo); if ( adr == NULL ) { return NULL; } return (VP)(adr + offset);}/* * Disk mapping * Map the one logical block of the disk, and return the first address. */EXPORT VP fmpMapLogBlk( UW lblk, MapClass mapc, ID_ERR *mid, FsInfo *fsinfo ){ PhyBlk blks[TSD_DIO_BLK_2]; blks[0].blk = (lblk * fsinfo->blkRatio) + (UW)fsinfo->pbadj; blks[0].len = fsinfo->blkRatio; blks[1].len = 0; return fmpMapPhyBlks(blks, mapc, MapNoClr, mid, fsinfo);}/* * Disk mapping with clear specification. * Map the one logical block of the disk, and return the first address. */EXPORT VP fmpMapLogBlkC( UW lblk, MapClass mapc, MapModeClr clear, ID_ERR *mid, FsInfo *fsinfo ){ PhyBlk blks[TSD_DIO_BLK_2]; blks[0].blk = (lblk * fsinfo->blkRatio) + (UW)fsinfo->pbadj; blks[0].len = fsinfo->blkRatio; blks[1].len = 0; return fmpMapPhyBlks(blks, mapc, clear, mid, fsinfo);}/* * Disk mapping * Map the disk block according to the logical block list (LBlks), * and return the first address. */EXPORT VP fmpMapLogBlks( LBlks *lb, MapClass mapc, MapModeClr clear, ID_ERR *mid, FsInfo *fsinfo ){ PhyBlk *blks, *p; LogBlk *lblk; W nlblk; W prev; VP mapadr; W blkRatio = (W)fsinfo->blkRatio; ER err; /* The number of entries of the logical block. */ nlblk = fmpNLBlks(lb); if ( nlblk <= 0 ) { err = E_SYS; goto err_ret; } /* Reserve the storing area of the physical block list. */ blks = (PhyBlk*)Kmalloc(((UW)nlblk + 1U) * sizeof(PhyBlk)); if ( blks == NULL ) { err = E_SYSMEM; goto err_ret; } /* Convert the logical block list into physical block list. */ p = blks; lblk = NULL; prev = TSD_FMB_VAL_M1; while ( fmNextLBlks(lb, &lblk) != 0 ) { if ( lblk->adr == prev ) { /* It is continued from the previous block. */ (p - 1)->len += (UW)lblk->cnt * (UW)blkRatio; } else { p->blk = (UW)((lblk->adr * blkRatio) + fsinfo->pbadj); p->len = (UW)lblk->cnt * (UW)blkRatio; p++; } prev = lblk->adr + lblk->cnt; } p->len = 0; /* Mapping */ mapadr = fmpMapPhyBlks(blks, mapc, clear, mid, fsinfo); Kfree((VB*)blks); return mapadr;err_ret: DEBUG_PRINT(("fmpMapLogBlks err = %d\n", err)); *mid = err; return NULL;}/* * Synchronize the cache in file. * Write the unwritten data of the map class specified in mapc to the disk. */EXPORT ER fmpSyncFile( MapClass mapc, FsInfo *fsinfo ){ OFCB *ofcb; (void)SyncFS(fsinfo->dskid, (VW)mapc); if ( (mapc == MAP_SYNC) || (mapc == MAP_ASYN) || (mapc == MAP_FSTSK) ) { ofcb = NULL; } else { ofcb = (OFCB*)mapc; } return fmpCheckDiskError(ofcb, fsinfo);}/* ----------------------------------------------------------------------- *//* * Map the specified elements of the file ID table. */EXPORT DfFileID* fmpMapFileID( FID fid, ID_ERR *mid, FsInfo *fsinfo ){ DfFileID *fidt = (DfFileID*)fsinfo->fidt; VP mapadr; if ( fid >= fsinfo->nfmax ) { /* Abnormal file ID */ *mid = E_NOEXS; return NULL; } mapadr = fmpMapDskAdrS(&fidt[fid], sizeof(DfFileID), MAP_SYS(fsinfo), mid, fsinfo); return (DfFileID*)mapadr;}/* * Map the file header. */EXPORT DfFileHeaderBlock* fmpMapFileHeader( FID fid, DskAdr *da, ID_ERR *mid, FsInfo *fsinfo ){ DfFileID *fidt, f; DskAdr fhd; VP mapadr; /* Map the file ID. */ fidt = fmpMapFileID(fid, mid, fsinfo); if ( fidt == NULL ) { goto err_ret; } if ( fidt->w == 0U ) { /* Unused entry (No file) */ fmpUnmapDisk(*mid, MD_RDONLY); *mid = E_NOEXS; goto err_ret; } /* Location of the file header */ f = fmpConvEndianFileID(*fidt, fsinfo); fhd = fmpLBlkToDAdr(f.s.blkadr, fsinfo); if ( da != NULL ) { *da = fhd; } fmpUnmapDisk(*mid, MD_RDONLY); *mid = fmpCheckDiskError(NULL, fsinfo); if ( *mid < E_OK ) { goto err_ret; } /* Map the file header. */ mapadr = fmpMapDskAdr(fhd, sizeof(DfFileHeaderBlock),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -